C++编程中的数据类型和常量学习教程

C++数据类型
计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数、浮点数、字符等形式)。不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组)。数据结构指的是数据的组织形式。例如,数组就是一种数据结构。不同的计算机语言所允许使用的数据结构是不同的。处理同一类问题,如果数据结构不同,算法也会不同。例如,对10个整数排序和对包含10个元素的整型数组排序的算法是不同的。

C++的数据包括常量与变量,常量与变量都具有类型。由以上这些数据类型还可以构成更复杂的数据结构。例如利用指针和结构体类型可以构成表、树、栈等复杂的数据结构。

C++并没有统一规定各类数据的精度、数值范围和在内存中所占的字节数,各C++编译系统根据自己的情况作出安排。表2.1列出了Visual C++数值型和字符型数据的情况。

几点说明:
1) 整型数据分为长整型(long int)、一般整型(int)和短整型(short int)。在int前面加long和short分别表示长整型和短整型。

2) 整型数据的存储方式为按二进制数形式存储,例如十进制整数85的二进制形式为1010101,则在内存中的存储形式如下图所示。

3) 在整型符号int和字符型符号char的前面,可以加修饰符signed(表示“有符号”)或unsigned(表示“无符号”)。如果指定为signed,则数值以补码形式存放,存储单元中的最高位(bit)用来表示数值的符号。如果指定为unsigned,则数值没有符号,全部二进制位都用来表示数值本身。例如短整型数据占两个字节 ,

有符号时,能存储的最大值为215-1,即32767,最小值为-32768。无符号时,能存储的最大值为216-1,即65535,最小值为0。有些数据是没有负值的,可以使用unsigned,它存储正数的范围比用signed时要大一倍。

4) 浮点型(又称实型)数据分为单精度(float)、双精度(double)和长双精度(long double)3种,在Visual C++ 6.0中,对float提供6位有效数字,对double提供15位有效数字,并且float和double的数值范围不同。对float分配4个字节,对double和long double分配8个字节。

5) 表中类型标识符一栏中,方括号[ ]包含的部分可以省写,如short和short int等效,unsigned int和unsigned等效。

常量的值是不能改变的,一般从其字面形式即可判别是否为常量。常量包括两大类,即数值型常量(即常数)和字符型常量。如12, 0, -3为整型常量,4.6, -1.23为实型常量,包含在两个单撇号之间的字符为字符常量,如′a′, ′x′。这种从字面形式即可识别的常量称为“字面常量”或“直接常量”。

C++常量(C++数值常量、字符串常量、符号常量)
数值常量

数值常量就是通常所说的常数。在C++中,数值常量是区分类型的,从字面形式即可识别其类型。

整型常量(整数)的类型
在上一节中已知道:整型数据可分为int, short int,long int以及unsigned int, unsigned short, unsigned long等类别。整型常量也分为以上类别。为什么将数值常量区分为不同的类别呢?因为在进行赋值或函数的参数虚实结合时要求数据类型匹配。

那么,一个整型常量怎样从字面上区分为以上的类别呢?
一个整数,如果其值在-32768~+32767范围内,认为它是short int型,它可以赋值给short int型?int型和long int型变量。
一个整数,如果其值超过了上述范围,而在-2147483648~+2147483647范围内,则认为它是long int型,可以将它赋值给一个int或long int型变量。
如果某一计算机系统的C++版本(例如Visual C++)确定int与long int型数据在内存中占据的长度相同,则它们能够表示的数值的范围相同。因此,一个int型的常量也同时是一个long int型常量,可以赋给int型或long int型变量。
常量无unsigned型。但一个非负值的整数可以赋值给unsigned整型变量,只要它的范围不超过变量的取值范围即可。

一个整型常量可以用3种不同的方式表示:
十进制整数。如1357, -432, 0等。在一个整型常量后面加一个字母l或L,则认为是long int型常量。例如123L, 421L, 0L等,这往往用于函数调用中。如果函数的形参为long int,则要求实参也为long int型,此时用123作实参不行,而要用123L作实参。
八进制整数。在常数的开头加一个数字0,就表示这是以八进制数形式表示的常数。如020表示这是八进制数20,即(20)8,它相当于十进制数16。
十六进制整数。在常数的开头加一个数字0和一个英文字母X(或x),就表示这是以十六进制数形式表示的常数。如0X20表示这是十六进制数20,即(20)16,它相当于十进制数32。
浮点数的表示方法

