关于C结构顺序有什么保证吗?

关于C结构顺序有什么保证吗?,c,pointers,struct,C,Pointers,Struct,我已经广泛使用了结构,并且看到了一些有趣的事情,特别是*value而不是value->first\u value其中value是指向结构的指针,first\u value是第一个成员,*value安全吗 还要注意的是,由于对齐的原因,大小不能得到保证。ALGINTION值基于什么,体系结构/寄存器大小 我们对齐数据/代码以加快执行速度。我们能告诉编译器不要这样做吗?所以也许我们可以保证结构的某些东西,比如它们的大小 当在结构成员上执行指针运算以定位成员偏移量时,我认为您应该执行-如果little

我已经广泛使用了结构,并且看到了一些有趣的事情,特别是
*value
而不是
value->first\u value
其中value是指向结构的指针,
first\u value
是第一个成员,
*value
安全吗

还要注意的是,由于对齐的原因,大小不能得到保证。ALGINTION值基于什么,体系结构/寄存器大小

我们对齐数据/代码以加快执行速度。我们能告诉编译器不要这样做吗?所以也许我们可以保证结构的某些东西,比如它们的大小

当在结构成员上执行指针运算以定位成员偏移量时,我认为您应该执行
-
如果little-endian
+
用于big-endian,还是仅仅依赖于编译器

malloc(0)到底分配了什么

以下代码用于教育/发现目的,并不意味着具有生产质量

更新 这是我的机器:

gcc--版本

i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Copyright (C) 2007 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.
uname-a

Darwin MacBookPro 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
从6.2.5/20开始:

结构类型描述按顺序分配的非空成员对象集 (在某些情况下,是一个不完整的数组),每个数组都有一个可选的 指定的名称和可能不同的类型

答复:

特别是*value而不是value->first\u value,其中value是指向struct的指针,first\u value是第一个成员,*value安全吗

见6.7.2.1/15:

15在结构对象中,非位字段成员和位字段所在的单位 驻存地址按声明顺序增加指向 经过适当转换的结构对象指向其初始成员(或者如果该成员是 位字段,然后是它所在的单元),反之亦然。可能有未命名的 在结构对象中填充,但不在其开头。1

但是,在结构的末尾以及成员之间可能有填充字节

在C中,
malloc(0)
是实现定义的。(作为一个旁注,这是C和C++不同的小事情之一)


[1] 强调我。

调用
malloc(0)
将返回一个指针,该指针可以安全地传递到
free()
至少一次。如果多个
malloc(0)
调用返回相同的值,则每次调用可能会释放一次。显然,如果它返回
NULL
,则可以无限次地传递给
free()
,而不会产生任何效果。对
malloc(0)
的每次调用如果返回非null,则应通过对
free()
的调用与返回值进行平衡。

如果有内部结构,则保证在与封闭结构相同的地址上启动,如果这是封闭结构的第一个声明

因此,
*value
value->first
正在访问相同地址(但使用不同类型)的内存,如下所示

struct St {
  long first;
} *value;
此外,结构的成员之间的顺序保证与声明顺序相同

要调整对齐方式,可以使用特定于编译器的指令或使用位字段

结构成员的对齐通常基于访问目标平台上单个成员的最佳方式

另外,对于
malloc
,它可能在返回的地址附近保留一些簿记,因此即使对于零大小的内存,它也可以返回一个有效地址(只是不要试图通过返回的地址访问任何内容)

我已经广泛地使用了结构,并且看到了一些有趣的事情,特别是
*value
而不是
value->first\u value
,其中
value
是指向结构的指针,
first\u value
是第一个成员,
*value
安全吗

是,
*值
是安全的;它生成
指向的结构副本。但是几乎可以保证它的类型与
*value->first\u value
不同,因此
*value
的结果几乎总是与
*value->first\u value
不同


反例:

在这种相当有限的情况下,您将从
*value
*value->first\u value
获得相同的结果。在该方案下,类型将是相同的(即使值不相同)。在一般情况下,
*value
*value->first\u value
的类型是不同的


还要注意的是,由于对齐,无法保证大小,但是对齐是否总是在寄存器大小上

因为“寄存器大小”不是一个定义的C概念,所以不清楚您在问什么。如果没有pragma(
#pragma pack
或类似内容),则在读取(或写入)值时,结构的元素将对齐以获得最佳性能

我们调整数据/代码以加快执行速度;我们能告诉编译器不要这样做吗?所以也许我们可以保证结构的某些东西,比如它们的大小

编译器负责
struct
类型的大小和布局。您可以通过仔细的设计,或者通过
#pragma pack
或类似的指令来影响

当人们关心序列化数据(或者,更确切地说,试图通过一次处理一个结构元素来避免序列化数据)时,通常会出现这些问题。一般来说,我认为最好编写一个函数来进行序列化,从组件块构建它

在对结构成员执行指针运算以定位成员偏移量时,我认为如果是小端,则执行减法运算,如果是大端,则执行加法运算,还是仅依赖于编译器

最好不要对
struct
成员执行指针运算。如果必须,请使用
中的
offsetof()
宏正确处理偏移(以及
Darwin MacBookPro 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
struct St {
  long first;
} *value;
struct something { struct something *first_value; ... };
struct something data = { ... };
struct something *value = &data;
value->first_value = value;
struct foo{
  int i;
  char c;
}

struct bar{
  int i;
  int j;
}

struct baz{
  int i;
  char c;
  int j;
}

sizeof(foo) = 8 bytes (32 bit arch)
sizeof(bar) = 8 bytes
sizeof(baz) = 12 bytes