基本数据类型

基本数据类型 — 空类型

C语言中的void关键字用于描述“没有具体类型或是没有内容”,其有3种常见使用场景:

1) 用于定义函数时说明其无返回值 (比如void f(int x,int y)的语法);

2) 用于定义函数时说明其没有参数(比如int f(void)的语法);

3) 用于定义无类型指针,可以指向任何类型的数据(void *p的语法);

 

基本数据类型 — int类型

整数(integer/int)类型由int关键字与long/short/unsigned组合而成。下面举例说明:

1) int:C90规定int取值范围至少为-32768~32767。这里的“至少”令人费解,因为在制定标准时考虑了对未来存储的兼容,在不同的机器/操作系统/编译器上,int可能允许更大范围的整数,比如在64位机器上,int会比16位机器的范围大;

2) long int:可简写为long,C90规定long int取值范围/内存占用不少于int,具体long int比int大多少,和机器/操作系统/编译器有关,在很多情况long int和int会分配一样的空间;

3) short int:可简写为short,和上述long int相同;

4) unsigned int:无符号整数,即不允许负数。其取值范围会平移,为0 ~65535。unsigned关键字也可以在声明时加在前面所说的其他的整数类型前;

5) 精确宽度int类型:考虑到int的范围与系统环境有关,C99标准库stdint.h和inttypes.h提供了精确宽度int类型(exact-width integer type),例如int32_t表示32位的有符号整数类型。在使用32位int的系统中,头文件会把int32_t作为int的别名。不同的系统也可以定义相同的类型名。例如,int为16位、long为32位的系统会把int32_t作为long的别名。然后,使用int32_t类型编写程序,并包含stdint.h头文件时,编译器会把int或long替换成与当前系统匹配的类型。精确宽度int类型需要底层系统的支持。

通常来说在代码或表达式中直接使用整数类型时(比如表达式22*333+22),这些整数是没有声明具体的类型的。但编译器通常会自己处理这个问题。当编译器发现表达式中的某个整数的取值范围超出int时,会尝试用long或unsigned作为其类型。事实上在直接使用整数的时候,可以在后面加上后缀L或U,分别表示long和unsigned。比如x = 22L * 33U。

 

基本数据类型 — char类型

char类型表示单个ASCII字符(比如英文字母、英文标点)。但实际上char类型也是整数类型,因为其存放的是字符的ASCII码。标准ASCII码的范围是0~127,只需7位二进制数即可表示,通常char类型被定义为8位的存储单元。其他系统(如macOS)还提供扩展ASCII码(比如Apple的LOGO字符)。

C语言不像其他语言那样可混用单引号双引号,其中的单引号表示字符,双引号表示字符串。所以char类型的赋值方式是x=’A’的形式,需要注意到如果使用char x = ‘FATE’这样的语法时,GCC不会报错误,但会报警告,变量x只会取最后的8位,也就是最后的结果是x = ‘E’。

另一问题是关于字符转义和对非打印字符ASCII码的处理,比如如果用char x = ”’赋值单引号这个字符是有歧义的,比如如何表示ASCII码表示换行的字符。C语言提供了这样几种处理方式:

1) 可通过整数ASCII码赋值,比如char x=’A’可写作char x=65;

2) 可通过\x+16进制ASCII码(比如char x = ‘\x41’),或\+8进制ASCII码(比如char x = ‘\101’);

3) 对于部分ASCII码C语言约定\+字符的方式,比如用\n表示ASCII码为10的换行符;

另外还有一些更特殊的ASCII符号,比如ASCII码为7的字符表示“主板蜂鸣器报警一次”。如果printf这个字符,有的机器真的会让主板响。

 

基本数据类型 — bool类型

C语言是没有布尔类型的,C语言约定了用int的0和1来表示真与假。在C99标准中引入了_Bool的基本类型,用于表示布尔值。它和C语言对char的处理类似,也是作为整数处理(0与1)。

 

基本数据类型 — float类型

顾名思义浮点就是记录“不定位置小数点”的类型。主要通过double/float关键字来声明。事实上浮点数更应看作另一种计算机下表示数的策略,而不仅是表示小数的方式,因为浮点数基于了科学记数法,这意味着浮点数可用于表示比int更大或更小范围的数。下面来看几种浮点类型:

1) float:C标准规定float至少要记录6位有效数字,并且取值范围至少是\(10^{-37} – 10^{37}\)。通常float会占用32位的空间,其结构是这样的,8位记录指数的值与其符号,24位记录有效数字与其符号。浮点数有两种声明的方式,一种是直接写成小数,比如float x=1.1。另一种是直接使用科学记数法,比如22.2可以写作float x=222e-1。也可以混合使用,比如float x=-222.222e-10;

2) double:即双精度的浮点数,double的取值范围和float相同,但C标准规定double至少要支持10位有效数字。通常double会占用64位的空间,不同的系统会按不同的方式分配这多出来的32位空间;

3) long double:C标准规定其精度(有效数字位数)至少和double相同;

在直接使用浮点数且不加后缀的情况下,编译器通常会把浮点数当作double类型处理。使用F和L后缀可以将浮点数分别作为float和long double处理。比如22.1L * 22e2F。

浮点数类型有一个非常不舒服的问题就是在运算和类型转换的时候,很容易丢失精度。

 

获取类型的大小

C语言内置了sizeof运算,用于返回类型所占用的字节数,具体用法如sizeof(long int)。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部