一个浮点数可以用两种不同的方式表示:
1) 十进制小数形式。如21.456, -7.98等。它一般由整数部分和小数部分组成,可以省略其中之一(如78.或.06, .0),但不能二者皆省略。C++编译系统把用这种形式表示的浮点数一律按双精度常量处理,在内存中占8个字节。如果在实数的数字之后加字母F或f,表示此数为单精度浮点数,如1234F, -43f,占4个字节。如果加字母L或l,表示此数为长双精度数(long double),在GCC中占12个字节,在Visual C++ 6.0中占8个字节。

2) 指数形式(即浮点形式)。一个浮点数可以写成指数形式,如3.14159可以表示为0.314159×101, 3.14159×100, 31.4159×10-1, 314.159×10-2等形式。在程序中应表示为:0.314159e1, 3.14159e0, 31.4159e-1, 314.159e-2,用字母e表示其后的数是以10为底的幂,如e12表示1012。其一般形式为:
    数符  数字部分  指数部分

上面各数据中的0.314159, 3.14159, 31.4159, 314.159 等就是其中的数字部分。可以看到:由于指数部分的存在,使得同一个浮点数可以用不同的指数形式来表示,数字部分中小数点的位置是浮动的。例如:

 a=0.314159e1;
 a=3.14159e0;
 a=31.4159e-1;
 a=314.159e-2;

以上4个赋值语句中,用了不同形式的浮点数,但其作用是相同的。

在程序中不论把浮点数写成小数形式还是指数形式,在内存中都是以指数形式(即浮点形式)存储的。例如不论在程序中写成314.159或314.159e0, 31.4159e1, 3.14159e2, 0.314159e3等形式,在内存中都是以规范化的指数形式存放,

数字部分必须小于1,同时,小数点后面第一个数字必须是一个非0数字,例如不能是0.0314159。因此314.159和314.159e0, 31.4159e1, 3.14159e2, 0.314159e3在内存中表示成0.314159×103。存储单元分为两部分,一部分用来存放数字部分,一部分用来存放指数部分。为便于理解,在图2.3中是用十进制表示的,实际上在存储单元中是用二进制数来表示小数部分,用2的幂次来表示指数部分的。

对于以指数形式表示的数值常量,也都作为双精度常量处理。
字符常量

1) 普通的字符常量
用单撇号括起来的一个字符就是字符型常量。如'a', '#', '%', 'D'都是合法的字符常量,在内存中占一个字节。注意:
字符常量只能包括一个字符,如'AB' 是不合法的。
字符常量区分大小写字母,如'A'和'a'是两个不同的字符常量。
撇号(')是定界符,而不属于字符常量的一部分。如cout<<'a';输出的是一个字母"a",而不是3个字符"'a' "。

2) 转义字符常量
除了以上形式的字符常量外,C++还允许用一种特殊形式的字符常量,就是以 "\"开头的字符序列。例如,'\n'代表一个"换行"符。"cout<<'\n'; " 将输出一个换行,其作用与"cout<<endl; " 相同。这种"控制字符",在屏幕上是不能显示的。在程序中也无法用一个一般形式的字符表示,只能采用特殊形式来表示。

3) 字符数据在内存中的存储形式及其使用方法
将一个字符常量存放到内存单元时,实际上并不是把该字符本身放到内存单元中去,而是将该字符相应的ASCII代码放到存储单元中。如果字符变量c1的值为'a',c2的值为'b',则在变量中存放的是'a'的ASCII码97,'b' 的ASCII码98,如图2.4(a)所示,实际上在内存中是以二进制形式存放的,

既然字符数据是以ASCII码存储的,它的存储形式就与整数的存储形式类似。这样,在C++中字符型数据和整型数据之间就可以通用。一个字符数据可以赋给一个整型变量,反之,一个整型数据也可以赋给一个字符变量。也可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算。

【例】将字符赋给整型变量。

#include <iostream>
using namespace std;
int main( )
{
 int i, j; //i和j是整型变量
 i='A'; //将一个字符常量赋给整型变量i
 j='B'; //将一个字符常量赋给整型变量j
 cout<<i<<' '<<j<<'\n'; //输出整型变量i和j的值,'\n' 是换行符
 return 0;
}

执行时输出

 65 66

i和j被指定为整型变量。但在第5和第6行中,将字符'A'和'B'分别赋给i和j,它的作用相当于以下两个赋值语句:

 i=65;j=66;

因为'A'和'B'的ASCII码为65和66。在程序的第5和第6行是把65和66直接存放到i和j的内存单元中。因此输出65和66。

