Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1725218
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: C/C++

2012-04-25 12:59:32

C里的所有对象都必须表示成连续的字节序列,且每个都至少有8位的宽度。在一个36位字长的机器上,一个字节可以定义成9、12、18、或36位, 对于占用一个字节的字符类型来说,它的位数也不会小于8。sizeof返回的“字节”数也是与机器无关的,它可能是8位、9位或其它的位数。

因为这种宽度限制,所以空结构体的对象也要占用至少一字节的空间。比如:

struct Empty
{
};

printf("%d, ", sizeof(struct Empty));
struct Empty e1, e2;
printf("%p, %p\n", &e1, &e2);

输出为:0, 0xbf9ccf8e, 0xbf9ccf8f


再讨论下包含空结构体对象的结构体:

struct EmptyGroup
{
    struct Empty e1;
    struct Empty e2;
    struct Empty e3;
};

int main()
{
    struct EmptyGroup eg1, eg2;
    printf("%p, %p\n", &eg1, &eg2);
    printf("%p, %p, %p\n", &(eg1.e1), &(eg1.e2), &(eg1.e3));
    return 0;
}

输出为:
0xbff7965e, 0xbff7965f
0xbff7965e, 0xbff7965e, 0xbff7965e

可以看到各成员共用一个地址。

注意,如果是C++,它的输出会有不同:

0xbfca68d8, 0xbfca68db
0xbfca68d8, 0xbfca68d9, 0xbfca68da

每个成员对象都占用了一个字节,这种特性在C++中保证了多重继承的可能性。


结构体的内存布局有一些限制:

1、结构体开头不能有空洞(hole);

2、成员会增加存储空间;

3、在结构体末,需要的时候可能会放置一个空洞来使结构体足够大,以便在数组里紧密排列并有恰当的内存对齐。


可变长度的结构体

在C89,有一种称为“struct hack”的方法来得到可变数组。

struct s
{
    int n_items;
    int items[1];
};
struct s *p = malloc(sizeof(struct s) + (n - 1) * sizeof(int));

这种方式可以使得结构体里的数组长度为n。但它被认为多少有些邪恶的。C99提供了类似的但合法的“struct”机制:

struct OK
{
    int n;
    int a[];
};
struct OK *p = (struct OK *)malloc(sizeof(struct OK) + 10 * sizeof(int));
p->a[9] = 9;

注意只有结构体内最后的数组才可以有可变长度,且它不能是唯一的成员。


结构体的初始化与赋值

C89的扩展和C++都支持“Compound Literal”的概念。例如:

struct R
{
    int c;
    double d;
};

struct S
{
    int a;
    float b;
    struct R r;
    char *s;
};

结构体的初始化和赋值可以很简明:

    struct S s = { 1, 3.4, {6, 7.8}, "hello" };
    s = (struct S){ 1, 3.4, {6, 7.8}, "hello" };
    s.r = (struct R){6, 7.8};

C99提供了“Designated Initializers”的机制,它可以以任意顺序为结构体赋值:
    s.r = (struct R) { .c = 8, .d = 9.0 };

或 s.r = (struct R) { .d = 8.0, .c = 9 };


对于union,只能用Designated Initializers,比如:

u = { .a = 4 };

虽然Compound Literal也可以使用,但它的效果仅等同于cast,结果可能会不正确。

阅读(2033) | 评论(0) | 转发(1) |
0

上一篇:C99的变量类型

下一篇:C99的数组

给主人留下些什么吧!~~