是否有关于C结构为了任何保证? [英] Are there any guarantees about C struct order?

查看:153
本文介绍了是否有关于C结构为了任何保证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用结构广泛,我已经看到了一些有趣的事情,尤其是 *值而不是值 - > FIRST_VALUE 其中value是一个指向struct, FIRST_VALUE 是第一个成员,是 *值安全吗?

另外请注意,大小不是因为对齐,什么的alginment价值基础上的保障,建筑/注册尺寸?

我们对齐数据/ code以加快执行速度,我们可以告诉编译器无法做到这一点?所以也许我们可以保证某些事情有关结构,就像他们的大小?

当上做结构成员指针运算,以找到成员偏移量,我想你做的 - 如果小尾数 + 为大端,还是只是依赖于编译器?

什么的malloc(0)真的分配?

下面code是为教育/发现目的,它并不意味着是生产质量。

 的#include<&stdlib.h中GT;
#包括LT&;&stdio.h中GT;诠释的main()
{
    的printf(的sizeof(结构{})==%璐; \\ N的sizeof(结构{}));
    的printf(的sizeof(结构{int类型的})==%璐; \\ N的sizeof(结构{int类型的;}));
    的printf(的sizeof(结构{int类型的;二重B;})==%璐; \\ N的sizeof(结构{int类型的;二重B;}));
    的printf(的sizeof(结构{字符℃;双A,双B:})==%璐; \\ N的sizeof(结构{字符℃;双A,双B:}));    的printf(的malloc(0))返回%P \\ N的malloc(0));
    的printf(的malloc(sizeof的(结构{}))返回%P \\ N的malloc(sizeof的(结构{})));    结构{int类型的;重B;} *测试=的malloc(sizeof的(结构{int类型的;二重B;}));
    测试 - >一种= 10;
    测试 - > B = 12.2;
    输出(测试 - >一种==%I,*测试==%I \\ N,测试 - >将*(INT *)测试​​);
    输出(测试 - > b ==%F,B的偏移量为%I *(测试 - offset_of_b)==%F \\ N,
        测试 - > B,(INT)((无效*)测试 - (无效*)及测试 - > B),
        *(双*)((无效*)测试 - ((无效*)测试 - (无效*)及测试 - > B))); //找到b的偏移,将其添加到基,$    自由(试验);
    返回0;
}

调用海合会test.c以然后按 ./ a.out的
我得到这样的:

 的sizeof(结构{})== 0;
的sizeof(结构{int类型的})== 4;
的sizeof(结构{int类型的;二重B;})== 16;
的sizeof(结构{字符℃;双A,双B:})== 24;
的malloc(0))返回0x100100080
的malloc(sizeof的(结构{}))返回0x100100090
测试 - >一种== 10 *试验== 10
测试 - > b == 12.200000,B的偏移量为-8,*(测试 - offset_of_b)== 12.200000

更新
这是我的机器:

的gcc --version

 的i686-苹果darwin10-GCC-4.2.1(GCC)4.2.1(苹果公司建立5666)(点3)
版权所有(C)2007自由软件基金会
这是自由软件;参见复印条件的来源。有否
保证;甚至不是针对特定目的的适销。

的uname -a

 达尔文的MacBookPro 10.8.0 Darwin内核版本10.8.0:星期二06月07日16时33分36秒PDT 2011;根:XNU-1504.15.3〜1 / RELEASE_I386 I386


解决方案

  

我用结构广泛,我已经看到了一些有趣的事情,尤其是 *值而不是值 - > FIRST_VALUE ,其中是一个指向struct, FIRST_VALUE 是第一个成员,是 *值安全吗?


*值是安全的;它产生了值在点结构的副本。但它几乎肯定会具有不同类型的 *值 - > FIRST_VALUE ,这样的结果 *值几乎总是不同于 *值 - 方式> FIRST_VALUE


反例:

 结构的东西{结构的东西* FIRST_VALUE; ...};
一些结构数据= {...};
一些结构*值=放大器;数据;
值 - > FIRST_VALUE =价值;

在这组相当有限的情况下,你会得到从 *值 *值 - &GT相同的结果; FIRST_VALUE 。根据该计划,类型是相同的(即使值不)。在一般情况下,类型 *值 *值 - 方式> FIRST_VALUE 是不同类型的



  

另外请注意,大小不保证,因为对齐,而是对准总是在寄存器的大小?


由于注册尺寸'是不是一个定义的C概念,目前还不清楚你问什么。在没有编译指令(的#pragma包或类似),结构的元素都将当值读取(或写)最佳性能对齐。


  

我们对齐数据/ code以加快执行速度;我们可以告诉编译器无法做到这一点?因此,也许我们可以保证某些事情有关结构,就像他们的大小?


编译器负责结构类型的大小和布局。您可以通过精心设计的#pragma包或类似指令影响,并可能通过

这些问题通常出现在人们关心的序列数据(或者,更确切地说,试图避免通过处理在同一时间的结构元素一个序列化数据)。通常情况下,我想你最好写一个函数来完成系列化,从组成部件构建起来。


  

当上做结构成员指针运算,以定位偏移成员,我想你做减法,如果小端,除了为大端,还是只是依赖于编译器?


