C++基本数据类型以及需要注意的地方

本文详细介绍了C++中的各种数据类型及其特点,包括基本数据类型、限定符、存储类型等,并对比了struct与union的区别。
  

image    

    以上为c++数据类型,注意在一些内置数据类型或引申数据类型的前面可以加一些限定的关键字,如:signed、unsigned、auto、extern、static、register、const 、volatile 等,用来限定定义(或声明)的变量的存储类型,可否修改等。

其中signed和unsigned是用来限定有无符号的,这个比较简单,这里就不讲了。

auto、extern、register和static

变量的存储类型

存储区域

存储方式

作用域

生命周期

默认初始化值

Auto

(自动变量)

栈区

动态存储

从定义(或声明)该变量的位置开始到的定义(或声明)该变量的语句块(通常是函数)结束的地方。

从函数调用开始到函数调用结束。

未知

Register

(寄存器变量)

CPU通用寄存器

动态存储

同自动变量

同自动变量

未知

Extern

(外部变量)

静态区

静态存储

从定义或声明该变量的位置开始到文件结束。

从程序执行开始-程序执行结束

0

Static

(静态变量)

静态区

静态存储

静态局部变量:同自动变量

静态外部变量:其作用域是从定义(不是声明)该变量的位置开始到文件结束。

从程序执行开始-程序执行结束

0

注:

1、 C语言规定,函数(包括main函数)内部(包括形参)或语句块内部,如果未加存储类型说明的变量均视为自动变量,也就是说自动变量可省去说明符auto。而在函数(包括main函数)外部和语句块外部的变量,如果未加存储类型说明的均视为外部变量。

2、 寄存器变量的个数,在 Turbo C 中寄存器变量限制最多只允许定义两个寄存器变量,一旦超过,系统就自动地将其余的作为非寄存器变量来处理。寄存器变量也是作为局部变量,它只适用于自动变量和函数的形参。寄存器变量的类型只能是 char、short int、unsigned int、int 等,而数据类型为 long 、float 、double 的变量不能定义为寄存器变量类型,因为这些数据类型的长度超过了寄存器本身的长度。

3、 外部变量的作用域是从定义或声明该变量的位置开始到文件结束。因此在一个源文件中定义的一个外部变量,在同一源程序的其他源文件中可以通过声明该外部变量的方法来访问这个外部变量。而静态外部变量的作用域是从定义(不是声明)该变量的位置开始到文件结束。因此,静态外部变量的作用域被局限于定义该变量的源文件内。故同一源程序的其他源文件就不能通过声明的方式来访问它了。

备注:

一个由C/C++编译的程序占用的内存分为以下几个部分


  1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  2、堆区(heap)— 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
  3、全局区(静态区)(static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
  4、文字常量区 — 常量字符串就是放在这里的。程序结束后由系统释放。
  5、程序代码区 — 存放函数体的二进制代码。

 

voilatle

volatile的本意是“易变的”,由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:

static int i=0;
int main(void)
{
    ...
        while (1)
        {
            if (i) dosomething();
        }
}
/* Interrupt service routine. */
void ISR_2(void)
{
    i=1;
}


      程序的本意是希望ISR_2中断产生时,在 main 当中调用 dosomething 函数,但是,由于编译器判断在 main 函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i 副本”,导致 dosomething 永远也不会被调用。如果将将变量加上 volatile 修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中 i 也应该如此说明。
     一般说来,volatile 用在如下的几个地方:
1、中断服务程序(回调函数)中修改的供其它程序检测的变量需要加 volatile ;
2、多任务(多线程)环境下各任务间共享的标志应该加 volatile ;
3、存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能由不同意义;
     另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

      一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:  
  1)   并行设备的硬件寄存器(如:状态寄存器)  
  2)   一个中断服务子程序中会访问到的非自动变量(Non-automatic   variables)  
  3)   多线程应用中被几个任务共享的变量
 

 

const

      const 指定一个变量在其声明周期内为可读的(即常量),要注意的是:const (常量)变量和 reference (引用)变量这两种变量必须初始化,否则编译不能通过。而其他变量的初始化则是可选的。那么你会问 static const 变量是否要初始化呢?static const 变量实际上是可以不初始化的。

两种类型的变量必须初始化

C++中有两种类型的变量必须初始化,否则编译是通不过的。这两种变量就是 constreference ,即常量变量和引用变量必须初始化。事实上,类这种变量也是要初始化的,比如我们定义了对象myclass myvar,这样定义实际上已经是调用了类myclass中的默认构造函数去初始化对象myvar了。

 

