C语言中的字符数组和字符指针是什么?

4
为什么我无法定义数组
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" }; .. 我们在谈论哪个编译器? - Eugene Sh.
使用 ++(**pointerToPointer) 的目的是什么? - Subinoy
1
@EugeneSh。不过要带上警告... - Spikatrix
1
“为什么我不能对 ++(**pointerToPointer); 进行递增操作?”因为你拥有的字符串是字符串字面量,它们是不可变的。 - Spikatrix
1
@Subinoy,由于这个。请通过这个进行修复。 - Spikatrix
显示剩余9条评论
2个回答

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]的事实是C语言中添加const之前的历史遗留问题。因此:

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

或者使用指向不可变字符串的非可变指针:
char const *const *pp = (char const *const []){ "123", "456", "789" };

1

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

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

但是,在char **pp={ "123", "456", "789" };的情况下

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

正如CoolGuy所说的++(**pointerToPointer)是错误的,因为它正在访问"123"字符串中的1,并尝试将1的值更改为2,由于这些是字符串字面量,不能进行赋值。您只能看到打印的增量值: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]

您可以在 此处 查看他对我来说是最好的解释。

一个数组是什么意思?@CoolGuy 如果有任何错误,请编辑。 - Subinoy
四个。三个字符串“123”,“456”,“789”和pp。 - Spikatrix
哦,是的,@CoolGuy,你说得对。但是这三个字符串是123456789,这就是我想要告诉你的。我是对的吧? - Subinoy
但是为什么我在函数中可以得到它作为char **? - Zag Gol
这里只是取第一个字符串并尝试将其分配给 char**,因此它没有发生 @ZagGol - Subinoy
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接