会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 swap可以交换struct!
当前位置:首页 > 知识 > swap可以交换struct 正文

swap可以交换struct

时间:2026-10-17 06:35:19 来源:烟消火灭网 作者:综合 阅读:791次

上周帮同事调一段C代码,可交他写了个交换两个结构体的可交函数,跑出来数据全乱。可交我扫了一眼,可交他把结构体当数组名传进去了——swap(a,可交 b),结果函数里改的可交是副本,外面纹丝不动。可交这毛病太典型了,可交很多人对struct在内存里的可交样子没概念,以为传个名字就能改。可交

其实struct变量名就是可交个标签,跟int没本质区别。可交你写struct Point { int x; int y; };,可交声明Point p1,可交 p2;,p1和p2就是可交两块独立的内存。想交换它们,得把整块内存的内容倒过去。用临时变量最直接:

void swap(Point *a, Point *b) {  Point tmp = *a; *a = *b; *b = tmp; } 

注意这里传的是指针。C里所有函数参数都是值传递,传结构体本身会完整拷贝一份,你在函数里怎么折腾都影响不到外面。传指针就相当于告诉函数“东西在哪儿”,它顺着地址去改,才有效。

有人会想,那我自己写循环逐字节交换行不行?比如用char *把结构体当字节数组,一个字节一个字节倒。技术上可行,但坑很多。结构体可能有填充字节,编译器为了对齐会在成员之间塞空隙,你逐字节交换把填充也换了,虽然通常不影响成员值,但要是结构体里有指针、有联合体,或者被volatile修饰,这种操作就是未定义行为。我见过有人用memcpy加临时缓冲区来换,比逐字节安全,但依然绕不开对齐和类型问题。

最稳的还是直接赋值。C标准保证同类型结构体之间可以整体赋值,编译器会处理好所有细节,包括填充字节的复制方式。你写Point tmp = *a; *a = *b; *b = tmp;,三行搞定,可读性好,优化器还能把它变成几条机器指令,效率不差。结构体小的时候,比如两个int,编译器直接当两个寄存器操作;结构体大的时候,它会调用memcpy,但那是编译器内联的,比你手写快。

说到效率,有人担心大结构体交换开销大。确实,如果结构体里有几百字节的数组,三次赋值就是三次内存拷贝。但这是值语义的必然代价——你要交换内容,就得搬内容。真想避免拷贝,那就别交换结构体本身,交换指向结构体的指针。比如你有一组Point *,交换指针只改地址,不动数据,O(1)完成。这也是很多场景下更合理的做法:数据留在原地,只调整引用关系。

还有个细节,如果结构体里有数组成员,比如struct S { int arr[10]; };,整体赋值依然有效,因为数组是结构体的成员,跟着结构体一起复制。但如果你单独写int a[10], b[10];,就不能用a = b,得用memcpy或循环。这是数组和结构体的关键区别:数组名会退化,结构体名不会。

我见过一些代码库自己封装swap_struct宏,用do { ... } while(0)包起来,里面还是临时变量那套。没必要,直接写三行赋值最清楚。宏反而容易在传参时出副作用,比如swap_struct(p++, q)这种,展开后自增次数不对。

最后提一句C++。C++里std::swap对结构体默认就是三次移动或拷贝,跟C的手动写法一个逻辑。但如果结构体定义了移动构造函数,交换会变成移动,比拷贝快。C没有移动语义,只能老老实实拷贝。所以如果你在C里交换一个带大缓冲区的结构体,性能敏感的话,考虑改成指针交换,或者重新设计数据结构,别让大块数据频繁搬家。

总之,swap交换struct,核心就一句话:传指针,用临时变量整体赋值。别传值,别逐字节,别自己造轮子。编译器比你懂对齐和填充。

(责任编辑:时尚)

相关内容
  • 雅安渗透
  • 联想y7000开机legion进不了系统
  • 网站关键词营销
  • 河北大型反渗透净水设备价格
  • 给力赚官网登录入口
  • 中国音响发烧友网
  • 反渗透设备招标
  • 游戏网站链接大全
推荐内容
  • tcp许可证
  • exp是什么
  • jjj最新发布网
  • 腾讯qq币充值中心官网
  • 谷歌浏览器客服在线
  • 高频彩票网