C - char数组和char指针

时间:2015-05-29 14:23:27

标签: c arrays pointers c-strings string-literals

为什么我无法定义 数组

char **pp={ "123", "456", "789" };

但我可以将它定义为char * [],并将其发送给一个将其作为char **接受的函数

char *pp[]={ "123", "456", "789" };
fun(pp);

void fun(char **pointerToPointer)
{
    //++(**pointerToPointer);//error
    printf("%s", *pointerToPointer); 
}
//output::"123"

为什么我不能增加

++(**pointerToPointer);

2 个答案:

答案 0 :(得分:2)

要回答第一个问题,如果我们使用单一深度的指针,原则可能会更清楚。出于同样的原因,此代码是非法的:

int *ptr = { 1, 2, 3 };

在C中,支撑的初始化列表不是对象(尤其不是数组)。它只能作为初始化对象时从中读取初始化程序的项目列表。

ptr是一个对象,因此最多可以使用一个初始值设定项,并且该初始值设定项的预期形式是指针(1不是)。

事实上,根据C11 6.7.9 / 11:

,此代码明显是非法的
  

标量的初始值设定项应为单个表达式,可选择用大括号括起来

但是,有一个gcc错误/功能,它允许标量的多余初始值设定项并忽略它们。此外,某些编译器可能“有用”并且“仅”发出警告,并初始化ptr以指向地址1,无论在哪里。

“标量”表示不是结构或数组的对象。

从C99开始,你可以写:

int *ptr = (int []){1, 2, 3};

创建一个数组(使用与ptr相同的存储持续时间)并在其第一个元素处指向ptr

这个数组是可变的;对于不可变的,请使用int const *ptr = (int const[]){1, 2, 3};

int替换char *,我们看到您可以写:

char **p = (char *[]){ "123", "456", "789" };

在这种情况下数组中的指针是可变的,但它们指向的东西(即字符串文字)仍然不是。

请注意,在处理字符串文字时应始终使用char const *,因为它们不可变。字符串文字具有类型char [N]的事实是从const添加到C之前的历史宿醉。所以:

char const **pp = (char const *[]){ "123", "456", "789" };

或使用不可变的字符串指针:

char const *const *pp = (char const *const []){ "123", "456", "789" };

答案 1 :(得分:1)

此处char *pp[]={ "123", "456", "789" };是正确的,因为:

  • 这是一个指针数组,可用于指向数据项数组,指针数组的每个元素都指向数据数组的元素。
  • 当我们将每个数组分配给char指针时,它可以正常工作。

但是在char **pp={ "123", "456", "789" };

的情况下
  • 这里没有发生内存初始化。
  • 而不是第一个字符串被分配给指针,然后编译器生成警告,说明丢弃了其他许多值。

由于 CoolGuy ++(**pointerToPointer)这是错误的,因为它访问了1 "123"字符串,并尝试将1的值更改为2,因为这些是字符串文字,所以无法完成分配。您只能看到print的增量值: printf("%c\n", **pointerToPointer+1); 这将提供输出:2

您可以通过评论中 CoolGuy 提供的解决方案来解决问题 -

  1. char *pp[]={ "123", "456", "789" };更改为char pp[][100]={ "123", "456", "789" };
  2. void fun(char **pointerToPointer)更改为void fun(char (*pointerToPointer)[100])
  3. 这是正确的,因为**pointerToPointer的值正在变化。

    这些是我的理由。而警告:

    warning: excess elements in scalar initializer [enabled by default]

    你可以看到here中的链接,这对我来说是最好的解释。