0

我正在阅读维基百科链接的这个版本的 C99 标准,试图了解灵活的数组成员是如何工作的。

在第 6.7.2.1 节中,声明了这个结构:

struct s { int n; double d[]; };

并举了一个例子:

s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);

它在哪里说,s1并且s2会表现得好像声明是:

struct { int n; double d[1]; } *s1, *s2;

它列出了一些你可以做的事情:

double *dp;
dp = &(s1->d[0]); // valid
*dp = 42; // valid
dp = &(s2->d[0]); // valid
*dp = 42; // undefined behavior

我可以看到为什么上面的最后一行是未定义的,因为s2只分配了 6 个额外的字节,这不足以存储双精度,但是我不明白为什么它会说s1and的行为s2就像它们被声明为:

struct { int n; double d[1]; } *s1, *s2;

当似乎s2没有分配足够的内存来存储该结构时。

该文件似乎是某种草稿,所以我不确定是否有错误或者我是否误解了其含义。

4

2 回答 2

1

(您不应该再研究 C99,它已经过时了。C11 是文档 n1570,位于您引用的同一位置。它可能/希望很快被 C17 取代。)

我认为,它说它表现得好像它有一个元素的原因是这句话

如果它没有元素,那么这样的数组的行为就好像它只有一个元素,但是如果尝试访问该元素,则行为是不确定的......

于 2018-04-01T12:57:32.373 回答
0

我喜欢将 C99 中的灵活结构视为 C++ 中的虚拟类,您可以指向它们,但不应该实例化它们。我经常构建一个辅助函数(工厂辅助函数?),它获取存储在灵活数组中的项目数并返回结构所需的实际分配,以确保其意图清晰。

#define OBJECTS_NEEDED 10

typedef struct
{
    uint8_t val1;
    uint32_t val2; // probable forces 4byte alignment of structure 
} myObject_t;

typedef struct
{
    uint8_t allocatedObjects;
    uint16 someMetaData;
    myObject_t objects[];   // struct inherits worst case alignment rule
} myObjectSet_t;

size_t getMyObjectSetSize(uint8_t reqObjs)
{
    return sizeof(myObjectSet_t) + reqObjs * sizeof(myObject_t);
}

void initMyObjectSetSize(myObjectSet_t *mySet, uint8_t reqObjs) 
{
   mySet->allocatedObjects = reqObjs;
   // Other Init code .....
}

void main()
{
    myObjectSet_t *mySet = malloc(getMyObjectSetSize(OBJECTS_NEEDED));
    initMyObjectSetSize(mySet , OBJECTS_NEEDED);
    // One issue, you can't rely on structure padding to be the same
    // from machine to machine so this test may fail on one compiler
    // and pass on another. You really do nee to use offsetof() if 
    // you need to find address of mySet given the address of one
    // of the objects[]
    assert((void*)mySet->objects == (void*)(mySet + 1)); 

}

编译器知道 sizeof(myObjectSet_t) 至少需要为 mod 4,因为 myObject_t 的数组可能需要至少 32 位对齐。我已经看到在 Windows 上运行的 GNU 编译器与在同一台笔记本电脑上的虚拟机中运行的 GNU 编译器生成不同的填充。

于 2018-04-10T22:12:27.233 回答