宏定义swap(x, y) 实现任何数据类型交换。

gfzeng 2012-06-01 02:56:58

#ifndef _SWAP_H
#define _SWAP_H

#define swap(x, y) \
{ \
if (sizeof(x) == sizeof(int)) { \
int *_p1 = (int *) &x; \
int *_p2 = (int *) &y; \
*_p1 ^= *_p2; \
*_p2 ^= *_p1; \
*_p1 ^= *_p2; \
} else { \
long long *_p1 = (long long *) &x; \
long long *_p2 = (long long *) &y; \
*_p1 ^= *_p2; \
*_p2 ^= *_p1; \
*_p1 ^= *_p2; \
} \
}

#endif

#include "swap.h"
#include <stdio.h>

int
main(void)
{
int i = 3;
int j = 4;
printf("i = %d, j = %d\n", i, j);
swap(i, j);
printf("i = %d, j = %d\n", i, j);

float pi = (float) 3.14159;
float e = (float) 2.71828;
printf("pi = %f, e = %f\n", pi, e);
swap(pi, e);
printf("pi = %f, e = %f\n", pi, e);

double g = 6.67259;
double c = 2.9979;
printf("g = %lf, c = %lf\n", g, c);
swap(g, c);
printf("g = %lf, c = %lf\n", g, c);
return 0;
}



弄着玩的, 不实用, 还有一些类型懒得写了。 ^_^。
...全文
2208 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
lwouyang 2012-06-02
  • 打赏
  • 举报
回复
劝 LZ 早点放弃写通用宏这种努力。C 宏缺乏类型检查的弊病早成定论,无需讨论。若执意强用,必然在某时候自己被自己搬起的石头砸到脚。看看标准头文件里,像 abs, labs, fabs 等等,谁高兴这样写,还有整个标准库连个好用的 max 都无法提供,要自己做,但没办法为了可移植性只好如此。(不像某个人明明无知却爱端架子教训别人的样子。。。)就是从 C 脱胎的 C++ 用了模板和内联函数等方案来解决这个问题,也不见得有多高明,副作用不小,例如代码膨胀和分离编译困难等。扯远了啊。。哈哈!贴个我写的。
#include <assert.h>
#include <stdio.h>
#include <mem.h>

#define SWAP(a, b) \
do { \
char temp[sizeof(a)]; \
assert(sizeof(a) == sizeof(b)); \
MY_TINY_MEMCPY((void*)temp, &(a), sizeof(a)); \
(a) = (b); \
(b) = (a); \
MY_TINY_MEMCPY(&(b), (void*)temp, sizeof(a)); \
} while(0)

#define MY_TINY_MEMCPY(dest, src, len) \
((len) == sizeof(char) ? (void)(*(char*)(dest) = *(char*)(src)) : \
(len) == sizeof(short) ? (void)(*(short*)(dest) = *(short*)(src)) : \
(len) == sizeof(int) ? (void)(*(int*)(dest) = *(int*)(src)) : \
(len) == sizeof(long) ? (void)(*(long*)(dest) = *(long*)(src)) : \
(len) == sizeof(float) ? (void)(*(float*)(dest) = *(float*)(src)) : \
(len) == sizeof(double) ? (void)(*(double*)(dest) = *(double*)(src)) : \
(void)memcpy((dest), (src), (len)))

int main()
{
int i_a = 1, i_b = 2;
long lval = 3;
float fval = 4.0f;
double dval = 5.0;
void* pval = (void*)0x1234;
struct { char name[10]; void* next; } node1 = {"abcd"}, node2 = {"efg"};
union { double d; void* p; } u1, u2;

SWAP(i_a, i_b);
SWAP(fval, dval);
SWAP(node1, node2);
SWAP(u1, u2);
SWAP(lval, pval); // error!
SWAP(lval, fval); // error!

return 0;
}
尽管不可谓不用心,但 LZ 能否看出代码里错漏百出啊。
proorck6 2012-06-02
  • 打赏
  • 举报
回复
好方法,我得试试。
fallening 2012-06-02
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 的回复:]

没问题的,这是最简洁的写法。前提是^操作要合法。
引用 22 楼 的回复:

怎么到现在大家都不肯指点一下赵老师  swap 不能这么写啊:
C/C++ code
(a)^=(b)^=(a)^=(b)
[/Quote]

18 楼来给他科普一下 sequence point 吧
mars_man 2012-06-02
  • 打赏
  • 举报
回复
没问题的,这是最简洁的写法。前提是^操作要合法。
[Quote=引用 22 楼 的回复:]

怎么到现在大家都不肯指点一下赵老师  swap 不能这么写啊:
C/C++ code
(a)^=(b)^=(a)^=(b)
[/Quote]
FrankHB1989 2012-06-02
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 的回复:]

没问题的,这是最简洁的写法。前提是^操作要合法。
引用 22 楼 的回复:

怎么到现在大家都不肯指点一下赵老师  swap 不能这么写啊:
C/C++ code
(a)^=(b)^=(a)^=(b)
[/Quote]
合法的程序不见得是正确的程序。
连续的sequence point之间修改同一个对象超过一次,引起undefined behavior,程序行为无法预测。
fallening 2012-06-02
  • 打赏
  • 举报
