1、用if(!strcmp(s1, s2)) 比较两个字符串等值,是否是个好风格?
这并不是个很好的风格, 虽然这是个流行的习惯用法。如果两个字符串相等,
这个测试返回为真, 但! (“非”) 的使用, 容易引起误会, 以为测试不等值情况。
另一个选择是用一个宏:
#define Streq(s1, s2) (strcmp((s1), (s2)) == 0)
2、为什么有的人用if (0 == x) 而不是if (x == 0)?
这是用来防护一个通常错误的小技巧:
if (x = 0)
如果你养成了把常量放在== 前面的习惯, 当你意外的把代码写成了:
if (0 = x)
那编译器就会报怨。明显的, 一些人会觉得记住反换测试比记住输入双= 号容易。当然这个技巧只对和常量比较的情况有用。
3、*p++ 自增p 还是p 所指向的变量?
后缀++ 和-- 操作符本质上比前缀一目操作的优先级高,即++与p结合优先级高于*与p的结合优先级, 因此*p++ 和*(p++) 等价, 它自增p 并返回p 自增之前所指向的值(也即先去内容,然后指针p才自加)。要自增p 指向的值, 使用(*p)++, 如果副作用的顺序无关紧要也可以使用++*p.
4、我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。为什么如下的代码((int *)p)++; 不行?
在C 语言中, 类型转换意味着“把这些二进制位看作另一种类型, 并作相应的对待”; 这是一个转换操作符, 根据定义它只能生成一个右值(rvalue)。而右值既不能赋值, 也不能用++ 自增。(如果编译器支持这样的扩展, 那要么是一个错误, 要么是有意作出的非标准扩展。) 要达到你的目的可以用:
p = (char *)((int *)p + 1);或者,因为p 是char * 型, 直接用p += sizeof(int);
但是, 在可能的情况下, 你还是应该首先选择适当的指针类型, 而不是一味地试图李代桃僵。
5、C 有“按引用传递” 吗?
真的没有。
严格地讲, C 总是按值传递。你可以自己模拟按引用传递, 定义接受指针的函数, 然后在调用时使用& 操作符。事实上, 当你向函数传入数组(传入指针的情况参见问题6.4 及其它) 时, 编译器本质上就是在模拟按引用传递。但是C 没有任何真正等同于正式的按引用传递或C++(www.cppentry.com) 的引用参数的东西。另一方面, 类似函数的预处理宏可以提供一种“按名称传递”的形式。
6、我们经常说空指针,那么那个“臭名昭着”的控制振动到底是什么呢?
语言定义中说明, 每一种指针类型都有一个特殊值-- “空指针” -- 它与同类型的其它所有指针值都不相同, 它“与任何对象或函数的指针值都不相等”.也就是说, 取地址操作符& 永远也不能得到空指针,同样对malloc() 的成功调用也不会返回空指针, 如果失败, malloc() 的确返回空指针, 这是空指针的典型用法:表示“未分配” 或者“尚未指向任何地方” 的指针。空指针在概念上不同于未初始化的指针。空指针可以确保不指向任何对象或函数; 而未初始化指针则可能指向任何地方。如上文所述, 每种指针类型都有一个空指针, 而不同类型的空指针的内部表示可能不尽相同。尽管程序员不必知道内部值, 但编译器必须时刻明确需要那种空指针, 以便在需要的时候加以区分。既然如此,那么怎样在一个程序里面获得一个空指针呢?
根据语言定义, 在指针上下文中的常数0 会在编译时转换为空指针。也就是说, 在初始化、赋值或比较的时候, 如果一边是指针类型的值或表达式, 编译器可以确定另一边的常数0 为空指针并生成正确的空指针值。因此下边的代码段完全合法:
char *p = 0;
if(p != 0)
然而, 传入函数的参数不一定被当作指针环境,因而编译器可能不能识别未加修饰的0“表示”指针在函数调用的上下文中生成空指针需要明确的类型转换,强制把0看作指针。例如, Unix 系统调用execl接受变长的以空指针结束的字符指针参数它。应该如下正确调用:execl(“/bin/sh”, “sh”, “-c”, “date”,(char *)0);
如果省略最后一个参数的(char *) 转换, 则编译器无从知道这是一个空指针,从而当作一个0 传入。(注意很多Unix 手册在这个例子上都弄错了。)如果范围内有函数原型, 则参数传递变为“赋值上下文”, 从而可以安全省略多数类型转换, 因为原型告知编译器需要指针, 使之把未加修饰的0 正确转换为适当的指针。函数原型不能为变长参数列表中的可变参数提供类型。在函数调用时对所有的空指针进行类型转换可能是预防可变参数和无原型函数出问题的最安全的办法。看一下摘要:
可以使用未加修饰的0 : 需要显示的类型转换:
初始化 函数调用,作用域内无原型
赋值 变参函数调用中的可变参数
比较
固定参数的函数调用且在作用域
内有原型
然而我们在平时使用的空指针NULL到底是什么含义,它是怎么定义的呢?
|