一、关于类型转换
K&R C的不说了,说了还容易混淆,只说ANSI C的:
如果其中一个操作数的类型是unsigned long int,那么另外一个操作数也被转换为unsigned long int。其次其中一个操作数的类型是long int,而另一个操作数的类型是unsigned int,如果long int能够完整表示unsigned int 的所有值,那么unsigned int 类型操作数被转换为long int ,如果long int 不能完整表示unsigned int 的所有值,那么两个数都被转换为unsigned long int 。再再次,如果其中一个操作数是unsigned int,那么另外一个操作数(int、char、unsigned char)被转换为unsigned int。所上情况以外,两个操作数都为int。
通俗来说:
当执行蒜素运算时,操作数的类型如果不同,就会发生转换。数据类型一般操作浮点精度更高、长度更长的方向转换,整数型如果转换为singed不会丢失信息,就转换为singed,否则转换为unsigned。
看下面两个例子:
例1:小于号左右两边操作数都转换为int
int main() { if (-1 < (unsigned int)1) printf("-1 is less than (unsinged int)1\n"); else printf("-1 is not less than (unsinged int)1\n"); return 0; }
例2:-1转换为unsigned int
int main() { if (-1 < (unsigned int)1) printf("-1 is less than (unsinged char)1\n"); else printf("-1 is not less than (unsinged char)1\n"); return 0; }
二、几个怪异的声明标示符
volatile:
它被设计用来修饰被不同线程访问和修改的变量。确保本条指令不会因编译器优化而省略,且要求每次直接读值。优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
register:
register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
三、关于sizeof
#includeint main() { struct Test1 { int i; char c; }; struct Test2 { char c; int i; }; struct Test3 { double d; char c; }; struct Test4 { char c; double d; }; printf("test1:%d, test2:%d, test3:%d, test4:%d\n", sizeof(struct Test1), sizeof(struct Test2), sizeof(struct Test3), sizeof(struct Test4)); return 0; }
在vs2008下输出结果为8、8、16、16,在下结果为8、8、12、12。
原因见这个地方: