1506-221(S)初始化程序必须是有效的常量表达式

时间:2018-08-02 09:19:17

标签: c linux compilation aix

在AIX头文件编译期间,我面临着这个问题。

头文件(header1.h)具有以下结构:

http://169.254.169.254/latest/user-data

.c文件中现在包括header1.h

<powershell>
New-Item C:\Temp\test.txt -ItemType file 
</powershell>
<persist>true</persist>

当我使用xlc编译器编译上述.c文件时,会引发错误:

  

header1.h”,行xxxx:1506-221(S)初始化程序必须是有效的常量表达式。

     

make:1254-004最后一条命令的错误代码为1。

     

停止。

2 个答案:

答案 0 :(得分:0)

与您对sx1的奇怪初始化无关(它是一个嵌套的结构,因此您需要一个嵌套的初始化程序)。

{{1,'a'},{1,'a'},{1,'a'}};

当使用变量(的地址)时,DEF的扩展仅在运行时可用。正如编译器告诉您的那样,您只能使用常量表达式,这意味着该值必须在编译时清除。就像上面的例子一样。

您可能正在寻找offsetof宏,它会得出一个常量表达式。 constant expression不能包含变量。幸运的是,结构的定义不是变量。

下面的示例摆脱了第二个结构,因为它不必要地使问题复杂化。您可以将其重新添加为您的代码。

AFAIK您需要完全声明Struct才能使用它。这就是sx1的声明是正确的原因。

struct MyStruct{
    int a;
    int c;
    int b;
};

static struct MyStruct sx1 = {offsetof(struct MyStruct,b),'B','A'};

int main()
{
    printf("%d %c",sx1.a,sx1.b);
}

您可能要检查typedef structs

答案 1 :(得分:0)

好吧,除了您要说的以外,您还有几个错误。首先,您正在DEF宏中封闭(这非常危险,因为您将表达式隐藏在宏实例化下面,并且使错误对您不可见),将具有不同指针类型的地址相减(这是非法的) )例如,如果您将DEF重新定义为您的第一个struct使用,则为:

#define DEF(f) (&sx1.f - &sx1.aa)

然后您会在扩展以下内容时出错:

DEF(bb) -> (&sx1.bb - &sx1.aa)

其中bbchar,而aint(您将int *减去char *)。展开DEF宏后,这将导致编译问题,但是您不会看到产生编译器错误的实际扩展。

第二,初始化程序只能使用常量表达式,这意味着仅生成常量或常量表达式的静态表达式,并且&运算符必须在链接时间多数时候进行解析(这使表达式不是常量一个,但是在编译之间可能会改变的东西),甚至在运行时也可以更改(假设第一个&的操作数是一个堆栈自动变量,而第二个操作数是一个全局的固定变量,那么每次初始化时,常数值会有所不同,具体取决于堆栈在运行时的增长方式。您不能在常数表达式中使用&运算符作为一般规则。

第三,如果您尝试模拟ANSI offsetof(structure_type, field)宏的定义,则可以使用类似(请注意,此定义会导致一些可能依赖于体系结构的技巧,因此,便携式):

#define OFFSETOF(type, field)  ((size_t)(char *)(&((type*)0)->field))

如以下代码所示:

pru.c

#include <stdio.h>
struct my_data_struct {
    int a;
    char b;
    double c;
    char d[100];
    int e;
};

#define OFFSET_OF(type, field) ((size_t)(char *)(&((type*)0)->field))

int main()
{
#define P(f) printf("OFFSET_OF(struct my_data_struct, %s) == %zu\n", #f, OFFSET_OF(struct my_data_struct, f))
    P(a);
    P(b);
    P(c);
    P(d);
    P(e);
}
产生以下结果的

$ run pru
OFFSET_OF(struct my_data_struct, a) == 0
OFFSET_OF(struct my_data_struct, b) == 4
OFFSET_OF(struct my_data_struct, c) == 8
OFFSET_OF(struct my_data_struct, d) == 16
OFFSET_OF(struct my_data_struct, e) == 116
$ _

在我的系统上。

说明

(type*)0

是将NULL文字转换为(type*)的地址

((type*)0)->field

是在其字段field上取消引用的空指针(不用担心,因为我们实际上并没有取消引用该值,而只是引用了它)

&((type*)0)->field

是它的地址。

(char *)(&((type*)0)->field)

是将地址转换为(char *)的地址(因此指针算术为字节大小)。还有

((size_t)(char *)(&((type*)0)->field)

是将地址转换为size_t值。

当然,此计算的一部分(如果不是大部分)取决于体系结构,这就是当今标准在标准库(#include <stddef.h>)中包含某种此类宏的原因。因此,请勿使用我的定义(以防万一您的系统中没有它),并在编译器/库文档中搜索一个offsetof宏,该宏向您显示结构中字段的位置。

最后一件事...因为我使用了常量指针值(所有内容都来自常量0)并且没有减去引用,因此它在需要常量表达式的初始化程序中可用。

#include <stdio.h>
struct my_data_struct {
    int a;
    char b;
    double c;
    char d[100];
    int e;
};

#define OFFSET_OF(type, field) ((size_t)(char *)(&((type*)0)->field))

static size_t my_vector[] = {
    OFFSET_OF(struct my_data_struct, a),
    OFFSET_OF(struct my_data_struct, b),
    OFFSET_OF(struct my_data_struct, c),
    OFFSET_OF(struct my_data_struct, d),
    OFFSET_OF(struct my_data_struct, e),
};

您可以很好地解释所有这些内容here