Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.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_Memcmp - Fatal编程技术网

C结构的内部一致性

C结构的内部一致性,c,struct,memcmp,C,Struct,Memcmp,如果我有两个C结构初始化为具有相同的成员,我可以保证: memcmp(&struct1, &struct2, sizeof(my_struct)) 是否总是返回零?否,对于memcmp(),所有成员相等的两个结构有时可能会比较不相等,因为 一个合理的例子如下。对于st2的初始化,符合标准的32位编译器可以生成一系列汇编指令,使部分最终填充未初始化。这段填充将包含堆栈上发生的任何内容,而st1的填充通常包含零: struct S { short s1; long long i;

如果我有两个C结构初始化为具有相同的成员,我可以保证:

memcmp(&struct1, &struct2, sizeof(my_struct))

是否总是返回零?

否,对于
memcmp()
,所有成员相等的两个结构有时可能会比较不相等,因为

一个合理的例子如下。对于
st2
的初始化,符合标准的32位编译器可以生成一系列汇编指令,使部分最终填充未初始化。这段填充将包含堆栈上发生的任何内容,而
st1
的填充通常包含零:

struct S { short s1; long long i; short s2; } st1 = { 1, 2, 3 };
int main() {
  struct S st2 = { 1, 2, 3 };
  ... at this point memcmp(&st1, &st2, sizeof(struct S)) could plausibly be nonzero
}

我认为你不能安全地
memcmp
一个测试平等性的结构

来自C11§6.2.6.6类型表示

当值存储在结构或联合类型的对象中时, 在成员对象中包括对象表示的字节 与任何填充字节相对应的值采用未指定的值

这意味着您需要编写一个函数来比较结构的各个元素

int my_struct_equals(my_struct* s1, my_struct* s2)
{
    if (s1->intval == s2->intval &&
        strcmp(s1->strval, s2->strval) == 0 && 
        s1->binlen == s2->binlen &&
        memcmp(s1->binval, s2->binval, s1->binlen) == 0 &&
        ...
        ) {
        return 1;
    }
    return 0;
}
如果两个变量都是全局变量或静态变量,并且它们的成员在程序初始化时初始化,则是,它们将与
memcmp()
进行相等比较。(注意,大多数系统只是将数据页加载到零初始化页中,但C标准不保证这种行为。)

此外,如果其中一个结构是使用
memcpy()
初始化的,那么它们将与
memcmp()
进行相等比较

如果在将它们的成员初始化为相同的值之前,首先使用
memset()
将它们初始化为某个公共值,则它们也将与
memcmp()
进行相等比较(除非它们的成员也是结构,否则相同的限制将递归应用).

如果您确保在填充整个内存块之前对其进行初始化,例如使用
memset
,则可以保证它们是相同的:


编辑将其保留在此处,因为注释流很有用。

除了结构填充的明显情况之外,甚至不能保证对单个变量进行填充。见6.2.6.1(8)的脚注:

对象
x
y
可能具有相同的有效类型
T
在作为类型的对象访问时具有相同的值
T
,但在其他上下文中具有不同的值。特别是,如果
=
是为类型
T
定义的,那么
x==y
并不意味着
memcmp(&x,&y,sizeof(T))==0
。此外,
x==y
没有 必然意味着
x
y
具有相同的值;其他 对
T
类型的值的操作可以区分它们


我创建了一个例子,展示了其他答案提到的填充问题:。谢谢Michael,这是一个极好的例子。我没有投反对票,但我不认为C11 s6.7.9.10支持第一段。它看起来好像静态/全局变量的初始化是一系列将成员赋值为0或NULL的操作。如果这是正确的,s6.2.6.6建议任何填充字节将具有未定义的值,而该值不受语言语义的支持-填充字节总是采用未指定的值,这特别意味着编译器在分配给成员时可以自由覆盖环境填充;不知道在实践中会不会发生…@克里斯托夫:你确定吗?如果是这样,我甚至不想考虑在这样一个系统上有多少协议栈会突然中断。@user315052:当一个值存储在一个结构或联合类型的对象中,包括在一个成员对象中时,与任何填充字节相对应的对象表示的字节采用未指定的值(C11 6.2.6.1§6)@克里斯托夫:不过,我读了脚注,该短语的目的是允许使用
memcpy()
实现结构赋值。请注意,在重新阅读了标准的相关部分之后,我认为填充字节的值总是未指定的说法似乎是不正确的-它只有在存储到结构中(分配给结构或其成员)时才会失效-如果您按字节执行所有修改操作(强制转换为
char*
memcpy()
,…),填充字节应该保留它们的值。您可以对结构进行打包,这样它就不会在其中填充任何(未初始化的)位。这是一个很好的观点。一个具体的例子是浮点类型,其中+'ve和-'ve 0值比较相等,但具有不同的位模式。可能值得注意的是,浮点也提供了相反的情况:即取两个双精度
x=y=1.0/0
它们比较不相等,
x=y
,但具有
memcmp(&x,&y,sizeof(double))==0
memset(&struct1, 0, sizeof(my_struct))