C 语言小技巧
C 语言有许多可以提高编程效率,简化代码,提高代码可读性的小技巧。这里列出几个小技巧及其应用,抛砖引玉,供大家参考。
逗号运算符
C 语言提供了一种特殊的运算符——逗号运算符,又称顺序求值运算符,可以用它将两个表达式连接起来。
逗号表达式的一般形式如下:
Exp1, Exp2
其计算过程为:
先计算 Exp1
,再计算 Exp2,然后将 Exp2
的返回值作为整个逗号表达式的值。
如 1+1, 2+2
,这个表达式的值是 4。
需要注意,逗号运算符的优先级是所有运算符中最低的,比如:
a = 1 + 2, 3 * 4;
表示将变量 a
赋值为 1+2
,然后计算 3*4
作为整个表达式的值,但这个值并没有被使用。
所以,这个表达式有什么用呢?
可以看以下几个例子:
#include <stdio.h>
int main() {
int n;
while (scanf("%d", &n), n) {
printf("%d\n", n);
}
return 0;
}
如果不用逗号表达式,上述代码就需要写成:
#include <stdio.h>
int main() {
int n = 1;
while (n) {
scanf("%d", &n);
printf("%d\n", n);
}
return 0;
}
还有:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for (int i = 0, j = n; i < j; ++i, --j) {
printf("%d %d %d\n", n, i, j);
}
return 0;
}
如果不用逗号表达式,上述代码就需要写成:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for (int i = 0, j = n; i < j; ++i) {
printf("%d %d %d\n", n, i, j);
--j;
}
return 0;
}
多了一行……好吧,实际上都没有多多少代码,但能少一行是一行嘛,并且,这样写代码的可读性提高了不少。
数组的部分初始化
当我们声明一个数组并对其进行初始化时,我们可以仅对其部分进行初始化,如:
int arr[] = {[1]=5, [5]=10, [2]=20};
int arr2[] = {[0 ... 9] = 10, [10 ... 19] = 20, [20 ... 29] = 30};
上面的例子很简单,应该没有什么可说的,这也算是 C 语言的一个很少有人知道的一个小特性吧。
C 语言的预处理器
C 语言的预处理器不是编译器的组成部分,而是编译过程中一个单独的步骤。实际上,我们可以把它理解为一个在开始编译源码之前的一个文本替换工具。最常用的预处理指令就是 #include
,用于包含另一个源码文件,当我们在程序开头加上下面这行时,
#include <stdio.h>
预处理器就会在程序开始的地方引入 stdio.h
的全部内容,这样我们就可以使用这个头文件中包含的函数了。
另一个常用的预处理指令就是 #define
,定义宏,如
#define PI 3.1415927
实际上就是将下面所有出现 PI
的地方替换为 3.1415927
。
完整的预处理指令如下:
指令 | 描述 |
---|---|
#define | 定义宏 |
#include | 包含一个源代码文件 |
#undef | 取消已定义的宏 |
#ifdef | 如果宏已经定义,则返回真 |
#ifndef | 如果宏没有定义,则返回真 |
#if | 如果给定条件为真,则编译下面代码 |
#else | #if 的替代方案 |
#elif | 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 |
#endif | 结束一个 #if……#else 条件编译块 |
#error | 当遇到标准错误时,输出错误消息 |
#pragma | 使用标准化方法,向编译器发布特殊的命令到编译器中 |
ANSI C 标准还定义了许多宏。在编程中我们可以使用这些宏,但是不能直接修改这些预定义的宏。
宏 | 描述 |
---|---|
__DATE__ | 当前日期,一个以“MMM DD YYYY”格式表示的字符常量。 |
__TIME__ | 当前时间,一个以“HH:MM:SS”格式表示的字符常量。 |
__FILE__ | 这会包含当前文件名,一个字符串常量。 |
__LINE__ | 这会包含当前行号,一个十进制常量。 |
__STDC__ | 当编译器以 ANSI 标准编译时,则定义为 1。 |
例:
#include <stdio.h>
int main() {
printf("File :%s\n", __FILE__);
printf("Date :%s\n", __DATE__);
printf("Time :%s\n", __TIME__);
printf("Line :%d\n", __LINE__);
printf("ANSI :%d\n", __STDC__);
}
通过巧用预处理指令,我们可以有效的简化代码,比如,我们可以用预处理指令来定义求较大值、求较小值、转大写和求数组元素数的函数。
#define MAX(x, y) (((x)>(y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define UPCASE(c) (((c)>='a' && (c) <= 'z') ? ((c) - 0x20) : (c))
#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))