龙空技术网

结构体对象赋值会发生你想不到的事

老一辈也说说 166

前言:

如今看官们对“c语言结构体怎么赋值”可能比较重视,我们都想要分析一些“c语言结构体怎么赋值”的相关内容。那么小编同时在网络上搜集了一些关于“c语言结构体怎么赋值””的相关内容,希望你们能喜欢,看官们一起来学习一下吧!

编程新手经常有疑惑,结构体对象到底能不能直接赋值呢?有的人会只直接说不能赋值,但具体原因不清楚,而有的程序员自己写了测试代码,发现直接赋值,程序并没有出错。

先给大家介绍下,结构体赋值的方法,总有一个是你困惑的。例如结构体

typedef struct

{

int a;

char b[2];

} MSG;

结构体赋值方式1,逐个成员赋值

MSG msg;

msg.a = 1;

msg.b[0] = 'a';

msg.b[1] = 'b';

结构体赋值方式2,定义时赋值

MSG msg = {1,{2,3}};

结构体赋值方式3,C99支持的定义时赋值

MSG msg = {

.a = 1,

.b = {4,5},

};

结构体赋值方式4,GCC2.5前支持,现在已经不支持

MSG msg = {

.a : 1,

.b : {4,5},

};

结构体赋值方式5,memcpy赋值

MSG msg = {1,{2,3}};

MSG it_msg;

memcpy(&it_msg, &msg, sizeof(MSG));

结构体赋值方式6,本文开头说的对象赋值

MSG msg = {1,{2,3}};

MSG it_msg;

it_msg = msg

好学的新手,一定会把这些方式一一尝试个遍,除了方式4,其他的方式应该都能正常工作,那个程序中应该使用哪种方式好呢?对于结构体的初始化,推荐新手使用方式2,相较于方式1与方式3,这种方式代码量少,并且通用性强,不需要考虑编译器是否支持C99。但是,它有个缺点粗心的新手会漏赋值。

那非初始化的赋值选择哪种方式呢? 如果是完全复制则选择方式5,如果是部分成员赋值则选方式1。

方式6看起来非常简洁,通过反汇编,实际上也是一个一个成员赋值,相当于代替我们写了方式1的代码。

0x080483ff <+59>: mov $0x80484e4,%eax

0x08048404 <+64>: mov %ecx,0x8(%esp)

0x08048408 <+68>: mov %edx,0x4(%esp)

0x0804840c <+72>: mov %eax,(%esp)

但不能使用此方式,方式6在一般的程序中都是没有问题,但是方式6代码运行在不支持奇地址访问cpu环境上,有可能引起异常。

msg_copy(MSG *msg)

{

it_msg = msg

}

例如,上面代码由于msg有可能是来自若个内存,并且msg指向奇地址时会导致cpu发生奇地址访问。

标签: #c语言结构体怎么赋值 #c语言结构体赋值 点成员赋值法