(一)数值类型
1.数值类型转换,在C中的格式为 (type)var;C++里面允许 type(var);
2.类型转换遵循如下准则:
(1)在表达式中,char 和 short 类型的值,无论有符号还是无符号,都会自动转换成 int 或者 unsigned int(如果 short 的大小和 int 一样,unsigned short 的表示范围就大于 int,在这种情况下,unsigned short 被转换成 unsigned int)。因为它们被转换成表示范围更大的类型,故而把这种转换称为“升级(promotion)”。
(2)按照从高到低的顺序给各种数据类型分等级,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。这里有一个小小的例外,如果 long 和 int 大小相同,则 unsigned int 的等级应位于 long 之上。char 和 short 并没有出现于这个等级列表,是因为它们应该已经被升级成了 int 或者 unsigned int。
(3)在任何涉及两种数据类型的操作中,它们之间等级较低的类型会被转换成等级较高的类型。
(4)在赋值语句中,= 右边的值在赋予 = 左边的变量之前,首先要将右边的值的数据类型转换成左边变量的类型。也就是说,左边变量是什么数据类型,右边的值就要转换成什么数据类型的值。这个过程可能导致右边的值的类型升级,也可能导致其类型降级(demotion)。所谓“降级”,是指等级较高的类型被转换成等级较低的类型。
(5)作为参数传递给函数时,(un)signed char 和 (un)signed short 会被转换成 (un)signed int,float 会被转换成 double。使用函数原型可以避免这种自动升级。
(6)有符号与无符号之间相互转换时遵循“位扩展原则”。
(7)一般平台都有全套的MOV指令来解决不通长度、不同符号的数据类型转换;因此利用强制类型转换一般都能获得正确的截断值;而利用指针类型转换后再取值的方式则不然,那样只是换了一种对内存访问的方式,所以取得的值往往不对。
3.编译器接受一些类型指导,如常数宏定义可以加后缀 U/L 来指定为无符号以及(强制)长整型。
==========================================================================
(二)数组、枚举与结构体
1.定义数组时的长度值C中必须是数值,可以用宏定义,C++允许常量;
2.多维数组a[2][3] 的含义是2个长度为3的一维数组。内存组织为:
|a[0][0] a[0][1] a[0][2]| |a[1]a[0] a[1][1] a[1][2]|
3.unoin支持用不同的访问方式访问同一个内存,典型应用大小端:
- union _st{
-
int i;
-
char ch;
-
}*st;
- st->i = 1;
- //std-> ch = 1 too
==========================================================================
(三)sizeof与指针运算
1.首先sizeof是一个关键字,其值是在编译时计算的。
- sizeof(char) 1
-
sizeof(short) 2
-
sizeof(int) 4
-
sizeof(float) 4
-
sizeof(long) 4
-
sizeof(double) 8
结构体的长度相对复杂一些,涉及到内存对齐的问题,主要遵循三个准则:
(1)结构体的每个成员都按照一个2^N 的地址对齐,N取决于成员类型,如char N=0
short N = 1, int N = 2;此外如果用pragma pack(n) 定义了对齐参数n,那么N是默认值和n之间较小的一个。
(2)结构体的总大小必须是最大尺寸成员的整数倍,这是为了保证结构体数组能够对齐;
(3)如果有结构嵌套有结构体成员,那么这个结构体成员对齐的N数值是他自己尺寸最大的成员的N。
需要注意的是,如果成员是数组,那么相当于所有数组元素依次排列。举几个例子:
- struct _st1{
-
char a;
-
int b;
-
};//sizeof(_st1) = 1 + (3) + 4 = 8
-
struct _st2{
-
char a;
-
char b;
-
short c;
-
int d;
-
};//sizeof(_st2) = 1 + 1 + 2 + 4 = 8
-
-
struct _st3{
-
char a[2];
-
_st2 b;
-
double c;
-
char d;
-
};//sizeof(_st3) = 1 + 1 + (2) + 8 + (4) + 8 + 1 = 25 -> 32
2.指针的运算,如相加、相减等等运算等要和指针对应的类型尺寸挂钩,如:
- int a;
-
-
int *p = &a;
-
//p = 0xC10000
-
p++;
-
//p = 0xC10004
-
int *q = &a;
-
-
int d = p - q;
-
//d = 1
-
-
int b[10];
-
int *pb = b;
-
-
//b @ 0xC20000
- pb = (int *)((int)b + 1)
- ////pb = 0xC20001 &b[0] + 1
-
pb = (int *)(b + 1);
-
//pb = 0xC20004 &b[0] + sizeof(int)
-
pb = (int *)(&b + 1);
-
//pb = 0xC20028 &b[0] + sizeof(b)
3.数组或者都可以用一种p[n]的方式访问,这个表达式完全等价于*(p + n * sizeof(p)) ,对于二维数组p[m][n] 则等价于*(p + m * sizeof(p) + n *
sizeof(p[])),注意要严格按照第2条中的规则计算地址。
阅读(1518) | 评论(0) | 转发(0) |