【问题标题】:excess elements in scalar initializer c标量初始化器 c 中的多余元素
【发布时间】:2015-02-07 21:44:54
【问题描述】:

正如“Excess elements of scalar initializer for pointer to array of ints”的问题一样,我也在研究 Ex。 5-9 在 K&R,尝试转换

static char daytab[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

进入

static char *daytab[] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

我得到了那里描述的错误。但是,接受的答案

static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;

ptr = arr;

只是在ptr = arr 处给我另一个错误

error: data definition has no type or storage class

谁能帮忙?

还有,为什么使用指向char数组的指针数组是合法的,比如

static char *name[] = {
    "Illegal month",
    "January", "February", "March",
    "April", "May", "June",
    "July", "August", "September",
    "October", "Novemer", "December"
};

但不是int 数组?

【问题讨论】:

  • 查看更新的答案。我对你的第二个问题的回答做了一点改进。

标签: c arrays pointers compiler-errors


【解决方案1】:

我假设您的代码看起来像(gcc 的错误消息完全相同):

#include <stdio.h>

static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;
ptr = arr;

int main(void)
{       
    printf("%d\n", ptr[0][0]);

    return 0;
}

这确实是无效的,因为ptr = arr; 赋值被放置在任何函数之外。 C语言的语法规则只允许放在里面,像这里:

#include <stdio.h>

int main(void)
{
    static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
    static char (*ptr)[3] = NULL;
    ptr = arr;

    printf("%d\n", ptr[0][0]);

    return 0;
}

对于这两个示例,static 关键字的含义也存在根本差异。前者影响链接,后者影响特定对象的存储时长,由标识符表示。

对于第二个问题,您可以将其简化为更基本的形式:

为什么以下是合法的:

char *name = "January";

虽然不是这样:

int *name = "January";

?

在这里(以及您问题中的先前形式),"January" 不被解释为数组初始值设定项,而是被解释为 字符串文字

这些文字是只读的(任何修改它们的尝试都会导致undefined behaviorchar[n] 类型的对象,其中 n 等于 " 分隔符之间的字符数(对 escape 进行特殊处理序列),加上一个空字符(共同表示为'\0')。 n 的值在字符串文字的编译时总是已知的。它们具有静态存储持续时间,因此您可以将它们视为现有对象,在执行 is 程序时已经存在。

指向int 的指针与char[n] 数组不兼容,因此您不能将字符串字面量分配给int *

说实话,是的,您可以通过显式强制转换来“强制”它,如下所示:

int *name = (int *) "January";

但任何从此类指针读取的尝试都会违反strict aliasing rule,从而导致 UB。

【讨论】:

  • 非常感谢您的回答。但是,对于第二部分,我更想知道为什么char *name = "January"; 是合法的,而char *num = {1, 2, 3}; 不是?字符串文字是否被视为现有数组?
  • 啊,这就是我想知道的,字符串文字被视为预先存在的数组。再次感谢!
  • char * name = "一月";正在被编译器转换为 char * name[8] = {'J','a','n','u','a','r','y','/0'};其中 [ char ] 编译将 /0 添加到数组的末尾。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
相关资源
最近更新 更多