文章目录
通过前面的学习,我们已经了解了C语言的基本内容,认识到程序 = 算法+数据,而C语言中数据是有类型的,这章对C语言的基本数据类型做一个较全面的介绍。
- 数据类型
- 基本数据类型
- 整型 int
- 实型(浮点型)float double
- 字符型 char
- 构造数据类型
- 数组、结构、联合、枚举
- 指针类型
- 基本数据类型
8.1 整数类型
C语言支持两种根本不同的数值类型:整数类型(整型)和浮点类型(浮点型)。整数类型的值是整数,而浮点类型的值可能有小数部分。整数类型又可以从有无符号分为两大类:有符号和无符号,从其表示范围分为几类:短、中、长。之前使用的int类型属于有符号、中长度的整型。
有符号和无符号整数的区别在于表示整数的二进制位最高位(最左边的位)是否用来表示符号位,有符号整数用最高位表示数的符号,1来表示负数,0表示正数或者0(具体来说用有符号整数用补码表示数)。而无符号整数没有符号位,全部二进制位都用来表示正数或者0。因此,4个字节,共32位的无符号整数可以表示的数的范围是[0, 232-1],即[000000000000000000000000000000002,111111111111111111111111111111112]。如果是32位的有符号整数,那么由于最高位是符号位,故其表示的数的范围是[-231, 231-1]。基本上是将无符号可以表示的整数分两半,一半表示负数,一半表示正数。在有符号整数类型名称前面加上unsigned就是无符号整数类型。
用不同的字节数来存储整数造成整数的范围不同,C语言规定了从小到大3种不同长度的整数类型:short int、int、long int。每种长度的整数类型,又可以分为有符号和无符号两种类型。所以在C89中有6种整数类型。
麻烦的是,C标准并没有规定short int、int、long int具体的字节长度是多大,只是规定了:
- short int、int、long int中的每种类型都要覆盖一个最小取值范围。
- int类型的范围大于等于short int的范围,long int类型的范围大于等于int类型的范围。
这样的规定导致在不同的机器、编译环境下它们有不同的取值范围(这点比Java复杂,Java会确定整数类型的字节大小)。还好的是,在特定位数的机器下,它们的取值范围通常是相对固定的。比如,在目前比较常见的32位环境下,它们的长度和范围如下
类型名 | 简称 | 字节数 | 范围 | ----- | 类型名 | 简称 | 字节数 | 范围 |
---|---|---|---|---|---|---|---|---|
short int | short | 2字节/16位(有符号) | -215 to 215-1 (-32, 768 to 32,767) | ----- | unsigned short int | unsigned short | 2字节/16位(无符号) | 0 to 216-1 (65535) |
int | 4字节/32位(有符号) | -231 to 231-1 ((-2147483648 to 2147483647) | ----- | unsigned int | unsigned | 4字节/32位(无符号) | 0 to 232-1 (4294967295) | |
long int | long | 4字节/32位(有符号) | -231 to 231-1 ((-2147483648 to 2147483647) | ----- | unsigned long int | unsigned long | 4字节/32位(无符号) | 0 to 232-1 (4294967295) |
可以看到,在这种环境下,long int和int是完全一样的。
如果在64位机器下,short和int与32位相同,分别占2字节和4字节,但是long占8字节,故有:
类型名 | 简称 | 字节数 | 范围 | ----- | 类型名 | 简称 | 字节数 | 范围 |
---|---|---|---|---|---|---|---|---|
short int | short | 2字节/16位(有符号) | -215 to 215-1 (-32, 768 to 32,767) | ----- | unsigned short int | unsigned short | 2字节/16位(无符号) | 0 to 216-1 (65535) |
int | 4字节/32位(有符号) | -231 to 231-1 ((-2147483648 to 2147483647) | ----- | unsigned int | unsigned | 4字节/32位(无符号) | 0 to 232-1 (4294967295) | |
long int | long | 8字节/64位(有符号) | -263 to 263-1 ((-9223372036854775808 to 9223372036854775807) | ----- | unsigned long int | unsigned long | 8字节/64位(无符号) | 0 to 264-1 (18446744073709551615) |
值得强调的是这些表给出的范围不是C标准强制的,随着编译环境的不同而不同。确定整数类型的一种方法是检查<limits.h>头。该头是标准库的一部分,其中定义了表示每种整数类型的最大值和最小值的宏。
#include <stdio.h>
#include <limits.h>
int main()
{
printf("The minimum value of SHORT INT = %d\n", SHRT_MIN);
printf("The maximum value of SHORT INT = %d\n", SHRT_MAX);
printf("The minimum value of INT = %d\n", INT_MIN);
printf("The maximum value of INT = %d\n", INT_MAX);
printf("The minimum value of LONG = %ld\n", LONG_MIN);
printf("The maximum value of LONG = %ld\n", LONG_MAX);
return 0;
}
还可以使用sizeof运算符来得到各种类型占了几个字节。根据字节数也可以确定其值取值范围。其用法是
sizeof(类型名)
或者sizeof(表达式)
sizeof(表达式)
的含义是先计算表达式的值,然后得到存储该值的类型占几个字节。
#include <stdio.h>
int main()
{
printf("The bytes of short int = %d\n", sizeof(short int));
printf("The bytes of int = %d\n", sizeof(10));
printf("The bytes of long = %d\n", sizeof(long));
return 0;
}
实际上,sizeof是运算符,因此在sizeof应用于表达式时不要求加圆括号,因此我们可以用sizeof i
代替sizeof(i)
。但是由于sizeof
运算符是一元运算符,其优先级较高,故sizeof i * f
会被解释为(sizeof i) * f
,可能与我们的期望不同,故建议始终加上圆括号。
8.1.1 C99中的整数类型
C99中提供了两种额外的标准整数类型:long long int和unsigned long long int。增加这两种整数类型有两个原因,一是为了满足日益增长的对超大型整数的需求,而是为了适应支持64位运算的新处理器的能力。这两个long long类型要求至少8个字节,64位宽,所以long long int类型值的范围通常为-263(-9 223 372 036 854 75 808)到263-1(9 223 372 036 854 75 807),而unsigned long long int类型值的范围通常为0到264-1(18 446 744 073 709 551 615)。
8.1.2 整数常量
在程序中以文本形式出现的数,而不是读、写或计算出来的数,称为整数常量,或者整数字面量。比如10,453。C语言除了允许用十进制书写整数常量,还支持用八进制和十六进制书写整数。
如同十进制的每个位是以10的幂为基底一样,八进制的数以8的幂为基底,而且只包含0~7,比如,八进制数237表示成十进制就是2 × 82 + 3 × 81 + 7 × 80 = 128 + 24 + 7 = 159。
十六进制的数以16的幂为基底,而且用数字0~9加上字母A~F来书写,其中A~F表示10~15之间的各个数。比如,十六进制数1AF表示成十进制就是1 × 162 + 10 × 161 + 15 × 160 = 256 + 160 + 15 = 431。
假如没有特殊的标志,很多数我们无法区别它们采用的是哪种进制,因此C语言有如下规定:
- 十进制常量包含0~9中的数字,但是一定不能以零开头。
如,15、345、-6574 - 八进制常量包含0~7中的数字,而且必须以零开头。
如,034、017、-0645 - 十六进制常量包含0~9中的数字和A~F中的字母,而且必须以0X开头,十六进制常量中的所有字母既可以是大写,也可以是小写。如,0xff、0xfF 、0xFF、0Xff、0xfF
注意,无论是十进制、八进制还是十六进制,它们都是数的书写方式,真正存储在计算机中的是二进制。一个式子中出现多种书写形式是可以的:10 + 015 + 0x11的值等于10+13+17(十进制)。八进制和十六进制更适合于底层程序的编写,一般情况不需要使用。
十进制整数常量的类型通常为int,但如果常量的值大到无法存储在int中,就用long int类型。如果出现long int类型也无法存储,编译器用unsigned long int做尝试。确定八进制和十六进制常量的规则略有不同:编译器会依次尝试int、unsigned int、long int和unsigned long int类型,直到找到能表示该常量的类型。
有时候可以强制编译器把常量当做长整数来处理,只需在后面加一个字母L(或者l):
15L 0377L 0x4567L
为了指明常量是无符号的,可以加上字母U(或者u):
15U 456U 0xFFFFU
L和U可以结合使用,表示常量既是长整型又是无符号整型。(字母的顺序和大小写无所谓)
8.1.3 C99中的整数常量
在C99中用LL或者ll(两个字母的大小写要一致)表示long long int型。C99确定整数常量类型的规则和C89有些不同。对于没有后缀(U、u、L、l、LL、ll)的十进制常量,其类型是int、long int、long long int中能表示该值的最小类型。对于八进制和十六进制常量,可能的顺序类型为int、unsigned int、long int、unsigned long int、long long int和unsigned long long int。后面的任何后缀都会改变可能类型的列表。比如,以U(或u)结尾的常量类型一定是unsigned int、unsigned long int、unsigned long long int的一种,以L(或l)结尾的十进制常量类型一定是long int和long long int中的一种。
8.1.4 读写整数
由于整数值有八进制、十进制、十六进制这3种常用表现形式,还有有符号、无符号整数,以及短整型、长整型的区别,故读写这些类型的整数时,需要使用新的转换说明符。下表总结了各种类型和进制下的转换说明符。
printf写函数的转换说明符使用说明:
有符号十进制 | 无符号八进制 | 无符号十进制 | 无符号十六进制 | |
---|---|---|---|---|
正常整型 | d | o | u | x |
短整型 | hd | ho | hu | hx |
长整型 | ld | lo | lu | lx |
长长整型(C99标准) | lld | llo | llu | llx |
短整型在正常整型转换说明符前面加上字母h;长整型在正常整型转换说明符前面加上字母l;长长整型在正常整型转换说明符前面加上字母ll(C99标准下才有长长整型)。
比如,读写短整型,
short s;
scanf("%hd", &s);
printf("%hd", s);
在C99标准中,有长长整数类型,读写这个类型的变量,在d、o、u或x前面加上字母ll:
long long ll;
scanf("%lld", &ll);
printf("%lld", ll);
可能有人会问,在输入有符号整数的时候,能否以八进制或者十六进制输入?这是可以的,只需要将%d替换为%i,输入八进制整数时,以0开头,输入十六进制时,以0x开头。
int a = 0;
scanf("%i", &a); // 输入:017 (15的八进制 )
printf("%d\n", a);
scanf("%i", &a); // 输入:0xf (15的十六进制 )
printf("%d\n", a);
那么在输出有符号整数的时候,能否以八进制或者十六进制的形式输出整数值呢?由于C语言没有对有符号输出为八进制或者十六进制的转换说明符,故要借助于无符号整数可以输出为八进制或者十六进制,比如
int x = 20;
printf("%o", x); // 将x看成为无符号整数来输出
输出:
如果要输出的是负值,需要输出其绝对值,并添加输出负号
int x = -20;
printf("-%o", -x); // 输出负号和负数的绝对值
输出:
8.2 浮点类型
整数类型无法存储带小数点的数,这就需要浮点数。相比整数的范围,浮点类型的数的范围也是很大的,因此需要很大或者很小的数时也可以考虑浮点数。浮点类型由于小数点是“浮动的”得名,C语言提供了3种浮点类型:
- float:单精度浮点数
- double:双精度浮点数
- long double:扩展精度浮点数
当精度要求不严格时(例如,计算带一位小数的温度),float类型是很适合的类型。double提供更高的精度,对绝大多数程序都够用了。long double支持极高精度的要求,很少会用到。
类似整数类型,C标准没有说明float、double和long double类型提供的范围和精度到底是多少,不同的计算机可以用不同方法存储浮点数。大多数现代计算机都遵循IEEE 754(即IEC 60559)的规范。
IEEE标准提供了两种主要的浮点数格式:单精度(32位)和双精度(64位)。数值以科学计数法的形式存储,每一个数都由三部分组成:符号、指数和小数。指数部分的位数说明了数值的可能大小程度,而小数部分的位数说明了精度。显然,总位数越多,指数和小数部分相应分到的位数也越多,范围也就越大,精度也越高。
类型 | 最小正值 | 最大值 | 精度 |
---|---|---|---|
float | 1.175 49 × 10 -38 | 3.402 82 × 10 38 | 6个数字 |
double | 2.225 07 × 10 -308 | 1.797 69 × 10 308 | 15个数字 |
在不遵循IEEE标准的计算机上,上表是无效的。事实上,在一些机器上,float可以有和double相同的数值集合,或者double可以有和long double相同的数值集合。不同于在头<limits.h>中查看整型范围的宏,在<float.h>头文件中查看浮点类型特征的宏。
8.2.1 浮点数常量
浮点常量可以有很多种书写方式。例如,下面这些常量全都是表示数57.0的有效方式:
- 57.0
- 57.
- 57.0e0
- 57E0
- 5.7e1
- 5.7e+1
- .57e2
- 570.e-1
浮点常量必须包含小数点或者指数(否则会当做整数常量):其中指数指明了对前面的数进行缩放的10的幂次。如果有指数,需要在指数前面放置字母E或者e。可选符号+或-可以出现在字母的后边,注意,这里的+或-是指数幂次的正负。可以参考科学计数法。
默认情况下, 浮点常量以双精度数的形式存储。比如,C程序中的浮点常量57.0,是以double类型存储的,如果要以float类型存储,可以在浮点常量的末尾加上F或者f,比如57.0F;为了说明浮点常量必须以long double格式存储,可以在浮点常量末尾加上字母L或者l,比如57.0L。
8.2.2 读写浮点数
读取double类型的值时,在e、f或g前放置字母l:
double d;
scanf("%lf", &d);
C99之前,用printf输出double类型的值时,不要加l,直接用e、f或g,C99允许printf函数使用%le、%lf和%lg,这样与float类型不加l形成对比,但是字母l不起作用。
读写long double类型的值时,在e、f或g前放置字母L:
long double ld;
scanf("%Lf", &ld);
printf("%Lf", ld);
8.3 数值类型小结
8.3.1 整数类型的问题
整型相比于浮点型,对数值的表示是精确的,但是问题是每一种整型变量的范围都是有限的,相比于浮点型,范围更要小很多。整数运算的时候很容易出现“溢出”现象。比如
int i = 100000 * 100000;
printf("%d\n", i);
显示结果不正确,因为正确的结果超出了int型的范围。还有
short i = 32767 + 1;
printf("%hd\n", i);
结果显示为负数。这也是因为溢出问题。
整数类型有好多种,建议范围足够的话就使用int,注意不要使用无符号整型,尤其是和有符号整型混用。
8.3.2 浮点类型的问题
与整数类型相反,浮点类型的优点是表示的数值范围很大,但是精度有限。(这也很好理解,像32位机器上,int和float都用4个字节表示,那么在精度和范围之中只能二取一,无法做到兼顾,毕竟用来存储的二进制位是有限的。)
float a = 1000.43f, b = 1000.0f;
printf("%f\n", a - b);
就像1/3是无限循环小数0.3333…一样,有的数本身也就无法用固定的位数表示。比如,
printf("%.16f\n", 2.0 - 1.1);
浮点型有几种,建议日常就使用double类型,一般情况下精度足够了。
8.4 字符类型
字符类型变量用来存储字符
char ch;
ch = 'a';
ch = '0';
ch = ' ';
问题来了,字符变量ch是如何存储字母’a’、'0’以及空格的呢?还有它还可以存储其它的字符有哪些呢?在字符类型上还有哪些操作呢?
实际上,这几个问题是紧密相关的。C语言中存储字符,实际上存储的是字符在ASCII字符集下的码值,比如,字符’a’的码值为97,‘A’的码值为65,而空格字符’ '的码值为32。就像用int类型变量存储整数那样,char类型变量也是存储了这些字符的整数码值。故C语言把char类型当做小整数来处理。只是因为char类型变量只占1个字节,即8个位,故其表示的整数范围有限。在ASCII编码中,字符的取值范围是00000002~11111112,可以看成是0~127的整数,它们是可以被8位char类型变量全部存储的。
C语言把char类型当做小整数来处理。比如
char ch;
int i;
i = 'a'; // i里面存储了'a'的码值97
ch = 97; //ch里面存储了码值97,被认为存储了'a'
ch += 1; //ch里面存储了码值98,被认为存储了'b'
判断字符是否是小写字母,
if ('a' <= ch && ch <= 'z'){
ch = ch - ('a' - 'A'); // 将ch转换为了其对应的大写字母
}
上述两块代码有意义是因为’a’~‘z’以及’A’~'Z’的码值是连续的。尽管字符类型可以当成小整数来处理,但是处理的方式还是与字符相关的,并不适合做一般意义上的算术运算,比如乘法或者除法,像'a' * 3
或者'a' + ‘b’
就是语法允许,但是没有意义的运算。
8.4.1 转义字符
一般情况下,字符常量是用单引号括起来的。而然有些字符是无法用上述方式书写的,有些字符无法键盘输入。因此,C语言提供了一种特殊的表示法:转义序列。
转义序列共有两种形式:字符转义序列和数字转义序列。
下表给出完整的字符转义序列
名称 | 转义序列 |
---|---|
警报(响铃)符 | \a |
回退符 | \b |
换页符 | \f |
换行符 | \n |
回车符 | \r |
水平制表符 | \t |
垂直制表符 | \v |
反斜杠 | \\ |
问号 | \? |
单引号 | \’ |
双引号 | \" |
最常用的转义字符是’\n’,表示输出一个换行,接下来的输出会另起一行。如果printf输出内容中有反斜杠、单引号或者双引号,需要用反斜杠’\'对它们进行转义。
转义序列列表没有包含所有无法打印的ASCII字符,只包含了最常用的。而数字转义序列可以表示任何字符。
为了把特殊字符写成数字转义序列,首先需要在ASCII码表中查找字符的八进制或十六进制值。比如,换行符(十进制10)对应的八进制值为12,对应的十六进制值为a
- 八进制转义序列 由字符\和跟随其后的一个最多含有三位数字的八进制数组成。比如,上述字符写成\12。注意这里与八进制整数常量不同,不要写开头的0。
- 十六进制转义序列 由\x和跟随其后的一个十六进制数组成。上述字符写成\xa或\xA的形式。字符x必须小写,这与十六进制常量中字母大小写都可以有所不同。注意这里也与十六进制整数常量不同,不要写开头的0。
作为字符常量使用时,转义序列必须用一对单引号括起来,比如,换行符要写成’\12’或者’\xa’。转义序列可能有些隐晦,所以采用#define的方式给它们起个容易理解的名字是个不错的主意,比如:
#define ESX '\33'
8.4.2 用scanf和printf读/写字符
字符变量的读写转换说明使用%c:
char ch;
scanf("%c", &ch);
printf("%c", ch);
这里有一个容易出错的地方是所有的字符,包括空格、换行符都是字符,都可以被读取到字符变量中,这与读取数值类型是不同的,读取数值类型的时候是会自动跳过空格、换行符的。但是读取字符的时候不会。如果下一个未读字符是空格,那么例子中scanf函数将把空格读到ch中。而一般这都不是我们的本意。为了强制scanf函数在读入实际关注的字符前跳过空白字符,需要在格式串中的转换说明符%c前加上一个空格:
scanf(" %c", &ch);
scanf格式串中的空白字符意味着“跳过零个或多个空白字符”。空白字符包含空格、换行符、制表符。
因为通常情况下scanf函数不会跳过空白,所以它很容易检查到输入行的结尾:检查刚读入的字符是否为换行符。例如,下面的循环将读入并且忽略掉当前输入行中剩下的所有字符:
do{
scanf("%c", &ch);
}while(ch != '\n');
那么下次再调用scanf函数时,将从下一行开始读入。这个方法可以忽略当前行剩余未读的字符。
8.4.3 用getchar()和putchar()读/写字符
C语言还提供了单独的两个函数专门用来读/写字符,读字符是getchar()函数,写字符是putchar()函数。
每次调用getchar()时,它会读入一个字符并将其返回。如果需要保存这个字符,需要用赋值语句将它存储到变量中:
ch = getchar();
这句话相当于
scanf("%c", &ch);
getchar()返回的是int类型,因此也可以用int变量接收返回值。
和scanf函数一样,getchar()函数也不会在读取的时候跳过空白字符。
putchar(ch)
写单个字符ch,这句话相当于
printf("%c", ch);
读/写字符时,使用getchar函数和putchar函数比scanf和printf函数效率要高一些。
8.4.4 读字符常见问题
混合使用scanf和getchar时注意scanf函数倾向于遗留下它“扫视”过但是未读取的字符(包括空格、换行符等,读取数值类型时这个现象非常常见)。假如下面的程序的输入内容与我们常规的输入一致,即输入一个整数后按下换行,那么getchar读回的就是这个换行符。或者是空格,反正就是紧跟着整数之后的第一个字符。
int i;
char c;
printf("请输入一个整数:");
scanf("%d", &i);
printf("请输入一个字符:");
c = getchar();
如果可能出现这样的问题,建议还是使用scanf读字符,并注意在读字符的格式串前加空格:scanf(" %c", &c)
。
8.5 类型转换
上面我们已经看了,C语言中有不同的类型,由于字符类型本质上是一种小整数类型,因此也可以把它看成是一种整数类型。因此,C语言中可以进行数值运算的“算术类型”有:
- 整型:
- 字符(char)
- 有符号整数(short int、int、long int)
- 无符号整数(unsigned short int、unsigned int、unsigned long int)
- 浮点型(float 、double 、long double)
那么支持在一个算术表达式中出现不同的“算术类型”吗,如果支持,那么运算的时候遵循什么规则呢?
C语言支持不同的“算术类型”参与运算,但是会做一些转换。转换的原则是:
- 会将它们转换为同一类型再进行运算。
- 尽量保留数值信息,减少转换信息损失。
下面就从隐式转换和显式转换两种转换介绍转换规则。隐式转换指编译器自动处理不同类型的运算,不需要程序员介入,显式转换指程序中用强制类型转换运算符进行显式的转换。
8.5.1 隐式类型转换
下面的情况会发生隐式类型转换:
- 当算术表达式或逻辑表达式中操作数的类型不同时。
- 当赋值运算符右侧表达式的类型和左侧变量的类型不同时。
- 当函数调用中的实参类型与其对应的形式参数不同时。
- 当return语句中表达式的类型和函数返回值类型不同时。
由于函数还没有介绍,这里将讨论前两种情况,3、4种函数的情况本质上与第2种情况是类似的。
8.5.1.1 隐式类型转换之算术转换
执行常用算术转换的规则还可以划分为两种情况。
-
操作数含有浮点类型的情况(任一个操作数是浮点类型)。按照下图将类型较狭小的操作数进行提升:
-
两个操作数的类型都不是浮点型的情况(两个操作数都是整数类型)。
首先对两个操作数进行整数提升(将类型低于int类型的值转换为int型或者unsigned int,比如字符型,短整型)。然后按照下图对类型较狭小的类型进行提升:
有一种特殊情况,在unsigend long int类型和long int类型长度相同时,它们都会转化为unsigned long int类型。
这个规则看似合理,实际在使用中,如果提升后两个操作数一个是有符号的,一个是无符号的,那么很可能出现意想不到的问题。比如,一个操作数是int型x,值为-10,一个是unsigned int型,值为10。显然,x是小于y的,但是,如果写出x < y
这样的式子,得到的结果却是假。这是因为x < y
会将int型的x值转换为unsigned int再进行比较,而-10转换为unsigned int值为一个很大的整数4 294 967 296,所以x < y
的结果为假,不是期望的真。由于此类陷阱的存在,所以最好避免使用无符号整数,尤其是不要把它和有符号整数混用。
8.5.1.2 隐式类型转换之赋值转换
赋值过程中的转换遵循另外的规则,就是把赋值号右边表达式的值转换为左边变量的类型。如果变量的“宽度”比表达式的值要大,那么转换不会损失信息,否则,就丢失信息,甚至得到无意义的结果。
比如,不损失信息的转换:
char c = 'a';
int i;
float f;
double d;
i = c;
f = i;
d = f;
会损失信息的转换:
int i;
i = 829.5; // i是829
如果把超过变量类型范围的值赋值给变量,结果没有意义:
char c;
c = 1000;
i = 1.0e20;
f = 1.0e100;
这些变量赋值得到了无意义的值。
浮点常量赋值给float型变量时,一个很好的方法是在浮点常量尾部加上后缀f,f = 3.14159f;
,如果没有后缀,常量3.14159是double类型,将double类型赋值给float类型,编译器认为有危险,可能会发出警告信息。
8.5.2 显式类型转换
有时候,我们想要强制将一种类型的值转换为另一种类型的值参与运算,此时就可以使用强制类型转换:
[强制类型转换表达式] (类型名)表达式
其中,类型名表示的是将表达式强制类型转换的目标类型。
比如,下面的例子使用强制类型转换将float类型转换为int型,得到浮点数的小数部分:f - (int)f
比如,C语言中整数除整数,结果还是整数,如果想在整数变量之间进行浮点数相除:(float)i1/i2
。
C语言把(类型名)视为一元运算符。一元运算符的优先级高于二元运算符,故先对i1进行强制类型转换运算,得到float类型的值,然后再与i2进行除法运算。除法运算时,i2会被隐式转换为float类型,最终结果是两个float类型相除的结果。即相当于((float)i1)/i2
。
注意,如果强制类型转换的表达式是变量,强制类型转换过后变量本身是不发生改变的,只是强转会依据变量的值得到目标类型的值。所以以上两个例子中,f
、i1
、i2
的值并没有改变。