【C语言基础】结构体赋值

结构体在 C 程序中使用的较为频繁,能对数据有一定的封装的作用。对一个结构体赋值时,经常采用的方式是,分别对其成员变量赋值。那么能否将一个结构体用赋值号(“=”)直接赋值给另一个结构体呢?网上的答案不一,有说可以的,有说不可以的,有说这样的话两个结构体共用一块内存空间。我们可以从汇编语言的角度来看这个问题,测试程序:

//test.c

#include <stdio.h>

int main() { struct foo { int a;

int b[5];

int *c; } x, y; x.a = 666; x.b[0] = 555; x.c = NULL; y = x;

return 0; }

程序定义了结构体 foo,它有3个成员变量:int 型数据 a、int 数组 b、int 指针 c,以观察是否对不同类型的成员有不同的处理。使用 gcc 将其编译:

gcc -S -masm=intel test.c

编译时并没有报错,说明编译器接受这种赋值方式,但赋值时具体发生了什么?打开其输出的汇编文件,关键部分为:

mov DWORD PTR [esp+36], 666

mov DWORD PTR [esp+40], 555

mov DWORD PTR [esp+60], 0

lea edx, [esp+8] lea ebx, [esp+36]

mov eax, 7

mov edi, edx

mov esi, ebx

mov ecx, eax rep movsd

前面3条 mov 语句为给成员变量赋值的语句;中间两条 lea 语句得到了两块内存空间的偏移地址,第一块为新的内存空间,第二块为结构体 x 占有的内存空间;后面4条 mov 语句,第1、4条作用为把7赋给 ecx,第2条为把新内存空间地址赋给 edi,第3条为把 x 内存空间地址赋给 esi。关键在于最后一条语句:rep movsd。 movsd 是一个串传送指令,其英文为 move string dword,具体作用为以 esi(Source Index)为源地址,以 edi(destination Index)为目的地址,将源地址处一个双字(dword)内容复制到目的地址。然后根据方向标志位 DF 的值,DF = 0,esi 与 edi 自增4,DF = 1,esi与edi自减4(dword 占用4个字节)。(但此处并没有使用 CLD 设置 DF 值,默认为0?)rep 可以根据 ecx 的值,重复执行 ecx 次 movsd 指令。 这样的话,rep movsd 指令的作用是,将 esi 处的7个 dword 复制到 edi 处,而 foo 结构体正好占用4*7个字节(此处没有对齐的问题)。于是,x 的内容便被复制到了另一块相同大小的内存中,我们基本可以确定,这块空间就是 y 所占的空间。 因此,我们可以得出结论,结构体可以直接赋值,且赋值的结果是将赋值号左边的结构体中的内容原原本本的复制到赋值号右边的结构体中,并没有共用同一块内存空间。

转自:http://blog.csdn.net/imred/article/details/45588477

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2018-02-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术/开源

从C#到TypeScript - Promise

从C#到TypeScript - Promise 背景 相信之前用过JavaScript的朋友都碰到过异步回调地狱(callback hell),N多个回调的嵌...

2018
来自专栏互联网技术栈

《Effective Java 》系列一

编写实例受控类有几个原因。实例受控使得类可以确保他是一个Singleton或者是不可实例化的。他还使得不可变类可以确保不会存在两个相等的实例。

1594
来自专栏闪电gogogo的专栏

【数据结构(C语言版)系列三】 队列

队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一...

2422
来自专栏顶级程序员

全面深入理解Python面向对象编程

面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。

1805
来自专栏向治洪

Android热补丁技术—dexposed原理简析(手机淘宝采用方案)

上篇文章《Android无线开发的几种常用技术》我们介绍了几种android移动应用开发中的常用技术,其中的热补丁正在被越来越多的开发团队所使用,它涉及到da...

2456
来自专栏chenssy

你真的了解try{ return }finally{}中的return?

刚看到这个问题后。突然发现基础不够扎实,居然来第一个都答不出来。。。(不知道还有木有和我也一样也回答不出以上的问题的? 如果有请在评论里告诉我一声,让我知道,我...

805
来自专栏java一日一条

代码优化那些事

/**************************************************************************/

573
来自专栏java学习

面试题63(链表,哈希表)

关于链表,哈希表 1·以下关于链式存储结构的叙述中哪一个是正确的? A.链式存储结构不是顺序存取结构 B.逻辑上相邻的节点物理上必须邻接 C.可以通过计算直接确...

3086
来自专栏JavaQ

多参数方法进阶

很多高级工程师还在写包含N个参数的方法、使用setter方法构造实例,其实这些方式都是过时并且有很大缺陷的,本篇将深入讲解这些问题及解决方法。 多参数方法的问题...

33611
来自专栏编程一生

PHP开发人员对JAVA的WEB开发入门(初版-基础知识)

1174

扫码关注云+社区