C++ Primer学习笔记——$2 变量和基本类型

转载 2011年01月19日 14:31:00
题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。
 
作者: tyc611, 2007-01-13

   本文主要讨论C++中关于变量及其类型的一些讨论。
   如果文中有错误或遗漏之处,敬请指出,谢谢!

算术类型(arithmetic type)
   C++标准规定了每个算术类型的最小存储空间,但允许编译器使用更大的存储空间。事实上,对于int型,几乎现在所有的编译器使用的存储空间都比所要求的大(也表明,在编写程序时不能对这些类型的大小做任何假设)。C++算术类型最小存储空间规定如下:
(注:要特别注意int型,并且这里没有long long类型,基本上所有编译器都有这个扩展)
 类型  含义  最小存储空间
 bool  布尔型  -
 char  字符型  8位
 wchar_t  宽字符型   16位 
 short  短整型  16位 
 int  整形型  16位 
 long  长整型   32位
 float  单精度浮点型  6位有效数字
 double  双精度浮点型   10位有效数字
 long double  扩展精度浮点型  10位有效数字

  
  • 整型(integral type)
      
    表示整数、字符和布尔值的算术类型合称为整型(与浮点型相对应)。
  • 字符型(char)
       有三种类型:plain char, signed char, unsigned char,但只有两种表示方式:signed char和unsigned char。plain char用这两个表示方式之一来表示,至于用那种方式来表示取决于编译器,是实现定义的。

signed与unsigned类型

   C++标准并没有定义signed类型如何用位来表示,编译器通常用其中一位作为符号位来表示。

   对于unsigned 整型(unsigned char,unsigned short int, unsigned int, unsigned long int),编译器会将越界值对2^n取模(n为该类型的位数)使其满足大小要求。因此,unsigned整型在计算时不会发生溢出。
例如:(假设char类型为8位,2^8 = 256)
   unsigned char ch = 300; 等价于 unsigned char ch = 44 (300 mod 256)
   unsigned char ch = -1;  等价于 unsigned char ch = 255 (-1 mod 256)

   而对于越界的signed类型赋值的情形,标准没有明确说明,也就是未定义行为。很多编译器采用与unsigned类型一样的处理方式。
 

字面值(literal, or literal constant)
   只有内置类型存在字面值,每个字面值都有相应的类型。例如:0是int型,2.718是double型。
 
整形字面值
   整型字面值的类型依赖于它的形式、值和类型后缀:
  • 如果它是十进制形式并且没有类型后缀,那么它的类型是下面第一个能表示它的类型:int、long int。
  • 如果它是八进制或十六进制形式并且没有类型后缀,那么它的类型是下面第一个能表示它的类型:int,unsigned int,long int, unsigned long int。
  • 如果它有类型后缀u或者U,那么它的类型是下面第一个能表示它的类型:unsigned int, unsigned long int。
  • 如果它有类型后缀l或者L,那么它的类型是下面第一个能表示它的类型:long int, unsigned long int。
  • 如果它有类型后缀ul,lu,uL,Lu,Ul,lU,UL或者LU,那么它的类型是unsigned long int。

如果一个字面值不能够被它所有可能类型所表示,那么将产生未定义行为。

字符串字面值(string literal)
   形如"..."或者L"..."的字符串。

   不是以L开头的字符串字面值,叫作平凡字符串字面值(ordinary string literal),也叫作窄字符串字面值(narrow string literal)。对于平凡字符串字面值,其类型是const char[num],静态存储区,并用所给字符串初始化。

   以L开头的字符串字面值,例如:L"foo",是宽字符串字面值。它的类型是const wchar_t[num],静态存储区,并用所给字符串初始化。
   (注意上面的num值为所给字符串中字符个数 + 1)
 
   所有字符串字面值的存储是否是不重叠的,这个问题是由实现定义的(implementation-defined)。试图去修改字符串字面值的行为所产生的结果是未定义的。
 
   在编译时,相邻的窄字符串字面值被连接成一个窄字符串字面值,相邻的宽字符串字面值也被连接成一个宽字符串字面值。如果一个窄字符串字面值和一个宽字符串字面值相邻,其结果是未定义了。
 

变量及其类型
   C++没有规定变量名的长度。

   一些特殊的标识符为实现专用的保留标识符:
   1)包含两个连续下划线的标识符以及以下划线开头紧跟一个大写字母的标识符。
   2)在函数外定义的以下划线开头的标识符。
 
初始化
   初始化有两种方式:
   1)拷贝初始化(copy-initialization),例如:int var = 6;
   2)直接初始化(direct-initialization),例如:int var(6);
两种方式对于内置类型是没区别的,而对于类类型是有区别的,详见构造函数章节。

extern与const
   如果extern声明有初始化表达式,那么它被认为是定义,而忽略extern。例如:

extern int var = 6; //definition (只有当extern 声明位于函数外部时,才可以含有初始化表达式)


const限定符
   在全局作用域内声明的const变量为内部连接属性,即是文件域变量,所以可以把const变量定义放在头文件中(如果这样做,那么在每个包含该头文件中的文件中都会有一个该变量的定义,这样可能造成存储空间的大量浪费。事实上,当const变量是用常量表达式初始化时,大部分编译器在编译时都会用相应的常量表达式替换这些const变量的任何使用。也就不会有空间用于这类const变量的存储)。
 
   可以指定const变量为extern,从而使其变成外部连接属性,可以在整个程序中访问const对象(需要在定义和使用处都用extern声明)。如果定义了一个extern const变量,那么在其它文件中就不能再在全局域定义该变量(一个例外是,可以定义一个内部连接属性的const变量)。例如:

