关于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