普通声明(不是函数参数)
char **p;
声明一个指向指针的指针char
。它为指针保留空间。它不为指向的指针或任何char
.
char *p[N];
声明一个数组N指向char
。它预留空间N指针。它不为任何内容保留任何空间char
. N
必须显式提供,或者在带有初始值设定项的定义中,通过让编译器计算初始值设定项来隐式提供。
char p[M][N];
声明一个数组M的数组N char
。它预留空间M•Nchar
。不涉及任何指针。N
必须明确提供。M
必须显式提供,或者在带有初始值设定项的定义中,通过让编译器计算初始值设定项来隐式提供。
函数参数中的声明
char **p
声明一个指向指针的指针char
。调用函数时,会为该指针提供空间(通常在堆栈上或处理器寄存器中)。没有为指向指针或任何指针保留空间char
.
char *p[N]
调整为char **p
,所以和上面的一样。的价值N
被忽略,并且N
可能缺席。 (某些编译器可能会评估N
,所以,如果它是一个有副作用的表达式,比如printf("Hello, world.\n")
,这些影响可能在调用函数时发生。 C 标准对此并不清楚。)
char p[M][N]
调整为char (*p)[N]
,所以它是一个指向数组的指针N char
。的价值M
被忽略,并且M
可能缺席。N
必须提供。调用函数时,会为指针提供空间(通常在堆栈上或处理器寄存器中)。没有为数组保留空间N char
.
argv
argv
是由调用的特殊软件创建的main
。它充满了软件从“环境”获得的数据。您可以修改char
里面的数据。
在你的定义中char *p = "some string";
,您无权修改以下数据p
指向,因为 C 标准规定字符串中的字符不能被修改。 (从技术上讲,它所说的是,如果你尝试的话,它并没有定义行为。)在这个定义中,p
不是数组;它是指向第一个的指针char
在一个数组中,以及那些char
位于字符串文字内部,并且不允许您修改字符串文字的内容。
在你的定义中char p[] = "some string";
,您可以修改内容p
。它们不是字符串文字。在这种情况下,字符串文字在运行时实际上并不存在;它只是用来指定数组如何p
已初始化。一次p
已初始化,可以修改。
数据设置为argv
以允许您修改它的方式设置(因为 C 标准指定了这一点)。