C语言细节与技巧
作为当前最流行的编程语言,C语言应该是每一个程序员必备的技能。不过,C语言里面有许多容易忽略或者误解的细节,当然也有许多技巧,在此我做了一个总结,希望能对各位同仁有所帮助!
1.boolean类型
众所周知,C语言没有boolean类型,不过可以很轻松地通过typedef和enum自定义。
typedef enum { false=0, FALSE=0, true=1, TRUE=1 } bool;
2.enum技巧
enum其实就是把一个标识符对应到一个常数,枚举值默认从0开始,比如
enum { ZERO, ONE, TWO, OTHER }; // ZERO=0, ONE=1; TWO=2, OTHER=3
可以任意改变枚举对应的值,比如
enum { A=65, B, C, E=69, F, AA=65, BB }; // A=65, B=66, C=67, E=69, F=70, AA=65, BB=66
3.函数名和函数指针以及函数指针参数
在C语言里面,函数名其实就是指针,下面两种函数调用方式都是正确的,这是为了方便程序编写,编译器对代码做了优化,所以可以不用在函数名前面加上‘*’。
void say(const char *str) { printf("%s\n", str); } // 函数调用 say("hello world!"); (*say)("hello world!");
而对函数指针和函数指针参数而言,情况也是类似的。
void (*func_ptr)(const char *) = say; // 或者void (*func_ptr)(char *) = &say; func_ptr("hello world!"); // 或者(*func_ptr)("hello world!"); void my_func(void (*executed_func)(const char *), const char *str) { executed_func("hello world!"); // 或者(*executed_func)("hello world!"); }
4.int char转换
字符串转换数字,atoi, atol, atof分别对应int型,long型,double型。数字转换字符串要用到sprintf函数(stdio.h文件已包含)。
// 字符串转换为int char s[] = "4321"; int a = atoi(s); // int转换为字符串 int x = 1234; char str[12]; sprintf(str, "%d", x);
5.变量初始化
全局变量程序会自动初始化为0或者null,局部变量(静态局部变量除外)必须手动初始化,否则将会得到一些随机的数。数组初始化的时候应该注意,除了手动赋值之外其它的所有变量均初始化为0或者null。
// 以下情况为局部变量 int a[] = {1, 2, 3, 4}; // 长度固定可以省略 int b[12] = {1, 2}; // b[0]=1, b[1]=2, 其它均为0 char c[12] = "hi"; // c[0]='h', c[1]='i', 其它均为‘\0’ int *ptr[12] = {}; // 全部为null
6.whitespace对输入输出的影响
scanf函数输入字符可以接受所有的空字符(空格,制表符,回车),为了避免这种情况,可以在输入格式控制里面添加一个空格,这样就会忽略所有的空字符,知道读到下一个非空字符才输入。
int n; char c; scanf("%d%c", &n, &c); // 但输入为12 h的时候,n=12, c=' ' scanf("%d %c", &n, &c); // 但输入为12 h的时候,n=12, c='h' scanf("%d %c", &n, &c); // 但输入为12回车h的时候,n=12, c='h'
scanf函数输入字符串的时候不能接受空字符(空格,制表符,回车),即遇到这些字符的时候就会终止字符串的输入,但输入的字符串不为空(即!=""),如果字符串中要输入空格或者制表符,可以用gets函数,遇到回车即终止字符串的输入,即使当前字符串为空。
// 假设键盘输入为hello world! I love this world!之后回车 char str1[100]; char str2[100]; scanf("%s", str1); // str1="hello" gets(str2); // str2=" world! I love this world!"
另外,字符、字符串的输入输出也可以用getchar,putchar,gets,puts函数,getchar函数可以接受空字符,puts函数默认换行。
char c; char str[100]; c = getchar(); putchar(c); gets(str); puts(str);
补充一点小知识:%p是专门输出地址的,%o和%x都是以unsigned int类型解析,%.2s只输出字符串前2位,函数参数是自右往左解析的,即int n=1; printf("%d%d%d", n, n++, n++);结果是321。
7.一些容易混淆的C与C++特性
C跟C++实在太像了,以致有时候把它们混为一谈,下面是一些最容易在C语言里面误用的C++特性:
1)C函数参数不能赋默认值
2)C函数参数不能传别名即&的方式
3)C没有bool和string类型
4)C在for循环的括号里面不能声明变量
5)C声明一个struct类型之后,在使用的时候还必须在类型名前面加上struct关键字