char ** p,char * p ,char p 之间的区别
char *p = "some string"
创建指向包含该字符串的块的指针p。
char p[] = "some string"
创建一个字符数组并在其中包含文字。
第一个是常量声明。二维数组是否相同?
有什么区别
char **p,char *p[],char p[][].
我读了一下这个,char ** p创建了一个指针数组,因此与char p[][]
相比,它存在开销,用于存储指针值。
前两个声明创建常量arrays.i当我试图修改main(int argc,char **argv)
的argv
的内容时,没有得到任何运行时错误。 是因为它们是在函数原型中声明的吗?
正常声明(非函数参数)
char **p;
声明指向char
的指针。 它为指针保留空间。 它不会为指向指针或任何char
保留任何空间。
char *p[N];
声明一个指向char
的N个指针数组。 它为N个指针预留了空间。 它不会为任何char
保留任何空间。 必须明确地提供N
或者在初始化器的定义中,通过让编译器计算初始值设定项来隐式提供。
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
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;
pba +------+ +------+ +------+ | | | | | | |0x2000|------------>|0x1000|------------>| g | | | | | | | +------+ +------+ +------+ 0x3000 0x2000 0x1000 Figure 1: Typical memory layout assumption
在上面的声明中, a
是包含字符g
char
类型。 指针b
包含现有字符变量a
的地址。 现在b
是地址0x1000
, *b
是字符g
。 最后, b
地址分配给p
,因此a
是字符变量, b
是指针, p
是指向指针的指针。 其中包含a
包含值, b
包含地址, p
包含地址,如下图所示。
这里, sizeof(p) = sizeof(char *)
在各自的系统上;
II。 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
是char
类型的3个指针的数组。 意味着数组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 **
这里sizeof(p) = Number of char array * sizeof(char *)
III。 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 onday \0 \0 \0 \0| 1 | T uesday \0 \0 \0| 2 | W ednesday \0| +-------------------------+ Figure 3: Typical memory layout assumption
在这种情况下,数组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)
的二维数组;
-
a
char* a
是指向字符数组的指针,可以修改。 -
char b[]
是字符数组。b
无法修改。
它们有点兼容 – b
可以自动衰减到赋值和表达式,但不是其他方式。
当你使用char** p
, char* p[]
和char p[][]
这是非常相似的情况,只是更多层次的间接。