char *p = "some string"
Run Code Online (Sandbox Code Playgroud)
创建指向包含该字符串的块的指针p.
char p[] = "some string"
Run Code Online (Sandbox Code Playgroud)
创建一个字符数组并在其中包含文字.
第一个是常量声明.二维数组是否相同?
有什么区别
char **p,char *p[],char p[][].
Run Code Online (Sandbox Code Playgroud)
我读了一下这个,char**p创建了一个指针数组,因此与char p[][]
存储指针值相比,它有一个开销.
前两个声明创建常量arrays.i当我试图修改argv
in 的内容时没有得到任何运行时错误main(int argc,char **argv)
.是因为它们是在函数原型中声明的吗?
Eri*_*hil 16
char **p;
声明指向指针的指针char
.它为指针保留空间.它不会为指向指针或任何指针保留任何空间char
.
char *p[N];
声明一个N指针数组char
.它为N个指针预留了空间.它没有为任何空间保留任何空间char
.N
必须通过让编译器对初始值设定项进行计数来显式提供,或者在带有初始值设定项的定义中提供.
char p[M][N];
声明N个M数组的数组.它为M • N预留空间.没有涉及指针.并且必须通过让编译器计算初始值设定项来隐式提供,或者在带有初始值设定项的定义中提供. char
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标准指定了这一点).
从内存寻址的角度来看,更多的差异描述如下,
I.char **p;
p
是双指针类型char
宣言:
char a = 'g';
char *b = &a;
char **p = &b;
Run Code Online (Sandbox Code Playgroud)
p b a
+------+ +------+ +------+
| | | | | |
|0x2000|------------>|0x1000|------------>| g |
| | | | | |
+------+ +------+ +------+
0x3000 0x2000 0x1000
Figure 1: Typical memory layout assumption
Run Code Online (Sandbox Code Playgroud)
在上面的声明中,a
是char
包含字符的类型g
。指针b
包含现有字符变量的地址a
。现在b
是地址0x1000
和*b
字符g
。最后的地址b
被分配给p
,因此a
是一个字符变量,b
是指针,p
是指向指针的指针。这意味着a
包含值,b
包含地址和p
包含地址的地址,如下图所示。
在这里,sizeof(p) = sizeof(char *)
在各自的系统上;
二、char *p[M];
p
是字符串数组
宣言:
char *p[] = {"Monday", "Tuesday", "Wednesday"};
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
在这个声明中,p
是 3 个类型为 的指针的数组char
。暗示数组p
可以容纳 3 个字符串。每个字符串(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 **
Run Code Online (Sandbox Code Playgroud)
这里 sizeof(p) = Number of char array * sizeof(char *)
三、 char p[M][N];
p
是维数为定长字符串的数组M x N
宣言:
char p[][10] = {Monday, Tuesday, Wednesday};
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,数组p
包含 3 个字符串,每个字符串包含 10 个字符。形成我们可以说的内存布局p
是一个大小为 的二维字符数组MxN
,这3x10
在我们的示例中。这对于表示相等长度的字符串很有用,因为与声明相比,当字符串包含少于 10 个字符时可能会浪费内存char *p[]
,没有内存浪费,因为没有指定字符串长度,并且它对于表示不等长度的字符串很有用。
访问元素与上述情况类似,p[M]
是第 M 个字符串 & p[M][N] 是第 M 个字符串的第 N 个字符。这里sizeof(p) = (M rows * N columns) * sizeof(char)
的二维数组;