标量初始化器中的多余元素c

时间:2015-02-07 21:44:54

标签: c arrays pointers compiler-errors

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

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数组?

1 个答案:

答案 0 :(得分:0)

我假设您的代码看起来像(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等于"分隔符之间的字符数(具有特殊值)处理转义序列),加上一个空字符(共同表示为'\0')。对于字符串文字,n的值在编译时始终是已知的。它们具有静态存储持续时间,因此当执行程序时,您可以将它们视为已存在的现有对象。

指向int的指针与char[n]数组不兼容,因此您无法将字符串文字指定给int *

说实话,是的,你可以通过明确的演员“逼迫”它,就像这里:

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

但是任何从这样的指针读取的尝试都会违反strict aliasing rule,这会导致UB。