C语言编程 行为鉴赏

不使用 IF/ELSE

bool值的判定

左值目标相同, 右值目标不同

背景

经常有些地方, 需要将一些字段输出,
这些字段, 有的时候是很多个, 有的时候是1个, 有的时候没有
输出的时候,为了便于阅读,
当字段个数为空时, 不输出
当字段个数只有1各时, 仅输出字段的内容
当字段个数超过1个时, 每个字段之间使用分隔符隔开

假设分隔符是: “,”
当出现
字段1: Hello
直接输出:Hello

当出现
字段1: Hello: 字段2:World
直接输出:Hello,World

代码

代码中有关内存安全, 代码风格的问题, 暂不讨论,
仅供展示, 不使用 IF/ESLE 也能达到 判断行为的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[root@localhost source]# cat main.c
#include "stdio.h"
#include "string.h"

int append(char *buff, int index, const char *str)
{
int len = strlen(str);
memcpy(buff + index, str, len);
return len;
}

int append_first(char *buff, int index, const char *str)
{
return append(buff, index, str);
}

int append_more(char *buff, int index, const char *str)
{
index += append(buff, index, ",");
index += append(buff, index, str);
return index;
}

//void show_code(const char **str, int (*func[])(char *buff, int index, const char *str)) //等效
void show_code(const char **str, int (*(*func))(char *buff, int index, const char *str))
{
char buff[1024];
int index = 0;

for(int i = 0; str[i]; i++)
{
int select = !!i;
index += func[select](buff, index, str[i]);
}
buff[index] = '\0';

printf("[%s]\n", buff);
}

int main()
{
int (*func[])(char *buff, int index, const char *str) = {
append_first,
append_more,
NULL,
};

const char *str1[]={"Hello", NULL,};
const char *str2[]={"Hello", "World", NULL,};

show_code(str1, func);
show_code(str2, func);

return 0;
}
[root@localhost source]#

这种形式只能判断 0/1+ 的状态,
其他状态不能判断,
如 i > 42 之类的, 就不可以。

运行

1
2
3
4
[root@localhost source]# gcc -std=c99 -Wall  main.c  && ./a.out 
[Hello]
[Hello,World]
[root@localhost source]#

bool值的判定

右值目标相同, 左值目标不同

引用的是linus 在TED 演讲过程的例子

单向链表的节点删除操作, 此处用了一个 IF/ELSE

修改后的代码, 没有IF/ELSE

没有IF/ELSE 利于代码的高效执行

大小的判定

无分支 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@localhost ~]# cat gcc.c
#include <stdio.h>

int max(int a, int b)
{
int index[]={a, b};
return index[a < b];
}

int min(int a, int b)
{
int index[]={a, b};
return index[a > b];
}

int main(int a, char **b)
{
printf("max=%u\n", max(0,0));
printf("max=%u\n", max(9,1));
printf("max=%u\n", max(2,7));
printf("min=%u\n", min(6,6));
printf("min=%u\n", min(6,1));
printf("min=%u\n", min(6,7));
}
[root@localhost ~]# gcc gcc.c && ./a.out
max=0
max=9
max=7
min=6
min=1
min=6
[root@localhost ~]#