// file1.cpp
extern const int var = 6;

// file2.cpp
extern const int var;     
//legal: refer to the var in file1
// file3.cpp
const int var = 9;        
//legal: internal linkage, only used in this file
// file4.cpp
extern const int var = 2; 
//illegal: redefinion of var (already defined in file1)
// file5.cpp
int var;                   //illegal: redefinion of var (already defined in file1)


   非const引用只能绑定到与该引用同类型的对象;const引用则可以绑定到不同但相关的类型(该类型能够转换到引用的类型)的对象、甚至绑定到右值。例如:

int var = 6;
//int& r = 9;             // error!
const int& r1 = 9;       
// ok
const int& r2 = var + r1;
// ok


   为什么const引用则可以绑定到不同但相关的类型的对象、甚至绑定到右值呢?
 
   因为如果是绑定到不同类型的对象或右值,会先生成一个与引用类型相同的临时对象(必要时进行类型转换),然后引用变量再与该临时对象绑定。由于临时对象是右值,所以只能进行const引用。
 
   另外,还可以从另一个角度来解释,先看下面的例子:
 

double var = 2.718;
const int& r = var;

 
上面的代码等价于:
 

double var = 2.718;
int tmp = var;
const int& r = tmp;


   如果r不是const引用,那么可以修改r的值。这样做,事实上是修改了临时变量tmp的值,而与程序员试图修改var的值的意愿完全偏离。这种错误是很难察觉的。而const引用不能修改,就完全避免了这种错误的发生。
 

枚举类型
   枚举类型的对象的初始化或赋值只能通过其枚举成员或同一枚举类型对象进行。
   当需要整形常量时,用枚举类型(匿名枚举类型)代替#define预处理命令是一个不错的选择。

如果文中有错误或遗漏之处,敬请指出,谢谢!

参考资料:
[1] C++ Primer(Edition 4)
[2] International Standard:ISO/IEC 14882:1998

相关文章推荐

C++ Primer 学习笔记_5_变量和基本类型(续2)

 变量和基本类型 七、枚举     枚举不但定义了整数常量集,而且还把它们聚集成组; 枚举与简单的const常量相比孰优孰劣, 通过下面一段代码, 一看便知: [c...

c++Primer学习笔记之六:变量和基本类型_2

定义 const 对象 const 限定符把一个对象转换成一个常量。  const int bufSize = 512; // input buffer size  定义 bufSize 为常量...

C++ Primer 学习笔记(一)——变量和基本类型

一、基本内置类型与类类型 C++中数据类型分为:基本内置类型与类类型。基本内置类型指:布尔型,字符型,整型,浮点型等。 二、字面值常量 1、只有内置类型存在字面值,没有类类型的字面值。 2、定...

C++ primer 学习笔记(第二章:变量和基本类型)

2.1基本内置类型      C++定义了一套包括算术类型和空类型在内的基本数据类型。      2.1.1、算术类型         算术类型分为两类:整型(integer type,包括字符...

C++ Primer学习笔记(二) 变量与基本类型

1、当我们吧一个超出其取值范围的值赋给一个特定类型的值会怎样? 编译器会将该值对类型的可能取值数目求模,然后取所得值。比如8位的unsigned char,其取值范围为从0到255。如果赋给超出这个范...

《C++ Primer第四版》学习笔记(七)变量和基本类型 - typedef、枚举、类

typedef 三种目的: 1. 为了隐藏特性的实现,强调使用类型的目的 2. 简化复杂的类型定义,使其更容易理解 3. 允许一种类型用于多个目的,同时使得每次使用该类型的目的明确(API...

【C++ Primer学习笔记】第2章:变量和基本类型

类型是所有程序的基础。类型告诉我们数据代表什么意思以及可以对数据执行哪些操作。 C++中对类型的支持是非常广泛的:语言自身定义了一组基础类型和修改已有类型的方法,还提供了一组特征用于自定义类型。...

C++ Primer 学习笔记_3_变量和基本类型

 变量和基本类型 引言:     1、各种程序设计语言都具有许多各具特色的特征,这些特征决定了用每种语言适合开发哪些类型的应用程序。     2、大多数现代现代程序设计语言都采...

【C++ Primer学习笔记】第2章 变量和基本类型

1、基本内置类型 整型:整数、字符、布尔值 浮点型:浮点数   2、C++的内置类型与其在计算机的存储器中的表示方法密切相关。让存储具有结构的最基本方法是用块(Chunk)处理存储。块的大小因...
  • left_la
  • left_la
  • 2012年04月09日 15:25
  • 607

C++ Primer学习笔记5 变量和基本类型(const限定符、引用、typedef名字、枚举)

1、const限定符 定义一个变量代表某一个常数存在严重的问题,变量可以被修改,如果用const限定符可以解决此问题,把一个对象转换为常量。 const  int  bufSize = 512; ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Primer学习笔记——$2 变量和基本类型
举报原因:
原因补充:

(最多只允许输入30个字)