2010-12-22 61 views
3

这是其中之一我认为这应该工作,但最好检查问题。它在我的机器上编译和正常工作。作为一个结构访问数组*

这是保证做我所期望的(即允许我访问数组的前几个元素,保证结构的布局,对齐,填充等与数组相同)?

struct thingStruct 
{ 
    int a; 
    int b; 
    int c; 
}; 


void f() 
{ 
    int thingsArray[5]; 
    struct thingStruct *thingsStruct = (struct thingStruct *)&thingsArray[0]; 

    thingsArray[0] = 100; 
    thingsArray[1] = 200; 
    thingsArray[2] = 300; 

    printf("%d", thingsStruct->a); 
    printf("%d", thingsStruct->b); 
    printf("%d", thingsStruct->c); 
} 

编辑:为什么地球上我会想要做这样的事情?我有一个数组,我正在映射到一个文件。我将数组的第一部分视为“标题”,它存储有关数组的各种信息,其余部分我将其视为一个普通数组。如果我将结构指向数组的开始,我可以以结构成员的形式访问这些头部数据,这些结构更具可读性。结构中的所有成员将与数组的类型相同。

+1

我认为**只要您使用`#pragma`或其他东西来禁用结构上的填充。 – 2010-12-22 17:48:27

+0

请注意,您可以通过在结束定义的大括号后面添加__attribute __(packed)来完成GCC。 – 2010-12-22 18:23:09

+1

对于Windows编译器(也受GCC支持),我相信你可以在结构定义之前使用`#pragma pack(0)`,之后使用`#pragma pack()`。 – 2010-12-22 18:23:53

回答

3

虽然我经常看到这样做,但你不能(这意味着它不合法,标准C)对结构的二进制布局做出假设,因为它可能在字段之间有填充。

这在comp.lang.c常见问题进行了说明:http://c-faq.com/struct/padding.htmls

2

由于Evan对此问题发表了评论,如果您的结构中的所有类型都与您的数组类型相同,那么在大多数情况下(如果您使用#pragma pack确保它们不是填充,可能最好) 。根据C的规则,这是合法的。

我对你的问题是“为什么?”这不是一件特别安全的事情。如果一个浮点数被扔进结构的中间,这一切都会崩溃。为什么不直接使用结构?这真的不是我在大多数情况下推荐的技术。

+1

“鉴于C的规则,这是合法的。”这是否违反严格的别名规则? – 2010-12-22 18:25:27

3

虽然这是可能在大多数地方工作,它仍然是一个有点玄乎。如果你想给符号名头的部分,为什么不只是做:

enum { HEADER_A, HEADER_B, HEADER_C }; 

/* ... */. 

printf("%d", thingsArray[HEADER_A]); 
printf("%d", thingsArray[HEADER_B]); 
printf("%d", thingsArray[HEADER_C]); 
0

用于表示一个头和文件数据的其余部分另一种解决方案是使用结构是这样的:

struct header { 
    long headerData1; 
    int headerData2; 
    int headerData3; 
    int fileData[ 1 ]; // <- data begin here 
}; 

然后你用一个文件的内容分配的内存块,并与

myFileHeader->fileData[ position ] 

任意大投它作为struct header *myFileHeader(或地图上的一个文件的内存块),并访问您的所有文件数据position。该语言对索引值没有限制,因此只有您有责任将您的任意大的posistion保留在您分配的内存块的实际大小(或映射文件的大小)内。

还有一个重要提示:除了关掉结构成员的填充,已经由他人进行了说明,你应该仔细选择页眉成员的数据类型,让他们尽管编译器贴合实际的文件数据布局你用(说,int将不会从32位更改为64位...)