可以看到:在一定条件下,字符型数据和整型数据是可以通用的。但是应注意字符数据只占一个字节,它只能存放0~255范围内的整数。

【例】字符数据与整数进行算术运算。下面程序的作用是将小写字母转换为大写字母。

#include <iostream>
using namespace std;
int main( )
{
 char c1,c2;
 c1='a';
 c2='b';
 c1=c1-32;
 c2=c2-32;
 cout<<c1<<' '<<c2<<endl;
 return 0;
}

运行结果为

 A B

'a'的ASCII码为97,而'A'的ASCII码为65,'b'为98,'B'为66。从ASCII代码表中可以看到每一个小写字母比它相应的大写字母的ASCII代码大32。C++符数据与数值直接进行算术运算,'a'-32得到整数65,'b'-32得到整数66。将65和66存放在c1,c2中,由于c1,c2是字符变量,因此用cout输出c1,c2时,得到字符A和B(A的ASCII码为65,B的ASCII码为66)。
字符串常量

用双撇号括起来的部分就是字符串常量,如"abc","Hello!","a+b","Li ping"都是字符串常量。字符串常量"abc"在内存中占4个字节(而不是3个字节),见图。

编译系统会在字符串最后自动加一个'\0'作为字符串结束标志。但'\0'并不是字符串的一部分,它只作为字符串的结束标志。如

  cout<<"abc"<<endl;

输出3个字符abc,而不包括'\0'。

注意: "a"和'a'代表不同的含义,"a"是字符串常量,'a' 是字符常量。前者占两个字节,后者占1个字节。请分析下面的程序片段:

 char c; //定义一个字符变量
 c='a'; //正确
 c="a"; //错误,c只能容纳一个字符

请思考:字符串常量"abc\n"包含几个字符?不是5个而是4个字符,其中"\n"是一个转义字符。但它在内存中占5个字节(包括一个"\0"字符) 。编译系统遇到"\"时就会把它认作转义字符的标志,把它和其后的字符一起作为一个转义字符。

如果"\"后面的字符不能与"\"组成一个合法的转义字符(如"\c"),则在编译时显示出错信息。如果希望将"\"字符也作为字符串中的一个字符,则应写为"abc\\n",此时字符包括5个字符,即a,b,c,\,n。如果有以下输出语句:

 cout<<"abc\\\n"<<endl;

则会输出:

 abc\ (然后换行)

同理执行

 cout<<"I say \"Thank you!\"\n";

的输出是:

 I say "Thank you!"

如果在一个字符串中最后一个字符为"\",则表示它是续行符,下一行的字符是该字符串的一部分,且在两行字符串间无空格。如

 cout<<"We must study C\ //本行最后的"\"后面的空格和换行均不起作用
 ++ hard!"; //本行的字符紧连在上一行最后的"\"前面字符之后

则输出:

 We must study C++ hard!

符号常量

为了编程和阅读的方便,在C++程序设计中,常用一个符号名代表一个常量,称为符号常量,即以标识符形式出现的常量。

【例】符号常量的使用。

#include <iostream>
using namespace std;
#define PRICE 30 //注意这不是语句,末尾不要加分号
int main ( )
{
 int num,total;
 num=10;
 total=num * PRICE;
 cout<<"total="<<total<<endl;
 return 0;
}

程序中用预处理命令#define指定PRICE在本程序单位中代表常量30,此后凡在本程序单位中出现的PRICE都代表30,可以和常量一样进行运算,程序运行结果为

 total=300

请注意符号常量虽然有名字,但它不是变量。它的值在其作用域(在本例中为主函数)内是不能改变的,也不能被赋值。如用赋值语句"PRICE=40;"给PRICE赋值是错误的。 使用符号常量的好处是:含义清楚,在需要改变一个常量时能做到"一改全改"。 如:

 #define PRICE 35
(0)

