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]; 声明一个指向charN个指针数组。 它为N个指针预留了空间。 它不会为任何char保留任何空间。 必须明确地提供N或者在初始化器的定义中,通过让编译器计算初始值设定项来隐式提供。

char p[M][N]; 声明一个由N char组成的M数组。 它为MN char预留空间。 没有涉及指针。 必须明确地提供MN或者在初始化器的定义中,通过让编译器计算初始值设定项来隐式提供。

函数参数中的声明

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; pchar类型的双指针

宣言:

 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 

在此声明中, pchar类型的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** pchar* p[]char p[][]这是非常相似的情况,只是更多层次的间接。