Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
&引用;“强”;通过一个元素结构在C中键入。编译器将做什么?_C_Struct_Padding_Strong Typing_C89 - Fatal编程技术网

&引用;“强”;通过一个元素结构在C中键入。编译器将做什么?

&引用;“强”;通过一个元素结构在C中键入。编译器将做什么?,c,struct,padding,strong-typing,c89,C,Struct,Padding,Strong Typing,C89,我计划在我的C代码中使用包含标量字段的结构来进行语义强类型化。基本思想是用于廉价“操作”的宏,这些操作将在错误命名的结构字段上失败,当然,通过严格的参数列表,更复杂的函数也会失败 示例(仅限于基本概念-不包括特别聪明的宏代码) 现在,在处理这样的OneElement结构时,我对编译器有什么期望?当使用这些结构作为函数参数时,我是否需要一些填充、更复杂的asm来“取消对第一个元素的引用”或可怕的事情?标准说明了什么?我不完全确定您担心会发生什么,但我相信填充会因操作系统而异。不要引用我的话。然而,

我计划在我的C代码中使用包含标量字段的结构来进行语义强类型化。基本思想是用于廉价“操作”的宏,这些操作将在错误命名的结构字段上失败,当然,通过严格的参数列表,更复杂的函数也会失败

示例(仅限于基本概念-不包括特别聪明的宏代码)


现在,在处理这样的OneElement结构时,我对编译器有什么期望?当使用这些结构作为函数参数时,我是否需要一些填充、更复杂的asm来“取消对第一个元素的引用”或可怕的事情?标准说明了什么?

我不完全确定您担心会发生什么,但我相信填充会因操作系统而异。不要引用我的话。然而,这绝对不是你需要担心的事情,除非你正在做一些粗略的大小计算来定制内存。访问成员变量的时间不应超过任何普通变量的时间。它本质上只是一个非常低级别的指针加法,除了添加0,所以它保持不变。我不确定你所说的“可怕的事情”是什么意思,但只要你不打字,它就应该能工作。

我不完全确定你担心会发生什么,但我相信填充会因操作系统而异。不要引用我的话。然而,这绝对不是你需要担心的事情,除非你正在做一些粗略的大小计算来定制内存。访问成员变量的时间不应超过任何普通变量的时间。它本质上只是一个非常低级别的指针加法,除了添加0,所以它保持不变。我不知道你所说的“可怕的事情”是什么意思,但只要你不打字,它就应该能工作。

不会有任何额外的填充。根据标准,结构的地址是其第一个元素的地址,因此填充总是插入到元素之间或结构的末尾,而不是开始。此外,您不必担心结尾的额外填充,因为对齐方式正是(单个)数据类型所需的对齐方式

启用优化后,您可以期望编译器生成基本相同的汇编代码。例如,O2的(32位)GCC生成的代码:

float add(float a, float b)
{
    return a + b;    
}
看起来像:

_add:
LFB0:
    .cfi_startproc
    flds    8(%esp)
    fadds   4(%esp)
    ret
    .cfi_endproc
如果您定义如下内容:

typedef struct foo
{
    float x;
} foo;

foo add(foo a, foo b)
{
    foo f; 
    f.x = a.x + b.x;
    return f;
}

使用O2编译,程序集完全相同。

不会有任何额外的填充。根据标准,结构的地址是其第一个元素的地址,因此填充总是插入到元素之间或结构的末尾,而不是开始。此外,您不必担心结尾的额外填充,因为对齐方式正是(单个)数据类型所需的对齐方式

启用优化后,您可以期望编译器生成基本相同的汇编代码。例如,O2的(32位)GCC生成的代码:

float add(float a, float b)
{
    return a + b;    
}
看起来像:

_add:
LFB0:
    .cfi_startproc
    flds    8(%esp)
    fadds   4(%esp)
    ret
    .cfi_endproc
如果您定义如下内容:

typedef struct foo
{
    float x;
} foo;

foo add(foo a, foo b)
{
    foo f; 
    f.x = a.x + b.x;
    return f;
}

使用O2编译,程序集是完全相同的。

我相信填充和访问的细节是由实现定义的。尽管从结构上看,我认为该标准意味着结构的地址与结构的第一个成员的地址相同。我把这个问题留给语言律师来回答,因为我不是100%确定。标准根本没有说明生成的程序集必须有多高效。你可以在你的系统上试试,看看会发生什么。我相信填充和访问的细节是由实现定义的。尽管从结构上看,我认为该标准意味着结构的地址与结构的第一个成员的地址相同。我把这个问题留给语言律师来回答,因为我不是100%确定。标准根本没有说明生成的程序集必须有多高效。你可以在你的系统上试试,看看会发生什么。我想他也在期待一些关于深度填充的解释,所以我想这会使你的答案更加完整:)我可以从许多其他信息中轻松提取的深度填充信息。意外的填充是我可能碰巧不知道的事情的例子。如果没有你期望的问题,除了看起来很糟糕的宏代码,我对这个答案很满意。我想他也期望得到一些关于填充深度的解释,所以我想这会使你的答案更加完整:)我可以从许多其他信息中轻松提取的填充深度信息。意外的填充是我可能碰巧不知道的事情的例子。如果没有你期待的问题,除了可怕的宏代码,我对这个答案很满意。我也不知道我的意思。我问了一些我可能不知道的问题:-),这种模式可能会引发一些问题。如果你没有看到一些,我完全同意。谢谢你的回答。我也不知道我的意思。我问了一些我可能不知道的问题:-),这种模式可能会引发一些问题。如果你没有看到一些,我完全同意。谢谢你的回答。