你可能最好关闭的结构成员没有做指针运算。如果你必须使用从 offsetof()< STDDEF.H> 来正确处理偏移(和这意味着你不能直接做指针运算)。第一个结构元素总是在最低的地址,无论大字节序或小字节序。事实上,字节序对结构中的不同成员的布局没有影响;它只有一个结构的成员值的(基本数据类型)中的字节顺序的影响。

C标准要求一个结构的元素,因为它们被定义的顺序布置;第一元件是在最低地址,和下一个在较高的地址等的每个元件。编译器是不允许更改顺序。可以存在的结构的第一个元素之前没有填充。可以有填充结构为编译器的任何元素认为合适,以确保它认为适当的调整之后。一个结构的大小就是这样,你可以分配的适当对齐(N×大小)字节(例如,通过的malloc()),并把结果作为一个数组结构。

I've used structs extensively and I've seen some interesting things, especially *value instead of value->first_value where value is a pointer to struct, first_value is the very first member, is *value safe?

Also note that sizes aren't guaranteed because of alignment, whats the alginment value based on, the architecture/register size?

We align data/code for faster execution can we tell compiler not to do this? so maybe we can guarantee certain things about structs, like their size?

When doing pointer arithmetic on struct members in order to locate member offset, I take it you do - if little endian + for big endian, or does it just depend on the compiler?

what does malloc(0) really allocate?

The following code is for educational/discovery purposes, its not meant to be of production quality.

#include <stdlib.h>
#include <stdio.h>

int main()
{
    printf("sizeof(struct {}) == %lu;\n", sizeof(struct {}));
    printf("sizeof(struct {int a}) == %lu;\n", sizeof(struct {int a;}));
    printf("sizeof(struct {int a; double b;}) == %lu;\n", sizeof(struct {int a; double b;}));
    printf("sizeof(struct {char c; double a; double b;}) == %lu;\n", sizeof(struct {char c; double a; double b;}));

    printf("malloc(0)) returns %p\n", malloc(0));
    printf("malloc(sizeof(struct {})) returns %p\n", malloc(sizeof(struct {})));

    struct {int a; double b;} *test = malloc(sizeof(struct {int a; double b;}));
    test->a = 10;
    test->b = 12.2;
    printf("test->a == %i, *test == %i \n", test->a, *(int *)test);
    printf("test->b == %f, offset of b is %i, *(test - offset_of_b) == %f\n",
        test->b, (int)((void *)test - (void *)&test->b),
        *(double *)((void *)test - ((void *)test - (void *)&test->b))); // find the offset of b, add it to the base,$

    free(test);
    return 0;
}

calling gcc test.c followed by ./a.out I get this:

sizeof(struct {}) == 0;
sizeof(struct {int a}) == 4;
sizeof(struct {int a; double b;}) == 16;
sizeof(struct {char c; double a; double b;}) == 24;
malloc(0)) returns 0x100100080
malloc(sizeof(struct {})) returns 0x100100090
test->a == 10, *test == 10 
test->b == 12.200000, offset of b is -8, *(test - offset_of_b) == 12.200000

Update this is my machine:

gcc --version

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

解决方案

I've used structs extensively and I've seen some interesting things, especially *value instead of value->first_value where value is a pointer to struct, first_value is the very first member, is *value safe?

Yes, *value is safe; it yields a copy of the structure that value points at. But it is almost guaranteed to have a different type from *value->first_value, so the result of *value will almost always be different from *value->first_value.


Counter-example:

struct something { struct something *first_value; ... };
struct something data = { ... };
struct something *value = &data;
value->first_value = value;

Under this rather limited set of circumstances, you would get the same result from *value and *value->first_value. Under that scheme, the types would be the same (even if the values are not). In the general case, the type of *value and *value->first_value are of different types.


Also note that sizes aren't guaranteed because of alignment, but is alignment always on register size?

Since 'register size' is not a defined C concept, it isn't clear what you're asking. In the absence of pragmas (#pragma pack or similar), the elements of a structure will be aligned for optimal performance when the value is read (or written).

We align data/code for faster execution; can we tell compiler not to do this? So maybe we can guarantee certain things about structs, like their size?

The compiler is in charge of the size and layout of struct types. You can influence by careful design and perhaps by #pragma pack or similar directives.

These questions normally arise when people are concerned about serializing data (or, rather, trying to avoid having to serialize data by processing structure elements one at a time). Generally, I think you're better off writing a function to do the serialization, building it up from component pieces.

When doing pointer arithmetic on struct members in order to locate member offset, I take it you do subtraction if little endian, addition for big endian, or does it just depend on the compiler?

You're probably best off not doing pointer arithmetic on struct members. If you must, use the offsetof() macro from <stddef.h> to handle the offsets correctly (and that means you're not doing pointer arithmetic directly). The first structure element is always at the lowest address, regardless of big-endianness or little-endianness. Indeed, endianness has no bearing on the layout of different members within a structure; it only has an affect on the byte order of values within a (basic data type) member of a structure.

The C standard requires that the elements of a structure are laid out in the order that they are defined; the first element is at the lowest address, and the next at a higher address, and so on for each element. The compiler is not allowed to change the order. There can be no padding before the first element of the structure. There can be padding after any element of the structure as the compiler sees fit to ensure what it considers appropriate alignment. The size of a structure is such that you can allocate (N × size) bytes that are appropriately aligned (e.g. via malloc()) and treat the result as an array of the structure.

这篇关于是否有关于C结构为了任何保证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