char *p = "some string"
创建一个指针p,指向包含该字符串的块。
char p[] = "some string"
创建一个字符数组并在其中包含文字。
第一个是常量声明。二维数组是否相同?
之间有什么区别
char **p,char *p[],char p[][].
我读了一下这个,char ** p创建了一个指针数组,因此与char p[][]
相比,它存在开销,用于存储指针值。
前两个声明创建常量数组。当我尝试修改argv
中main(int argc,char **argv)
的内容时,没有出现任何运行时错误。是因为它们是在函数原型中声明的吗?
答案 0 :(得分:16)
char **p;
声明指向char
的指针。它为指针保留空间。它不会为指向指针或任何char
保留任何空间。
char *p[N];
声明了一个指向char
的 N 指针数组。它为 N 指针保留空间。它不会为任何char
保留任何空间。必须明确地提供N
,或者在初始化器的定义中,通过让编译器计算初始化器来隐式提供。{/ p>
char p[M][N];
声明 N char
的 M 数组。它为 M • N char
预留空间。没有涉及指针。必须明确地提供M
和N
,或者在初始化程序的定义中,通过让编译器计算初始值设定项来隐式提供。
char **p
声明指向char
的指针。调用该函数时,为该指针提供空间(通常在堆栈或处理器寄存器中)。没有为指向指针或任何char
保留空间。
char *p[N]
调整为char **p
,因此与上述相同。 N
被忽略,可能不存在。
char p[M][N]
调整为char (*p)[N]
,因此它是指向 N char
数组的指针。 M
被忽略,可能缺席。必须提供N
。调用该函数时,为指针提供空间(通常在堆栈或处理器寄存器中)。没有为 N char
数组保留空间。
argv
由调用main
的特殊软件创建。它充满了软件从“环境”获得的数据。您可以修改其中的char
数据。
在您的定义char *p = "some string";
中,不允许修改p
指向的数据,因为C标准表示字符串文字中的字符可能无法修改。 (从技术上讲,它说的是,如果你尝试,它不会定义行为。)在这个定义中,p
不是数组;它是指向数组中第一个char
的指针,而那些char
位于字符串文字中,并且不允许修改字符串文字的内容。
在您的定义char p[] = "some string";
中,您可以修改p
的内容。它们不是字符串文字。在这种情况下,字符串文字在运行时实际上不存在;它只是用于指定数组p
如何初始化的东西。初始化p
后,您可以对其进行修改。
为argv
设置的数据的设置方式允许您对其进行修改(因为C标准指定了这一点)。
答案 1 :(得分:4)
从内存寻址视图中查看的更多差异描述如下,
予。 char **p;
p
是char
声明:
char a = 'g';
char *b = &a;
char **p = &b;
p b a
+------+ +------+ +------+
| | | | | |
|0x2000|------------>|0x1000|------------>| g |
| | | | | |
+------+ +------+ +------+
0x3000 0x2000 0x1000
Figure 1: Typical memory layout assumption
在上述声明中,a
是包含字符char
的{{1}}类型。指针g
包含现有字符变量b
的地址。现在a
是地址b
,0x1000
是字符*b
。最后g
的地址被分配给b
,因此p
是字符变量,a
是指针,b
是指针的指针。这意味着p
包含值,a
包含地址,b
包含地址,如下图所示。
此处,p
各个系统;
II。 sizeof(p) = sizeof(char *)
char *p[M];
是字符串数组
宣言:
p
char *p[] = {"Monday", "Tuesday", "Wednesday"};
在此声明中, p
+------+
| p[0] | +----------+
0 | 0x100|------>| Monday\0 |
| | +----------+
|------| 0x100
| p[1] | +-----------+
1 | 0x200|------>| Tuesday\0 |
| | +-----------+
|------| 0x200
| p[2] | +-------------+
2 | 0x300|------>| Wednesday\0 |
| | +-------------+
+------+ 0x300
Figure 2: Typical memory layout assumption
是类型为p
的3个指针的数组。 Implies数组char
可以容纳3个字符串。每个字符串p
位于内存(Monday, Tuesday & Wednesday)
中的某些位置,其中地址分别位于数组(0x100, 0x200 & 0x300)
中p
。因此它是指针数组。
备注:(p[0], p[1] & p[2])
char *p[3];
此处1. p[0], p[1] & p[2] are addresses of strings of type `char *`.
2. p, p+1 & p+2 are address of address with type being `char **`.
3. Accessing elements is through, p[i][j] is char; p[i] is char *; & p is char **
III。 sizeof(p) = Number of char array * sizeof(char *)
char p[M][N];
是固定长度字符串数组,其维度为p
宣言:
M x N
char p[][10] = {Monday, Tuesday, Wednesday};
在这种情况下,数组 p 0x1 2 3 4 5 6 7 8 9 10
+-------------------------+
0 | M o n d a y \0 \0 \0 \0|
1 | T u e s d a y \0 \0 \0|
2 | W e d n e s d a y \0|
+-------------------------+
Figure 3: Typical memory layout assumption
包含3个字符串,每个字符串包含10个字符。形成内存布局,我们可以说p
是一个大小为p
的二维字符数组,在我们的示例中为MxN
。这对于表示相等长度的字符串非常有用,因为当字符串包含少于10个字符时,与声明3x10
相比,存在内存浪费的可能性,因为没有指定字符串长度,并且它对于表示非常有用,因此没有内存浪费不等长的字符串。
访问元素与上述情况类似,char *p[]
是M'字符串& p [M] [N]是第M个字符串的第N个字符。
这里是二维数组的p[M]
;
答案 2 :(得分:0)
a
在char* a
中是指向字符数组的指针,a
可以修改。
b
中的char b[]
是字符数组。 b
无法修改。它们有点兼容 - b
可以在作业和表达式中自动衰减到a
,但不是其他方式。
当您使用char** p
,char* p[]
和char p[][]
时,情况非常相似,只是更多层次的间接。