C语言的奇技淫巧之二

本文首发于公众号:嵌入式软件实战派

11. 用异或运算实现数据交换

交换俩变量数据,一般做法是:

// 方法1
temp = a;
a = b;
b = temp;

// 方法2
a=a+b;
b=a-b;
a=a-b;

方法1需要第三个变量,方法二存在数据溢出可能,可以尝试下以下方法:

a = a ^ b;
b = a ^ b;
a = a ^ b;
12. 判断语句中把const数值放在前面

通常条件语句写成

if(n == 0){ /*...*/ }

但是,有可能手误写成

if(n = 0){ /*...*/ }

这种错误只有机器在运行时候知道,而人不一定能发现这种bug。
把数值放在前面就不怕了,==写成=,编译器就知道

if(0 == n){ /*...*/ }
13. 用冒号表达式替代if...else...语句

这个用法应该很普遍了,不算什么特别的技巧了。

if(y < 0)
{
    x = 10;
}
else
{
    x = 20;
}

可以改成以下一行代码即可

x = (y < 0) ? 10 : 20;
14. 判断一个整数是否为2的幂

也许你会不断地将这个数除以2,除到底,然而Linux kernel有个巧妙的办法:

#define is_power_of_2(n) ((n) != 0 && ((n) & ((n) - 1)) == 0)

((n) & ((n) - 1)) == 0这个不理解?那先想想2的X次方的值的二进制是怎样的。

15. 静态链表

直接看代码

    struct mylist {
        int a;
        struct mylist* next;
    };
    #define cons(x, y) (struct mylist[]){{x, y}}
    struct mylist *list = cons(1, cons(2, cons(3, NULL)));
    struct mylist *p = list;
    while(p != 0) {
        printf("%d\n", p->a);
        p = p -> next;
    };
16. 柔性数组
#include <stdlib.h>
#include <string.h>

struct line
{
    int length;
    char contents[0];
};
struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

struct f1 { int x; int y[]; } f1 = { 1, { 2, 3, 4 } }; 
struct f2 { struct f1 f1; int data[3]; } f2 = { { 1 }, { 2, 3, 4 } };

详见6.18 Arrays of Length Zero

17. 数组之间直接赋值
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int b[10] = {0};
b = a;

这样是非法的,但是你可以放数组穿个马甲:

typedef struct
{
    int n[10];
}S;
S a = {{0,1,2,3,4,5,6,7,8,9}};
S b = {0};
b = a;
18. #include的不一定是要.h文件

#include后面跟的可以是任意后缀的,但文件内容一定要是合法的。不信?你试试这个:

  // plus.fxxk
  int plus(int a, int b)
  {
      return a+b;
  }
  // main.c
  #include <stdio.h>
 
  int a = 1, b = 1;
 
  #include "plus.fxxk"
 
  int main(void)
  {
      printf("plus %d + %d = %d\n", a, b, plus(a,b));
      return 0;
  }
19. 自动获取变量类型
#define var(left, right) __typeof__(right) left = (right)

var(s, 1LL); // 相当于 long long s = 1LL;

是不是有点像C++ 11的auto类型?

20. 宏定义函数MIN(x,y)的终极做法
#define MIN(x, y)   x < y? x : y    // 这样给0分

#define MIN(x, y)   (x < y? x : y)  // 这样给50分
// 不信你试试这个
int n = 3 * MIN(3, 4 < 5 ? 4 : 5);

#define MIN(x, y)   ((x) < (y)? (x) : (y))  // 这个给90分
// 不信你试试这个
double xx = 1.0;
double yy = MIN(xx++, 1.5);
printf("xx=%f, yy=%f\n",xx,yy);

// 以下放大招了,看看GNU的
#define MIN(A,B)	({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
double xx = 1.0;
double yy = MIN(xx++, 1.5);
printf("xx=%f, yy=%f\n",xx,yy);

未完待续……

我打算写100条,你还不关注我?
在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值