【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 条评论
登录 后参与评论

相关文章

来自专栏Spark生态圈

[Spark SQL] 源码解析之Parser

Parser就是将SQL字符串切分成一个个Token,再根据一定语义规则解析为一棵语法树。我们写的sql语句只是一个字符串而已,首先需要将其通过词法解析和语法解...

812
来自专栏JAVA后端开发

activiti通过扩展点重写节点行为

在activit项目中,有时需要重写节点的behaviour,但如果将代码反编译,会为后续升级,及项目打包带为不方便。   其实 acitivit已经提供了扩...

735
来自专栏开发与安全

从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

一、boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源。关...

2160
来自专栏乐百川的学习频道

Powershell快速入门(二) Shell编程

这一部分着重于介绍Powershell的程序知识,让我们能够编写功能强大的Powershell脚本,执行比较复杂的任务。 变量 变量使用$变量名创建和引用。举个...

22110
来自专栏每日一篇技术文章

Swift3.0 - 异常错误

501
来自专栏Zephery

2017-03-01学习笔记

知识点 1.java中只有值传递,没有引用传递http://guhanjie.iteye.com/blog/1683637 2.final关键字 final修饰...

3408
来自专栏烂笔头

python类中super()和__init__()的区别

目录[-] 单继承时super()和init()实现的功能是类似的 class Base(object): def __init__(self): ...

3206
来自专栏王亚昌的专栏

lua中设置只读table

C++里有const用来定义常量,保护参数或函数意外地修改,提高程序的健壮性。在lua里虽然没有没有类似的关键字,我们可以用...

601
来自专栏Java帮帮-微信公众号-技术文章全总结

Java面试系列9

✎一、Java有没有goto? java中的保留字,现在没有在java中使用。 ✎二、必须要知道的运行时异常 ArithmeticException 是...

2464
来自专栏爱撒谎的男孩

Spring初体验

4086

扫描关注云+社区