为什么用三元运算符初始化数组是非法的?

Why is array initialization with ternary operator illegal?

C 让我可以经常互换使用 char 指针和数组,以至于我经常认为它们是完全可以互换的。但是下面的代码证明这是不正确的。谁能解释为什么在下面的代码中使用三元运算符初始化 const char d[] 是非法的?

/* main.c */
#include <stdio.h>

int main()
{
  const char* a = "lorem";
  const char b[] = "ipsum";
  int* p;
  const char* c = ( *p ? "dolor" : "sit" );
  const char d[] = ( *p ? "amet" : "consectetur" ); // Why am I an error?
  return 0;
}

编译:

> gcc -g main.c 
main.c: In function \u2018main\u2019:
main.c:10:20: error: invalid initializer
   const char d[] = ( *p ? "amet" : "consectetur" ); // Why am I an error?

相关问题:如果我的术语在这里不准确:描述 const char d[] 的正确术语是什么?它是一个数组吗?变长数组?还有别的吗?它不被视为指针 - 是吗?

编辑:我相信 Array initialization with a ternary operator?

没有回答这个问题

RE: 参考问题,我相信前提略有不同。例如。接受的答案解释说 { 1, 2 };(或 { 'a', 'b' );)是无效的 C 表达式,我已经知道并接受了。但是 "amet";"consectetur"; 是有效的 C 表达式。

您只能使用初始化列表而不是表达式来初始化数组。在您的代码中

const char* c = ( *p ? "dolor" : "sit" );  

这里c是一个指针变量,字符串常量只代表地址。这就是为什么我们可以使用三元运算符,我们可以将字符串常量的地址分配给指针 c,然后我们可以初始化数组。但是

const char d[] = ( *p ? "amet" : "consectetur" );

这里的d是一个数组,但是d表示数组的地址,字符串常量也只表示地址。因此我们不能将地址分配给地址,这意味着数组 d 的字符串常量。这就是为什么我们会出错。

请访问 link 以获得更好的理解:

https://www.geeksforgeeks.org/whats-difference-between-char-s-and-char-s-in-c/

Array initialization with a ternary operator?

6.7.9 Initialization

...
14 An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

C 2011 Online Draft

( *p ? "amet" : "consectetur" ) 不是 字符串文字,它也不评估 为字符串文字。它计算为 char * 类型的表达式,它本身不是有效的数组初始值设定项,并且该计算直到运行时才会发生。

更不用说,p 未初始化,因此表达式未定义开头。

字符串文字有点神奇。通常(在表达式中使用时),它们表示数组。数组可以 "decay" (隐式转换)为指针,这就是为什么

const char *p = "foo";

有效。 "foo" 在这里是一个正常的表达式。你也可以写

const char *p;
p = "foo";  // assignment, not initialization

但是,如果使用字符串文字来初始化数组,它的行为类似于字符的初始化列表:

char s[] = "foo";
// equivalent to:
char s[] = { 'f', 'o', 'o', '[=12=]' };

在你的例子中

const char d[] = ( *p ? "amet" : "consectetur" );

初始化器不是唯一的字符串文字;这是一个表达。因此,两个字符串文字都会衰减为指针,然后您会收到一个错误,因为您无法从指针初始化数组。 (事实上​​ ,您根本无法从表达式初始化数组。)

您在尝试定义 d 之前犯了错误。在尝试定义 c 时,您会问 *p ?但是 p 没有被初始化。我认为该行为未定义。