c中的sizeof初始化常量

sizeof initialized constant in c

我已经编写了简单的示例代码 (also available at ideone) 来说明我在哪里发现了问题。 Sizeof return 在常量 s 情况下的错误结果。下面是文件 main.c.

#include <stdint.h>
#include <stdio.h>

// comment this option if you know what is UB and want to avoit it 
#define I_DONT_KNOW_WHAT_IS_UB ( 1 )

struct _sa {
    uint32_t w;
    uint8_t const a[];
};

uint8_t const a[] = { 7,6,5,4,3,2,1,0 };

struct _sa const s = {
    .w = 8,
    .a = { 7,6,5,4,3,2,1,0 },
};

char const b[] = "line";

int main(void)
{
    #ifdef I_DONT_KNOW_WHAT_IS_UB
    printf("sizeof(a) = %d \n", (int)sizeof(a)); // = 8
    printf("sizeof(s) = %d \n", (int)sizeof(s)); // = 4
    printf("sizeof(b) = %d \n", (int)sizeof(b)); // = 5
    #else
    printf("sizeof(a) = %zu \n", sizeof(a)); // = 8
    printf("sizeof(s) = %zu \n", sizeof(s)); // = 4
    printf("sizeof(b) = %zu \n", sizeof(b)); // = 5
    #endif

    return 0;
}

我用老年 ubuntu:

uname -a
Linux imbearr 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

gcc --version
gcc (Ubuntu 9.3.0-11ubuntu0~14.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gcc main.c -o szof -Xlinker -Map=szof.map
grep -C 1 "\bs\b" ./szof.map 
                0x00000000004005e8                a
                0x00000000004005f0                s
                0x00000000004005fc                b

所以我已经通过链接器映射文件检查了大小: 0x4005fc - 0x4005f0 = 12, 0x4005f0 - 0x4005e8 = 8.

为什么我有这样的结果,这是 gcc 限制还是错误,可能是我的错误?

sizeofreturns参数类型的大小

所以当你调用 sizeof(b) 时,你实际上是在问,“struct _sa 的大小是多少?

struct _sa的大小是4字节,因为元素.w占4字节,而元素.a是一个灵活的数组,占用零字节,因为数组, 如类型中定义的那样,没有定义的大小。

询问具有灵活数组成员的结构的大小只给出结构的基本大小,没有数组成员。 C 2018 6.7.2.1 18 说:

… In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply…

因此,如果灵活数组成员 a 不存在,sizeof s 是结构的大小,除非它可能有额外的填充。由于 uint32_t w; 成员需要四个字节,并且您的编译器在这种情况下不会插入额外的填充,因此结构的大小为四个字节。

备注

在这种情况下会出现额外的填充:

struct foo
{
    char c;
    int array[];
};

int 需要四字节对齐的实现中,编译器将通过在成员 c 后插入三个字节来确保数组成员对齐,因此 sizeof (struct foo) 将为四.