1. 示例一
先看下如下代码,思考一下,结果是输出a == b
还是a != b
?
1#include <stdio.h>
2#include <string.h>
3
4struct test_type {
5 char name[10];
6 int i;
7 long l;
8};
9
10int main(void)
11{
12 struct test_type a = {
13 "test", 1, 2
14 };
15 struct test_type b;
16
17 b.i = a.i;
18 b.l = a.l;
19 strcpy(b.name, a.name);
20
21 if (0 == memcmp(&a, &b, sizeof(struct test_type))) {
22 printf("a == b\n");
23 } else {
24 printf("a != b\n");
25 }
26
27 return 0;
28}
1.1. 结果及分析
实际结果很可能是a != b
。
注意到strcpy(b.name, a.name)
,由于a.name
是"test"
,字符串长度比10要小,strcpy
只是复制了a.name
的一部分到b.name
,所以两者会存在不相等的情况。
2. 示例二
我们把strcpy(b.name, a.name)
改成memcpy(b.name, a.name, sizeof(a.name))
,来看一下,代码如下。
1#include <stdio.h>
2#include <string.h>
3
4struct test_type {
5 char name[10];
6 int i;
7 long l;
8};
9
10int main(void)
11{
12 struct test_type a = {
13 "test", 1, 2
14 };
15 struct test_type b;
16
17 b.i = a.i;
18 b.l = a.l;
19 memcpy(b.name, a.name, sizeof(a.name));
20
21 if (0 == memcmp(&a, &b, sizeof(struct test_type))) {
22 printf("a == b\n");
23 } else {
24 printf("a != b\n");
25 }
26
27 return 0;
28}
2.1. 结果及分析
然而,实际结果很可能还是a != b
。
这里涉及到编译器对结构体的处理,为了提高访问性能,编译器会对结构体成员地址进行对齐。对于64位系统来说,int
型变量的地址通常要4字节对齐,long
型变量的地址通常要8字节对齐。而name
数组大小是10,为了满足4字节对齐,i
前要留出2字节的空洞。而空洞的内容是不确定的,这就导致了对比结果显示a != b
。
不过要注意的是,大多数编译器对long
型变量也是4字节对齐,所以l
前通常不会有空洞。
3. 总结
在编码中,如果要使用memcmp
来比较结构体,在声明变量时,要保证使用memset
来进行初始化,否则就不用直接使用memcmp
来进行比较。