Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141119
  • 博文数量: 25
  • 博客积分: 100
  • 博客等级: 中士
  • 技术积分: 310
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-03 18:56
文章分类

全部博文(25)

文章存档

2012年(4)

2011年(21)

分类: C/C++

2011-06-20 22:34:55

(一)数值类型
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支持用不同的访问方式访问同一个内存,典型应用大小端:

  1. union _st{
  2.     int i;
  3.     char ch;
  4. }*st;

  5. st->= 1;
  6. //std-> ch = 1 too
==========================================================================
(三)sizeof与指针运算

1.首先sizeof是一个关键字,其值是在编译时计算的。
  1. sizeof(char) 1
  2. sizeof(short) 2
  3. sizeof(int) 4
  4. sizeof(float) 4
  5. sizeof(long) 4
  6. 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。

需要注意的是,如果成员是数组,那么相当于所有数组元素依次排列。举几个例子:
  1. struct _st1{
  2.  char a;
  3.  int b;
  4. };//sizeof(_st1) = 1 + (3) + 4 = 8

  5. struct _st2{
  6.  char a;
  7.  char b;
  8.  short c;
  9.  int d;    
  10. };//sizeof(_st2) = 1 + 1 + 2 + 4 = 8

  11. struct _st3{
  12.   char a[2];
  13.   _st2 b;
  14.   double c;
  15.   char d;
  16. };//sizeof(_st3) = 1 + 1 + (2) + 8 + (4) + 8 + 1 = 25 -> 32

2.指针的运算,如相加、相减等等运算等要和指针对应的类型尺寸挂钩,如:
  1. int a;

  2. int *p = &a;
  3. //p = 0xC10000
  4. p++;
  5. //p = 0xC10004
  6. int *q = &a;

  7. int d = p - q;
  8. //d = 1

  9. int b[10];
  10. int *pb = b;

  11. //b @ 0xC20000
  12. pb = (int *)((int)b + 1)
  13. ////pb = 0xC20001 &b[0] + 1
  14. pb = (int *)(b + 1);
  15. //pb = 0xC20004 &b[0] + sizeof(int)
  16. pb = (int *)(&b + 1);
  17. //pb = 0xC20028 &b[0] + sizeof(b)

3.数组或者都可以用一种p[n]的方式访问,这个表达式完全等价于*(p + n * sizeof(p)) ,对于二维数组p[m][n] 则等价于*(p + m * sizeof(p) + n *
sizeof(p[])),注意要严格按照第2条中的规则计算地址。
 
阅读(1505) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~