C/C++语言——数据类型

short、int、long、char、float、double 这六个关键字代表C语言里的六种基本数据类型。

术语宽度(width)用于描述存储整数时使用的内存量,使用的内存量越大,可以表示的整数值范围也越大。C的内置运算符sizeof以字节为单位给出类型的大小。
32位编译器:
char:1个字节
char*(即指针变量):4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short:2个字节
int:4个字节
unsigned int:4个字节
float:4个字节
double:8个字节
long:4个字节
long long:8个字节
unsigned long:4个字节

64位编译器:
char:1个字节
char*(即指针变量):8个字节
short:2个字节
int:4个字节
unsigned int:4个字节
float:4个字节
double:8个字节
long:8个字节
long long:8个字节
unsigned long:8个字节

1. char类型
        char类型用于存储字母,数字和标点符号之类的字符
。但是在技术实现上, char却是整数类型,这是因为char类型实际存储的是整数而不是字符。为了处理字符,计算机使用一种数字编码,用特定的整数表示特定的字符。
        最常用的编码是 ASCII码,在ASCII码中,整数值 65代表大写字母A;因此要存储字母A,实际只需要存储65。标准 ASCII码值的范围从0到127,只需7位即可表示。而 char类型通常定义为使用8位内存单元,该大小容纳标准 ASCII编码是绰绰有余的。许多系统提供的不同的扩展 ASCII编码也是使用 8位存储单元。更普遍一些来看,C/C++保证 char类型足够大,以存储其实现所在的系统上的基本字符集。
        许多字符集包含先多于 127甚至远多于 255个值,商用的 Unicode字符集建立了一个能够表示世界范围内多种字符集的系统,目前已有超过 96000个字符。采用这一集合作为基本字符集的平台应该使用 16位甚至32位的char表示方法。C把一个字节(byte)定义为 char类型使用的位(bit)数。所以在这样的系统上,C文档中提到的一个字节是 16位或者 32位,而不是 8位。

char character;/*声明一个char变量*/
character = ‘T’;/*单引号中的一个字符是一个字符常量*/
character = 56;/*对于 ASCII,正确。推荐使用字符常量,而不是数值编码*/
character = T;/*不使用单引号,编译器会将T视为一个变量名*/
character = “T”;/*ERROR:编译器视为一个字符串,不能将"const char *"类型的值分配到"char"类型的实体*/

unsigned char类型的表示范围通常为:0~255
signed char类型的表示范围通常为:-128~127

1) wchar_t类型
宽字符类型,是一种整数类型,它有足够的空间,可以表示系统使用的最大扩展字符集。

  • wcin和wcout可用于处理wchar_t流。
  • 通过前缀L表示宽字符常量和宽字符串:
wchar_t bob = L’P’;    //a wide-character constant
wcout << L”tall” << endl;    //outputting a wide-character string

2) char16_t和char32_t
char16_t:无符号类型,长16位
通过前缀u表示char16_t字符常量和字符串常量。

char32_t:无符号类型,长32位
通过前缀U表示char32_t字符常量和字符串常量。


2. short/int/long类型
1) 有符号整数

有符号整数可以取正值及负值,关键字signed可以和任何有符号类型一起使用,以明确表示这一属性。

short类型:
short int类型(简写为short类型)可能占用比int类型更少的存储空间,用于仅需小数值的场合以节省空间。
short类型不得长于int类型。C保证short类型至少有16位长。

int 类型:
int 类型是系统的基本整数类型。C保证int类型至少有16位长。
后缀u或U,表示该整型为unsigned int常量

long类型:
long int类型(简写为long类型)可能占用比 int类型更多的存储空间,用于使用大数值的场合。
int类型不得长于long类型。C保证long至少有32位长。
后缀l或L,表示该整型为long常量
后缀ul或UL,表示该整型为unsigned long常量

long long类型:
long long int 类型(简写为 long long类型),可能占有用比long更多的存储空间,用于使用更大数值的场合。
long类型不得长于long long类型。C保证long long类型至少有64位长。
后缀ll或LL,表示该整型为long long常量
后缀ull或ULL,表示该整型为unsigned long long常量

整型数:
        整型数除了用十进制表示外,还可以用八进制或十六进制表示。带前缀0的整型常量表示它为八进制形式;前缀为0x或0X,则表示它为十六进制形式

2) 无符号整数
无符号整数只有0和正值,这使得无符号数可以表达比有符号数更大的正值。使用 unsigned关键字表示无符号数。

unsigned int类型:
 unsigned int类型(简写为 unsigned类型)用于只使用非负值的场合。这种类型同有符号的表示范围不同。
