#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;
}
弄着玩的, 不实用, 还有一些类型懒得写了。 ^_^。
26 个解决方案
#1
x,y的类型必须一样吗?如果类型实际大小小于int(比如short),你的程序可能会非法访问内存。
#2
所有类型都可以通用吗???
字符类型、short类型不行啊。。
字符类型、short类型不行啊。。
#3
这不告诉你们, 还有些情况没有写吗? 主要是看中思想, 如果你用void 加个循环, 那什么都可以了.(最大的也就是16 字节 ------ C 的标准类型.)
#4
...写模板吧,如果楼主闲着发慌的话
问题一大堆,你这样写,遇上自定义类型就完蛋
问题一大堆,你这样写,遇上自定义类型就完蛋
#5
无奈, 不懂 C++
#6
楼主丢脸了, 怎么不去看看stdlib.h里的qsort,bsearch呢? 我非常瞧不起闭门造车的人.
[User:root Time:14:04:40 Path:/home/liangdong/c]$ ./output
3.000000 2.000000
[User:root Time:14:04:41 Path:/home/liangdong/c]$ cat src/main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int swap(void *left, void *right, size_t len) {
if (!len) {
return -1;
}
void *temp = malloc(len);
memcpy(temp, left, len);
memcpy(left, right, len);
memcpy(right, temp, len);
free(temp);
return 0;
}
int main(int argc, char* const argv[]) {
double a = 2;
double b = 3;
swap(&a, &b, sizeof(a));
printf("%lf %lf\n", a, b);
return 0;
}
#7
这个我也想到了。 请看#3 楼回复。
再者, 对于我这个新手来说, 确实水平有限。
#8
华丽的外表下面不一定是美丽的灵魂
#9
如果是c++的话,而且你的编译器支持c++0x
可以利用下 decltype
可以利用下 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;
}
#10
#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
#11
赵老....你这个程序有语法错误.
#12
不懂,为什么要while(0)?如果只执行一次,要循环干吗呢?
#13
块作用域和分号问题,方便放在if里面之类……
#14
UB就别拿出来丢人现眼了。
#15
因为“驾船出海时一定只带一个指南针。”
所以我“编写C程序时一定只用VC6.0一个IDE。”
(^_^)
#16
我说的是语法错误...不是未定义行为,我没能力说服你这是未定义行为的....
稍微正常点的"指南针"都会指出这种错误.
#17
反正我这枚“指南针”编译链接没有语法错误。
(^_^)
#18
那你以后就说清楚点,凡是说“用C语言写”的地方你都用VC6代替。
#19
劝 LZ 早点放弃写通用宏这种努力。C 宏缺乏类型检查的弊病早成定论,无需讨论。若执意强用,必然在某时候自己被自己搬起的石头砸到脚。看看标准头文件里,像 abs, labs, fabs 等等,谁高兴这样写,还有整个标准库连个好用的 max 都无法提供,要自己做,但没办法为了可移植性只好如此。(不像某个人明明无知却爱端架子教训别人的样子。。。)就是从 C 脱胎的 C++ 用了模板和内联函数等方案来解决这个问题,也不见得有多高明,副作用不小,例如代码膨胀和分离编译困难等。扯远了啊。。哈哈!贴个我写的。
#include <assert.h>尽管不可谓不用心,但 LZ 能否看出代码里错漏百出啊。
#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;
}
#20
楼上还是想开点吧。这年头“有点文化的流氓无赖”是最让你咬牙切齿却又无可奈何的。推荐用业界内有名的 pc-lint 这个指南针让他原形毕露吧。鼠目寸光、敝帚自珍,却又好断章取义、好端架子教训人的家伙。擦!不说了,省的污染版面了。
只可惜了坛子里的那些孜孜不倦的懵懂少年们哪!
只可惜了坛子里的那些孜孜不倦的懵懂少年们哪!
#21
讲得好,无论是关于LZ的题目的讲解,或是其它内容
#22
怎么到现在大家都不肯指点一下赵老师 swap 不能这么写啊:
(a)^=(b)^=(a)^=(b)
#23
没问题的,这是最简洁的写法。前提是^操作要合法。
#24
18 楼来给他科普一下 sequence point 吧
#25
好方法,我得试试。
#26
合法的程序不见得是正确的程序。
连续的sequence point之间修改同一个对象超过一次,引起undefined behavior,程序行为无法预测。
#1
x,y的类型必须一样吗?如果类型实际大小小于int(比如short),你的程序可能会非法访问内存。
#2
所有类型都可以通用吗???
字符类型、short类型不行啊。。
字符类型、short类型不行啊。。
#3
这不告诉你们, 还有些情况没有写吗? 主要是看中思想, 如果你用void 加个循环, 那什么都可以了.(最大的也就是16 字节 ------ C 的标准类型.)
#4
...写模板吧,如果楼主闲着发慌的话
问题一大堆,你这样写,遇上自定义类型就完蛋
问题一大堆,你这样写,遇上自定义类型就完蛋
#5
无奈, 不懂 C++
#6
楼主丢脸了, 怎么不去看看stdlib.h里的qsort,bsearch呢? 我非常瞧不起闭门造车的人.
[User:root Time:14:04:40 Path:/home/liangdong/c]$ ./output
3.000000 2.000000
[User:root Time:14:04:41 Path:/home/liangdong/c]$ cat src/main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int swap(void *left, void *right, size_t len) {
if (!len) {
return -1;
}
void *temp = malloc(len);
memcpy(temp, left, len);
memcpy(left, right, len);
memcpy(right, temp, len);
free(temp);
return 0;
}
int main(int argc, char* const argv[]) {
double a = 2;
double b = 3;
swap(&a, &b, sizeof(a));
printf("%lf %lf\n", a, b);
return 0;
}
#7
这个我也想到了。 请看#3 楼回复。
再者, 对于我这个新手来说, 确实水平有限。
#8
华丽的外表下面不一定是美丽的灵魂
#9
如果是c++的话,而且你的编译器支持c++0x
可以利用下 decltype
可以利用下 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;
}
#10
#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
#11
赵老....你这个程序有语法错误.
#12
不懂,为什么要while(0)?如果只执行一次,要循环干吗呢?
#13
块作用域和分号问题,方便放在if里面之类……
#14
UB就别拿出来丢人现眼了。
#15
因为“驾船出海时一定只带一个指南针。”
所以我“编写C程序时一定只用VC6.0一个IDE。”
(^_^)
#16
我说的是语法错误...不是未定义行为,我没能力说服你这是未定义行为的....
稍微正常点的"指南针"都会指出这种错误.
#17
反正我这枚“指南针”编译链接没有语法错误。
(^_^)
#18
那你以后就说清楚点,凡是说“用C语言写”的地方你都用VC6代替。
#19
劝 LZ 早点放弃写通用宏这种努力。C 宏缺乏类型检查的弊病早成定论,无需讨论。若执意强用,必然在某时候自己被自己搬起的石头砸到脚。看看标准头文件里,像 abs, labs, fabs 等等,谁高兴这样写,还有整个标准库连个好用的 max 都无法提供,要自己做,但没办法为了可移植性只好如此。(不像某个人明明无知却爱端架子教训别人的样子。。。)就是从 C 脱胎的 C++ 用了模板和内联函数等方案来解决这个问题,也不见得有多高明,副作用不小,例如代码膨胀和分离编译困难等。扯远了啊。。哈哈!贴个我写的。
#include <assert.h>尽管不可谓不用心,但 LZ 能否看出代码里错漏百出啊。
#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;
}
#20
楼上还是想开点吧。这年头“有点文化的流氓无赖”是最让你咬牙切齿却又无可奈何的。推荐用业界内有名的 pc-lint 这个指南针让他原形毕露吧。鼠目寸光、敝帚自珍,却又好断章取义、好端架子教训人的家伙。擦!不说了,省的污染版面了。
只可惜了坛子里的那些孜孜不倦的懵懂少年们哪!
只可惜了坛子里的那些孜孜不倦的懵懂少年们哪!
#21
讲得好,无论是关于LZ的题目的讲解,或是其它内容
#22
怎么到现在大家都不肯指点一下赵老师 swap 不能这么写啊:
(a)^=(b)^=(a)^=(b)
#23
没问题的,这是最简洁的写法。前提是^操作要合法。
#24
18 楼来给他科普一下 sequence point 吧
#25
好方法,我得试试。
#26
合法的程序不见得是正确的程序。
连续的sequence point之间修改同一个对象超过一次,引起undefined behavior,程序行为无法预测。