1.表达式中有无符号数和有符号数混用的时候
先看一个例子:
int main(void)
{
unsigned int a = 6;
int b = -20
return (a+b) > 0 ? 1 : 0;
}
echo $ 的结果是 1。
首先这两个数在内存中都是以补码形式存储的,
以上面的例子分别为0xffffffec , 0x6。相加后的值也很明显等于fffffff2
可以看一下gcc中反汇编:
但是关键对a+b这个add操作后,编译器对结果的解释 ,在这里很不幸,被解释成unsigned int。因为在c语言中,当有符号数
和无符号数在同一个表达式的时候,有符号数被解释成无符号数。而且a+b > 0这个操作(当然0是无符号的(默认))。
所以这种写法很不好的。最好避免有同一个表达式中同时出现有符号数和无符号数。
表达式求值:
隐式类型转换
c的整型算术运算总是至少以整型类型的精度来进行的。为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通整型,这种转换称为“整型提升”。
算术转换
当两个操作数属于不同的类型,那么除非其中一个操作数转换为另外一个操作数的类型,否则操作无法进行。
下面的层次体系----称为寻常算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
如果操作数的类型在上面这个列表中排名较低,那么它首先将转换为另外一个操作数的类型然后执行操作。(自己的理解,排名是根据类型表示的数据的个数(范围的大小)来决定的。
2.标准c的标记化初始化语法
在linux设备驱动程序看到的一种标准:
struct file_operations scull_fops ={
.owner = THIS_MODULE,
.llseek = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release
};
这种写法是很值得采用的,因为它使驱动程序在结构的定义发生变化时更具可移植性,并且使得代码更加紧凑且易读。而且标记化的初始化方法允许对结构成员进行重新排列。
当然是Iso c99的标准。
比起传统的初始化办法:scull_fops= {THIS_MODULE, scull_read, scull_write, scull_iotcl, scull_open, scull_release};有很明显的好处。
3-14日
sig_atomic_t类型,由 iso c标准定义的变量类型,在写这种类型的变量时,不会被中断(不会有缺页中断发生)。它意味着在具有虚拟存储器的系统上这种变量不会跨越页边界,可以用一条机器指令对其进行访问。
而且在使用的时候,前面加上volatile
如 volatile sig_atomic_t quitflag;