对于指针,我对使用char**或char*或*array [n]等的声明和函数参数感到困惑.就像函数采用(*array [n])参数一样,我是否通过它是**型?
我尝试使用右 - 左规则并知道p将是指向char(char**p)的指针,而p是n个指针的数组(*p [n]),但有人说*p [n]和**p基本相同.真的吗?
在正确的上下文(即函数的参数)中,以下声明是等效的:
int main(int argc, char *argv[]);
int main(int argc, char **argv);
int main(int argc, char *argv[12]); // Very aconventional!
Run Code Online (Sandbox Code Playgroud)
类似的注释适用于函数定义(在括号中用块括起来代替分号).
在任何其他情况下,符号之间存在重要差异.例如:
extern char *list1[];
extern char **list2;
extern char *list3[12];
Run Code Online (Sandbox Code Playgroud)
第一个说某个地方有一个包含'char*'值的不确定大小的数组.第二个说某处 - 可能在这里 - 有一个值包含指向char指针的指针.第三个说某个地方 - 可能在这里 - 有一个由12个字符指针组成的数组.
但是,所有三个列表都可以以相同的方式引用 - 假设它们实际上已经被定义和初始化.
list1[0][0] = '1';
list2[0][0] = '2';
list3[0][0] = '3';
Run Code Online (Sandbox Code Playgroud)
此外,如果它们被传递到这样的函数:
function(list1, list2, list3);
Run Code Online (Sandbox Code Playgroud)
然后该函数可以声明为:
void function(char **list1, char **list2, char **list3);
Run Code Online (Sandbox Code Playgroud)
数组(list1,list3)从数组衰减到指向数组第一个元素的指针; 当然,list2已经是指向指针的指针.
在一个函数中需要注意的一个细节,例如:
void otherfunction(char *list[12])
{
...
}
Run Code Online (Sandbox Code Playgroud)
C编译器不会将该声明与以下内容区别对待:
void otherfunction(char **list)
{
...
}
Run Code Online (Sandbox Code Playgroud)
要么
void otherfunction(char *list[])
{
...
}
Run Code Online (Sandbox Code Playgroud)
特别是,它没有数组边界检查,就函数而言,12也可能不存在.
C99引入了VLA(可变长度数组)类型,并在数组边界中引入了带有"static"和大小的符号.您需要阅读标准才能完全理解这些标准.
在下面的函数中可以说数组的大小很重要,并且在运行时确定.通常使用二维数组,除了第一个之外的所有维度都需要指定.
void vla_function(size_t m, int vla[m][m]);
Run Code Online (Sandbox Code Playgroud)
引用标准(第6.7.5.3节):
void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);
void f(double a[restrict static 3][5]);
Run Code Online (Sandbox Code Playgroud)
(注意,最后一个声明还指定在对f的任何调用中对应于a的参数必须是指向至少三个5个双精度数组中的第一个的非空指针,而其他数组则不是.)
读取C声明符(这是带有*和[]的变量的一部分)相当细微.有一些网站提示:
A char**是指向(可能是多个)指针(可能是多个)指针的指针.例如,它可能是指向字符串指针的指针,也可能是指向字符串指针数组的指针.
A char*[]是char的指针数组.如果你有一个以此为参数的函数,那么C编译器会将其"衰减"为a char**.这只发生在第一层......所以,举一个复杂的例子,char*[4][]变成了char*(*)[4].阅读上面的链接,这样你就可以理解这意味着什么了.
或者你可以做一个(非常明智的)并制作一堆typedef.我不这样做,但在你擅长阅读宣传员之前,这是一个好主意.
typedef char * stringp;
void func(stringp array[]) { ... }
static stringp FOUR_STRINGS[4] = { ... };
Run Code Online (Sandbox Code Playgroud)