如何选择整型类型

      在老式的 IBM PC 机上,int 为2个字节,short为2个字节,long 为4个字节。

      在Win98,winNT,WinXP上,int 为4个字节,short为2个字节,long 为4个字节。

      实际上,short 是 short int 的简称,而 long 是 long int 的简称。

      一般来说整型类型用int,因为int被设置为对目标计算机而言最为“自然”的长度。自然长度(Natural size)指的是计算机处理起来效率最高的长度。

       若变量可能表示超过16位的十六进制整数,则用long,即使系统上 int 为32位也应该这么做,这样,当程序移植到16位系统中时,程序就不会无法正常工作了。

      若是大型数组时,且其所有元素表示的值都不超过16位的十六进制整数,请用short,若只需要一个字节,请用char。

      在嵌入式开发中,为了可移植性更好,一般建议用下面整形:

数据类型备注
__int81个字节
__int162个字节
__int323个字节
__int644个字节

      若需要无符号整型,请加上关键字unsigned。

 

数组

1、如果初始化数组时方括号[]内为空,C++编译器将自动计算元素个数。例如:

short things[] = {1, 3, 5, 8};     // sizeof(things) = 8 ( 即sizeof(short) * 4 )

short things[5] = {1, 3, 5, 8};     // sizeof(things) = 10 ( 即sizeof(short) * 5 )

2、只对数组的一部分进行初始化,则编译器自动把没有被初始化的元素都初始化成0。

3、在大多数情况下,C++和C语言都把数组名视为指针,数组名解释为其第一个元素的地址,即:array = &array[0]; 因此数组名实际上就是一个指针,而且是指针常量(该指针是常量)。但这一规则有例外的情况:对数组名使用 sizeof 操作符时。例如:

short array[5] = {1, 2, 3, 4, 5};    // sizeof(str) = 10 ( 即 sizeof(short) * 5 )

fun(array, 5);

void fun(short str[], int n)

{

    int i = sizeof(str);    // 此处 i 的值为4.
                                   // 数组参数作为函数参数时,其等价于一个指针,只占用4个字节(32位机上)。
                                   // 按照按值传递的原则,将数组名,即数组第一个元素的地址,作为实参赋值给形参str,
                                   // 形参str实际上就指向了array第一个元素的地址啦。

}

因此,为了将数组元素传递给数组处理函数,请通过两个不同的参数来传递它们,即:

void ProcArray(short arr[], int size);    // OK,  等价于:void ProcArray(short* arr, int size); 

4、在第一次引用数组的一个元素时,一定要对数组的这个元素进行初始化或赋值,否则会运行出错的。

5、在确定存储字符串所需要的最短数组时,别忘了将结尾的空字符计算在内,例如:

     char str[4] = “good”;   //  error

     char str[5] = “good”;   //  OK

     char str[] = “good”;     //  OK, and sizeof(str) = 5 ( 即 sizeof(char) * 5 )

     char str[8] = “good”;   //   OK, and sizeof(str) = 8

6、计算数组元素的公式是:

     int num_elements = sizeof(array) / sizeof(type of array);

 

struct和union的区别

struct(结构体)用途:把不同类型的数据组合成一个整体。
结构体变量所占内存长度是各成员所占内存长度的总和(似乎总是这样)。


union(共用体,也叫联合体):使用几个不同类型变量共占一段内存(相互覆盖)。
公用体所占内存长度是最长成员所占的内存长度。(最长成员是指占用内存长度最大的成员)

struct和union都是由多个不同数据类型的成员组成,但在同一时刻,union只存放一个被选中的成员,
而struct的所有成员都存在,对union的不同成员赋值,将会对其他成员重写,原来的成员就不存在了,
而对struct成员赋值则互不影响。例如:

union w
{
    char i[2];
    short k;
};

w r;
r.i[0] = 2;
r.i[1] = 1;
cout<< r.k << endl;

上面代码的输出是:258  

示意图为:

地址
0x40000x02 (r.i[0])
0x40010x01 (r.i[1])

由于 r.k 占两个字节,然而k没有赋值,但 k 占的内存地址也是从0x4000开始的,因此 r.k = 0x0102 = 258 (小端)。

 

关于更多的知识请查看 c++ primer 中的内容

参考网页: http://www.sarkuya.cn/computing/programming/language/c++/DataTypes.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Linruin/archive/2009/10/16/4679528.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值