16位的unsigned int 取值范围为 0 到65535,由于指示数值正负的位也被用于二进制位,所以无符号数可以表示更大的数值。
        在 C90标准中,还允许 unsigned long int (简写 unsigned long)和 unsigned short int (简写 unsigned short)类型。 C99又增加了 unsigned long long int(简写为 unsigned long long)类型。

3) 整数溢出
C 语言标准规定了每种基本数据类型的最小取值范围:

  • 对应于16位单位,short类型和int类型的最小取值范围为 -32768 到 32767;
  • 对应于32位单位,long类型的最小取值范围为 -2147483648 到 2147483647;
  • 对于unsigned short类型 和unsigned int类型,最小取值范围为 0 到 65535;
  • 对于unsigned long类型,最小取值范围为 0 到 4294967295;
  • 对于long long类型,是为了支持64位的需求,最小取值范围是数目可观的 -9223372036854775807 到9223372036854775807;
  • unsigned long long 类型的最小取值范围为 0 到 18446744073709551615。

3. float/double/long double类型
float类型:

        C标准规定, float类型必须至少能表示 6位有效数字 ,取值范围至少为 10-37 到 10+37。通常,系统使用 32位存储一个浮点数。其中 8位用于表示指数及其符号, 24位用于表示非指数的部分(称为尾数或有效数字)及其符号。

double类型:
        C提供double(称为双精度)浮点类型。double类型和 float类型具有相同的最小取值范围,但它 必须至少能表示10位有效数字 。一般地,double使用64位而不是32位长度。一些系统将多出的32位全部用于尾数部分,这增加了数值的精度并减少了舍入误差。其他的一些系统将其中的一些位分配给指数部分,以容纳更大的指数,从而增加了可以表示的数的范围。每种分配方法都使得数值至少具有13位有效数字,超出了C的最小标准规定。

long double类型:
C 提供long double 浮点类型,以满足比 double类型更高的需求。不过,C 只保证 long double 类型至少同 double 类型一样精确。

浮点数常量:
        浮点数常量中包含一个小数点或一个指数,也可以两者都有。没有后缀的浮点数常量为double类型,后缀f或F表示float类型,后缀l或L则表示long double类型
将浮点值转换为整数时,C简单地丢弃小数部分(截尾),而不进行四舍五入。

4. _Bool类型
        _Bool类型 由C99和ANSI/ISO C++引入,用于表示布尔值,即逻辑值 true(真)与 false(假)。 原则上它仅仅需要1位来进行存储。 程序使用布尔值来选择执行哪个代码分支。

C用值1表示 true,用值 0表示 false ,所以 _Bool类型实际上也是一种整数类型。
C++将非零值解释为true,将零解释为fals e,所以任何数字值或指针值都可以被隐式转换为bool值。

5. 结构体struct类型
        函数的参数尽量不多于4 个,
如果函数的参数多于4 个使用起来非常容易出错(包括每个参数的意义和顺序都容易弄错),效率也会降低(与具体CPU 有关)。 这个时候,可以用结构体压缩参数个数
struct student
{
}stu;
sizeof(stu) = 1;
        编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。编译器理所当然的认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要1 个byte(char 型的数据成员,大小为1byte。这里不考虑内存对齐的情况),编译器为每个结构体类型数据至少预留1 个byte的空间。所以,空结构体的大小就定位1 个byte。
        结构是一个或多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下。结构可以拷贝、赋值、传递给函数,结构类型也可以作为函数返回的返回值。

关键字struct引入结构声明:
struct 结构标记
{
一系列声明
};

  • struct声明定义了一种数据类型
struct {...} x, y; 从语法角度来说,与声明int x, y; 具有相似的意义
  • 如果结构声明的后面不带变量表,则不需要为它分配存储空间,它仅仅描述了一个结构的模版或轮廓。但是,如果结构声明中带有标记,那么在以后定义结构实例时便可以使用该标记定义
  • 在表达式中,可以通过下列形式引用某个特定结构中的成员:结构名.成员

6. 共用体union类型
union 中所有的数据成员共用一个空间, 同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址
union StateMachine
 {
    char character;
    int number;
    char *str;
    double exp;
 };
一个union 只配置一个足够大的空间以来容纳最大长度的数据成员 ,以上例而言,最大长度是double 类型,所以StateMachine 的空间大小就是double 数据类型的大小。

共用体的用途:
  • 当数据项使用两种或更多种格式(但不会同时使用时)可节省空间。
  • 匿名共用体(anonymous union)没有名称,其成员将成为位于相同地址处的变量,每次只有一个成员是当前的成员。
