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

时间:2013-10-11 18:52:24

标签: c

char *p = "some string"   

创建一个指针p,指向包含该字符串的块。

char p[] = "some string" 

创建一个字符数组并在其中包含文字。

第一个是常量声明。二维数组是否相同?

之间有什么区别
char **p,char *p[],char p[][]. 

我读了一下这个,char ** p创建了一个指针数组,因此与char p[][]相比,它存在开销,用于存储指针值。

前两个声明创建常量数组。当我尝试修改argvmain(int argc,char **argv)的内容时,没有出现任何运行时错误。是因为它们是在函数原型中声明的吗?

3 个答案:

答案 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预留空间。没有涉及指针。必须明确地提供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标准指定了这一点)。

答案 1 :(得分:4)

从内存寻址视图中查看的更多差异描述如下,

予。 char **p; pchar

类型的双指针

声明:

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是地址b0x1000是字符*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)

    {li> achar* a中是指向字符数组的指针,a可以修改。 b中的
  • char b[]是字符数组。 b无法修改。

它们有点兼容 - b可以在作业和表达式中自动衰减a,但不是其他方式。

当您使用char** pchar* p[]char p[][]时,情况非常相似,只是更多层次的间接。