char**p,char*p [],char p [] []之间的区别

pro*_*er8 14 c

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当我试图修改argvin 的内容时没有得到任何运行时错误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数组的数组.它为MN预留空间.没有涉及指针.并且必须通过让编译器计算初始值设定项来隐式提供,或者在带有初始值设定项的定义中提供. char charMN

函数参数中的声明

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标准指定了这一点).


Sun*_*lly 6

从内存寻址的角度来看,更多的差异描述如下,

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)

在上面的声明中,achar包含字符的类型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)的二维数组;