回复
怎么到现在大家都不肯指点一下赵老师  swap 不能这么写啊:
(a)^=(b)^=(a)^=(b)
CandPointer 2012-06-02
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 的回复:]

劝 LZ 早点放弃写通用宏这种努力。C 宏缺乏类型检查的弊病早成定论,无需讨论。若执意强用,必然在某时候自己被自己搬起的石头砸到脚。看看标准头文件里,像 abs, labs, fabs 等等,谁高兴这样写,还有整个标准库连个好用的 max 都无法提供,要自己做,但没办法为了可移植性只好如此。(不像某个人明明无知却爱端架子教训别人的样子。。。)就是从 C 脱胎的 C++ 用了模板和内联函数等方案来……
[/Quote]

讲得好,无论是关于LZ的题目的讲解,或是其它内容
lwouyang 2012-06-02
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]

引用 15 楼 的回复:
引用 11 楼 的回复:
引用 10 楼 的回复:
C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&amp;amp;amp;(a))!=(&amp;amp;amp;(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1……
[/Quote]楼上还是想开点吧。这年头“有点文化的流氓无赖”是最让你咬牙切齿却又无可奈何的。推荐用业界内有名的 pc-lint 这个指南针让他原形毕露吧。鼠目寸光、敝帚自珍,却又好断章取义、好端架子教训人的家伙。擦!不说了,省的污染版面了。
只可惜了坛子里的那些孜孜不倦的懵懂少年们哪!
hackbuteer1 2012-06-01
  • 打赏
  • 举报
回复
所有类型都可以通用吗???
字符类型、short类型不行啊。。
FrankHB1989 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]

引用 11 楼 的回复:
引用 10 楼 的回复:
C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&amp;amp;(a))!=(&amp;amp;(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=……
[/Quote]
那你以后就说清楚点,凡是说“用C语言写”的地方你都用VC6代替。
cryingbee 2012-06-01
  • 打赏
  • 举报
回复
x,y的类型必须一样吗?如果类型实际大小小于int(比如short),你的程序可能会非法访问内存。
赵4老师 2012-06-01
  • 打赏
  • 举报
回复

反正我这枚“指南针”编译链接没有语法错误。
(^_^)
iamnobody 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]
引用 11 楼 的回复:
引用 10 楼 的回复:
C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&amp;amp;(a))!=(&amp;amp;(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 ……
[/Quote]

我说的是语法错误...不是未定义行为,我没能力说服你这是未定义行为的....

稍微正常点的"指南针"都会指出这种错误.
赵4老师 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
引用 10 楼 的回复:
C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&amp;(a))!=(&amp;(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
short s1=1 ,……
赵老....你这个程序有语法错误.
[/Quote]
因为“驾船出海时一定只带一个指南针。”
所以我“编写C程序时一定只用VC6.0一个IDE。”
(^_^)
FrankHB1989 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
short s1=1 , s2=2 ;
in……
[/Quote]
UB就别拿出来丢人现眼了。
FrankHB1989 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hjf004 的回复:]

引用 10 楼 的回复:

C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&amp;(a))!=(&amp;(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
……
[/Quote]
块作用域和分号问题,方便放在if里面之类……
pupa 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
short s1=1 , s2=2 ;
in……
[/Quote]
不懂,为什么要while(0)?如果只执行一次,要循环干吗呢?
iamnobody 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
C/C++ code
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
short s1=1 , s2=2 ;……
[/Quote]

赵老....你这个程序有语法错误.


赵4老师 2012-06-01
  • 打赏
  • 举报
回复
#include <stdio.h>
#define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0)
char *p1="1" ,*p2="2" ;
char c1=1 , c2=2 ;
short s1=1 , s2=2 ;
int i1=1 , i2=2 ;
__int64 I1=1i64, I2=2i64;
float f1=1.0f, f2=2.0f;
double d1=1.0 , d2=2.0 ;
void main() {
SWAP((int)p1,(int)p2); printf("char * %5s, %5s\n",p1,p2);
SWAP(c1,c2); printf("char %5d, %5d\n",c1,c2);
SWAP(s1,s2); printf("short %5d, %5d\n",s1,s2);
SWAP(i1,i2); printf("int %5d, %5d\n",i1,i2);
SWAP(I1,I2); printf("__int64 %5I64d,%5I64d\n",I1,I2);
SWAP(*(int *)&f1,*(int *)&f2);printf("float %5g, %5g\n",f1,f2);
SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double %5lg, %5lg\n",d1,d2);

SWAP(c1,c1);
printf("%d\n",c1);
}
//char * 2, 1
//char 2, 1
//short 2, 1
//int 2, 1
//__int64 2, 1
//float 2, 1
//double 2, 1
//2
星羽 2012-06-01
  • 打赏
  • 举报
回复
如果是c++的话,而且你的编译器支持c++0x
可以利用下 decltype


#define _swap(x, y) \
do \
{ \
decltype(x) t = (x); \
(x) = (y); \
(y) = (t); \
} while (false);

struct st
{
int i;
float f;
short s;
};

int main()
{
int a = 0;
int b = 1;
_swap(a, b);

st s0;
s0.i = 0;
s0.f = 0.f;
s0.s = 0;

st s1;
s1.i = 1;
s1.f = 2.f;
s1.s = 3;
_swap(s0, s1);

return 0;
}

加载更多回复(6)

69,396

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