C:点/箭头操作员如何在引擎盖下工作?

时间:2019-06-18 14:12:13

标签: c

据我所知,

int *x = malloc(10 * sizeof(int));
x[5] = 13;

malloc仅分配空白空间(不假设将放置在此处的对象),并且x[5]转换为*(x + 5),它被视为整数。因此,留给[]运算符来创建数组的错觉。

但是在以下情况下会发生什么?

struct test {
    int a;
    char b;
};

struct test* x = malloc(sizeof(struct test));
x->a = 3;
x->b = 'a';

x->a, x->b是否像[i]运算符那样以某种常规方式转换到某个内存位置? C引用是否声明任何内容,或者它是特定于实现的?我一直在浏览各种书籍,但是与数组相反,结构始终以黑匣子的形式呈现。

2 个答案:

答案 0 :(得分:2)

假设int是4个字节,char是1个字节(我不知道这些数字是什么意思,但可以说这是正确的)。然后,结构test将在内存中连续5个字节(第一个a(4个字节),然后是b(1个字节)。

如果您随后调用test->b,则指向该struct的开头加上4字节的偏移量。 (由于test是指针,->a是指手段+0,而->b是指手段+4

答案 1 :(得分:1)

  

malloc仅分配空白空间(不假设将放置在那里的对象)

正确。具体来说,动态分配的内存在您向该区域写入内容之前没有类型。正式地,C语言将其称为 有效类型 。正式定义可在C17 6.5 / 7中找到:

  

用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。如果通过具有非字符类型的左值将值存储到没有声明类型的对象中,则该左值的类型将成为该访问和不修改该访问的后续访问的对象的有效类型。储值。

从malloc返回的内容只是一块原始内存,没有特殊属性,直到您写入该区域为止。之后,编译器必须在内部在其上放置“类型标签”。使用[]进行访问后,编译器将不得不假定已分配的数据必须视为数组,以使静态分配对象和动态分配对象之间的类型系统保持一致。

类似地,在您访问内存时,内存区域将成为一个结构,因为它将具有填充等内容,并指示每个成员的内存偏移量。因此,如果给出与示例相反顺序的结构,如下所示:

struct test {
    char a;
    int  b;
};

然后x->b会导致对字节1,字节4或其他内容的访问,这是实现定义的,因为编译器可以自由地在成员之间添加填充。

但是,一旦您访问x->something,编译器将必须开始考虑x所指向的有效类型struct test的类型,否则类型系统的行为将不一致。 / p>