【问题标题】:C - char array and char pointerC - 字符数组和字符指针
【发布时间】:2015-08-12 11:13:21
【问题描述】:

为什么我不能定义 一个数组

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);

【问题讨论】:

  • 我可以定义char **pp={ "123", "456", "789" }; ..我们在谈论什么编译器?
  • 使用++(**pointerToPointer)的目的是什么?
  • @EugeneSh。 , 虽然有警告...
  • "以及为什么我不能增加 ++(**pointerToPointer);" 因为您拥有的字符串是字符串文字,它们是不可变的。
  • @Subinoy ,因为this。通过this修复它

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


【解决方案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])

这是正确的,因为这里**pointerToPointer 的值正在改变。

这些都是我的原因。对于警告:

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

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

【讨论】:

  • 一个数组是什么意思? @CoolGuy 如果您发现任何错误,请编辑它
  • char *pp[]={ "123", "456", "789" }; 声明了一个指针数组,每个指针类型为char*。实际上,这里可以看到 4 个数组(我错了),每个字符串字面量也是一个数组。
  • 是的,我已经编辑过了。我只是忘记了这个概念。对错误感到抱歉@CoolGuy
  • 不是三个数组吗?@CoolGuy
  • 四个。三个字符串"123","456","789"pp
【解决方案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" };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2018-05-08
    • 1970-01-01
    相关资源
    最近更新 更多