相关推荐

  • 简单总结C++中指针常量与常量指针的区别

    我们先回顾下,什么是指针?什么是常量?指针是一种特殊的变量,它里面存储的内容是内存地址.常量是指其里面存储的内容不能发生改变的量.明白了这两个概念后,我们现在正式进入指针常量与常量指针. 1.指针常量与常量指针的概念 指针常量就是指针本身是常量,换句话说,就是指针里面所存储的内容(内存地址)是常量,不能改变.但是,内存地址所对应的内容是可以通过指针改变的. 常量指针就是指向常量的指针,换句话说,就是指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容.但是,指针自身不是常量

  • 剖析C++中的常量表达式与省略号的相关作用

    C++ 常量表达式 常量值是指不会更改的值.C + + 提供了两个关键字,它们使你能够表达不打算修改对象的意图,还可让你实现该意图. C++ 需要常量表达式(计算结果为常量的表达式)以便声明: 数组边界 case 语句中的选择器 位域长度规范 枚举初始值设定项 常量表达式中合法的唯一操作数是: 文本 枚举常量 声明为使用常量表达式初始化的常量的值 sizeof 表达式 必须将非整型常量(显式或隐式)转换为常量表达式中合法的整型.因此,以下代码是合法的: const double Size = 1

  • 详解C++中常量的类型与定义

    常量是固定值,在程序执行期间不会改变.这些固定的值,又叫做字面量. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符.字符串和布尔值. 常量就像是常规的变量,只不过常量的值在定义后不能进行修改. 整数常量 整数常量可以是十进制.八进制或十六进制的常量.前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制. 整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long).后缀可以是大写,也可以是小

  • C++ 常量成员常量返回值详解

    总结: 1.常量数据成员,形式:const Type m_tData; 1)常量数据成员,需要在构造函数列表中给出,构造函数中可以用常量赋值,也可以实例化的时候赋值. 2)赋值函数中不能赋值,起到保护常量数据成员的作用,和友元作用相反. 2.常量成员函数,形式:type funname(type1 arg1,type2 arg2,...) const 1)常量成员函数,不能修改类数据成员,不能调用非常量函数. 2)常量成员函数的作用,可以有效的将类的函数分为可以修改类的函数,和不能修改类的函数:

  • c++常量详解

    概念 常量是存放固定且不可变值的,一旦确定初始值则在程序其它地方不可改变, 所以const对象必须初始化.常量一般使用const关键字来修饰. const 对象可以大致分为三类: 1. const int a const int a =10; int const b =10; 这两种格式是完全相同的.也就是说const 与int哪个写前都不影响语义.有了这个概念后,我们来看这两个家伙:const int * pi与int const * pi ,它们的语义有不同吗? 你只要记住一点,int 与c

  • C++中的常量定义小结

    本篇笔记总结自一次代码检视. 一般来说,使用C语言编程时我们都习惯在代码当中使用C当中的宏定义来定义一个数值常量: #define MY_CONST 7 在C++开发项目时,也会经常存在沿袭C当中常量用法情况.所以,如下的一种写法看起来反倒觉得有些不正宗了: class MyClass { static const int my_const = 7; // ... }; 站在编译器的角度,这两种写法都是合法的,但在使用的时候总得二中择一,究竟哪种更合适呢?之前有所耳闻在C++中应该尽可能少的使用

  • C++常量详解一(常量指针与常量引用的初始化)

    1.常量 1.1.常量的初始化: const对象一旦创建后其值就不能再改变,所以const对象必须初始化.这里我们要注意一点,像const int *p和const int &r都并不是const对象.因为const int *p只是表示不能通过p改变p所指的对象的值,p的值是可以变的,所以p可以不用初始化.至于r ,引用本身就不是对象,所以r也并不是const对象,r之所以一定初始化,是因为引用必须初始化.对于以上内容,你也可以理解为底层const 修饰的并不是const对象,还要注意像con

  • C++常量详解二(常量形参,常量返回值,常量成员函数)

    1.常量形参 当形参有顶层const或者底层const的时候,传给它常量对象或者非常量对象都是可以的,在这里我们主要考虑形参无const, 而实参有const的情况,其实这里也十分简单,只需要记住一点:底层const的限制,就可以了. 2.常量返回值 这里也很简单,略过不提. 3.常量成员函数 常量函数里的const是用来修饰*this的,其形式如下: int f() const{```} 然后这里就有意思了 *this的默认类型是type *const this,this指针有一个顶层cons

  • C++类中的常量介绍

    由于#define 定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用 const 修饰数据成员来实现.const 数据成员的确是存在的,但其含义却不是我们所期望的.const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其 const 数据成员的值可以不同. 不能在类声明中初始化 const 数据成员.以下用法是错误的,因为类的对象未被创建时,编译器不知道 SIZE 的值是什么. 复制代码 代码如下: class A {  cons

  • C++编程中的数据类型和常量学习教程

    C++数据类型 计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数.浮点数.字符等形式).不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组).数据结构指的是数据的组织形式.例如,数组就是一种数据结构.不同的计算机语言所允许使用的数据结构是不同的.处理同一类问题,如果数据结构不同,算法也会不同.例如,对10个整数排序和对包含10个元素的整型数组排序的算法是不同的. C++的数据包括常量与变量,常量与变量都具有类型.由以上这些数据类型还可以构成更复杂的数据结构.例如利

  • Python面向对象编程中的类和对象学习教程

    Python中一切都是对象.类提供了创建新类型对象的机制.这篇教程中,我们不谈类和面向对象的基本知识,而专注在更好地理解Python面向对象编程上.假设我们使用新风格的python类,它们继承自object父类. 定义类 class 语句可以定义一系列的属性.变量.方法,他们被该类的实例对象所共享.下面给出一个简单类定义: class Account(object): num_accounts = 0 def __init__(self, name, balance): self.name =

  • C语言编程中的联合体union入门学习教程

    联合体(union)在C语言中是一个特殊的数据类型,能够存储不同类型的数据在同一个内存位置.可以定义一个联合体使用许多成员,但只有一个部件可以包含在任何时候给定的值.联合体会提供使用相同的存储器位置供多用途的有效方式. 定义联合体 要定义联合体,必须使用union语句很相似于定义结构.联合体声明中定义了一个新的数据类型,程序不止一个成员.联合体声明的格式如下: union [union tag] { member definition; member definition; ... member

  • Java线程编程中Thread类的基础学习教程

    一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time waiting.waiting.消亡(dead). 当需要新起一个线程来执行某个子任务时,就创建了一个线程.但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内

  • C++编程中new运算符的使用学习教程

    new运算符用作从自由存储为 type-name 的对象或对象数组分配内存,并将已适当分类的非零指针返回到对象. [::] new [placement] new-type-name [new-initializer] [::] new [placement] ( type-name ) [new-initializer] 备注 如果不成功,则 new 将返回零或引发异常:有关详细信息,请参阅 new 和 delete 运算符. 通过编写自定义异常处理例程并调用 _set_new_handler

  • Python编程中的for循环语句学习教程

    Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串. 语法: for循环的语法格式如下: for iterating_var in sequence: statements(s) 流程图: 实例: #!/usr/bin/python # -*- coding: UTF-8 -*- for letter in 'Python': # 第一个实例 print '当前字母 :', letter fruits = ['banana', 'apple', 'mango'] for f

  • 完全掌握C++编程中构造函数使用的超级学习教程

    构造函数是一种可初始化其类的实例的成员函数.构造函数具有与类相同的名称,没有返回值.构造函数可以具有任意数量的参数,类可以具有任意数量的重载构造函数.构造函数可以具有任何可访问性(公共.受保护或私有).如果未定义任何构造函数,则编译器会生成不采用任何参数的默认构造函数:可以通过将默认构造函数声明为已删除来重写此行为. 构造函数顺序 构造函数按此顺序执行工作: 按声明顺序调用基类和成员构造函数. 如果类派生自虚拟基类,则会将对象的虚拟基指针初始化. 如果类具有或继承了虚函数,则会将对象的虚函数指针

  • Java编程中的vector类用法学习笔记

    java.util.vector提供了向量类(vector)以实现类似动态数组的功能.在Java语言中没有指针的概念,但如果正确灵活地使用指针又确实可以大大提高程序的质量.比如在c,c++中所谓的"动态数组"一般都由指针来实现.为了弥补这个缺点,Java提供了丰富的类库来方便编程者使用,vector类便是其中之一.事实上,灵活使用数组也可以完成向量类的功能,但向量类中提供大量的方法大大方便了用户的使用. 创建了一个向量类的对象后,可以往其中随意插入不同类的对象,即不需顾及类型也不需预先

  • 详解JUC并发编程中的进程与线程学习

    目录 进程与线程 进程 线程 同步异步 串行并行执行时间 创建和运行线程 Thread 与 Runnable 的关系原理分析 查看进程 线程运行原理 线程上下文切换 start与run方法 sleep方法 sleep打断 join方法 interrupt 方法 守护进程 线程的状态 Java API 层面 总结 进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存.在指令运行过程中还需要用到磁盘.网络等设备.进程就是用来加载指令.管理内

  • Java中的数组基础知识学习教程

    数字 通常情况下,当我们处理数字时,使用原始数据类型,如 byte,int,long,double 等. 示例 int i = 5000; float gpa = 13.65; byte mask = 0xaf; 然而,在开发中,我们会遇到需要使用对象而不是原始数据类型的情况.为了实现这个, Java 为每个原始数据类型提供包装类. 所有的包装类 (Integer, Long, Byte, Double, Float, Short) 是抽象类 Number 的子类. 这种包装是由编译器处理,这个

随机推荐