假设管理一个小商品目录,其中一些商品的ID为整数,而另一些的ID为字符串。
struct widget
{
    char brand[20];
    int type;
    union
    {
        long id_num;
        char id_char[20];
    };
}prize;
if (prize.type == 1)
    cin >> prize.id_num;
else
    cin >> prize.id_char;
程序员负责确定当前哪个成员是活动的。

共用体常用于节省内存,用于嵌入式开发,操作系统数据结构或硬件数据结构。

7. 枚举enum类型
枚举常量:一个常量整型值的列表

enum boolean {NO, YES};
用来初始化枚举成员的值必须是一个常量表达式(constant expression,编译器在编译时就能够计算出结果的整型表达式)

设置枚举量的值:
  • 在没有显式说明的情况下,enum类型中第一个枚举名的值为0,第二个为1,第三个为2,以此类推。如果只指定了部分枚举名的值,那么未指定值的枚举名的值将依着最后一个指定值向后递增
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}
FEB的值为2, MAR的值为3,依此类推
  • 可以使用赋值运算符来显式地设置枚举量的值
enum bits {one = 1, two = 2, four = 4, eight = 8};
  • 指定的值必须为整数(可以使用long甚至long long类型的值)
enum bigstep{first, second = 100, third};
first为0,third值为101
  • 可以创建多个值相同的枚举量
enum {zero, null = 0, one, numero = 1};
zero,null值为0,one, numero值为1.

枚举变量
可以用枚举名来声明这种类型的变量:months m;
  • 在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋给枚举的变量
m = MAR; //valid , MAR is an enumerator
m = 20; //invalid , 20 not an enumerator
  • 枚举只定义了赋值运算符,没有定义算术运算
++m; //invalid
m = JUL + AUG; //invalid
  • 枚举量是整型,可被提升为int类型,int类型不能自动转换为枚举类型
int now = AUG; //valid, months type promoted to int
m = 3; //invalid, int not converted to months
now = 3 + AUG; //valid, AUG converted to int
  • 如果int值是有效的,则可以通过强制类型转换,将它赋给枚举变量
m = months(3);
  • 如果试图对一个不适当的值进行强制类型转换,结果是不确定的,不能依赖得到的结果。
m = months(1000); //undefined

枚举的取值范围
每个枚举都有取值范围(range),通过强制类型转换,可以将取值范围中的任何整数值赋给枚举变量,即使这个值不是枚举值。

上限: 找出枚举量的最大值,找出大于这个最大值的,最小的2的幂,将它减去1,结果便是取值范围的上限。
如果最大枚举量是101,在2的幂中,比这个数大的最小值为128,因此取值范围的上限为127。

下限: 找出枚举量的最小值。如果不小于0,则取值范围的下限为0。否则使用与上限相同的方式,但加上负号。
如果最小枚举量是-6,在2的幂中,比这个数小的最大值为-8,因此取值范围的下限为-7。

8. void类型
void 类型没有对应的值,通常用作无返回值函数的返回类型。
void 不能代表一个真实的变量。因为定义变量时必须分配内存空间。
  • 如果函数没有返回值,那么应声明为void 类型
        在C语言中,凡不加返回值类型限定的函数,就会被编译器作为返回整型值处理。因此,为了避免混乱,我们在编写C 程序时,对于任何函数都必须一个不漏地指定其类型。如果函数没有返回值,一定要声明为void 类型。这既是程序良好可读性的需要,也是编程规范性的要求。
  • 如果函数无参数,那么应声明其参数为void
无论在C 还是C++中,若函数不接受任何参数,一定要指明参数为void。
  • 任何类型的指针都可以直接赋值给void *,无需进行强制类型转换
void *p1;
int *p2;
p1 = p2;

按照ANSI标准,不能对void 指针进行算法操作,即下列操作都是不合法的:
void * pvoid;
pvoid++;    //ANSI:错误
pvoid += 1;    //ANSI:错误
ANSI 标准坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。也就是说必须知道内存目的地址的确切值。

但是GNU则认定:void *的算法操作与char *一致。因此下列语句在GNU 编译器中皆正确:
pvoid++;    //GNU:正确
pvoid += 1;  //GNU:正确
在实际的程序设计中,为符合ANSI 标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:
void * pvoid;
(char *)pvoid++; //ANSI:正确;GNU:正确
(char *)pvoid += 1; //ANSI:错误;GNU:正确
  • 如果函数的参数可以是任意类型指针,那么应声明其参数为void *
典型的如内存操作函数memcpy 和memset 的函数原型分别为:
void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );
这样,任何类型的指针都可以传入memcpy 和memset 中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值