最全《C语言程序设计现代方法》----第七章 基本类型(1),2024年最新跟C C++初学者分享几点经验

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

7.1.4 整数溢出

有符号整数运算中发生溢出时,程序的行为是未定义的。

无符号整数运算过程中发生溢出时,结果是有定义的:正确答案是对2n取模,其中n是用于存储结果的位数。例如,如果无符号的16位数65535加1,其结果可以保证为0。

7.1.5 读/写整数

假设有一个程序因为其中一个int变量发生溢出而无法工作。我们的第一反应是把变量的类型从int变为long int。但仅仅这样是不够的,我们还必须检查数据类型的改变对程序其它部分的影响,尤其是需要检查该变量是否用在printf函数或者scanf函数的调用中。如果用了,需要改变调用的格式串,因为%d只适用于int类型。

  • 读/写无符号整数时,使用字母u、o或x代替转换说明中的d。如果使用u说明符,该数将以十进制形式读写,o表示八进制形式,而x表示十六进制形式。
  • 读写短整数时,在d、o、u或x前面加上字符h。
  • 读写长整数时,在d、o、u或x前面加上字符l。
  • (C99)读写长长整数时,在d、o、u或x前面加上字母ll。

7.2 浮点类型

long double支持极高精度的要求,很少会用到。

7.2.1 浮点常量

默认情况下,浮点常量都以双精度的形式进行存储。

为了表明只需要单精度,可以在常量的末尾处加上字母F或f;而为了说明常量必须以long double格式存储,可以在常量的末尾处加上字母L或l。

7.2.2 读/写浮点数

转换说明符%e、%f和%g用于读写单精度浮点数。

C99允许printf函数调用中使用%le、%lf和%lg,不过字母l不起作用。

7.3 字符类型

字符常量需要用单引号括起来,而不是双引号。

7.3.2 有符号字符和无符号字符

标准C允许使用单词signed和unsigned来修饰char类型:

unsigned char x;
signed char x;

可移植性技巧 不要假设char类型默认为signed或unsigned。如果有区别,用signed char或unsigned char代替char。

7.3.4 转移序列
名称转义序列
警报(响铃)符\a
回退符\b
换页符\f
换行符\n
回车符\r
水平制表符\t
垂直制表符\v
反斜杠\
问号?
单引号\’
双引号"
  • 八进制转义序列由字符\和跟随其后的一个最多含有三位数字的八进制数组成。(此数必须表示为无符号字符,所以最大值通常是八进制的377。)例如,可以将转义字符写成\33或\033。跟八进制常量不同,转义序列中的八进制数不一定要用0开头。
  • 十六进制转义序列由\x和跟随其后的一个十六进制数组成。虽然标准C对于十六进制数的位数没有限制,但必须表示成无符号字符(因此,如果字符长度是8位,那么16进制数的值不能超过FF)。若采用这种表示法,可以把转义字符写成\x1b或\x1B的形式。字符x必须小写,但是十六进制的数字(例如b)不限大小写。x不可省略。
7.3.5 字符处理函数

toupper()函数在被调用时检测参数是否为小写字母,如果是,他会把参数转换成相应的大写字母;否则,该函数会返回参数的值。

调用toupper函数的程序要添加预处理指令包含相应的头文件<ctype.h>。

7.3.6 用scanf和printf读/写字符

scanf函数不会跳过空白字符。为了强制scanf函数在读入字符前跳过空白字符,需要在格式串中的转换说明%c前面加上一个 空格。

注意:scanf格式串中的空白意味着“跳过零个或多个空白字符”。

7.3.7 用getchar和putchar读/写字符

注意:getchar含糊返回的是一个int类型的值而不是char类型的值。和scanf函数一样,getchar函数也不会在读取时跳过空白字符。

在执行程序时,使用getchar函数和putchar函数可以节约不少时间(胜于scanf和printf)。原因有两个:

  1. 这两个函数比scanf函数和printf函数简单的多,因为scanf函数和printf函数时设计用来按照不同的格式读/写多种不同类型的数据的。
  2. 为了额外的速度提升,通常getchar函数和putchar函数是作为宏来实现的。

惯用法:

while(getchar()!='\n')
···
while((ch = getchar())==' ')
···

7.4 类型转换

隐式转换:

  • 当算术表达式或者逻辑表达式中操作数的类型不相同时。(C语言执行所谓的常用算术转换
  • 当赋值运算符右侧表达式的类型和左侧变量的类型不匹配时。
  • 当函数的调用中的实参类型与其对应的形参类型不匹配时。
  • 当return语句中表达式的类型和函数返回值的类型不匹配时。
7.4.1 常用算术转换

整值提升:它把字符或短整型整数转换成int类型(或者某些情况下是unsigned int类型)。

整值提升有下列两种情况:

  • 任一操作数的类型是浮点类型的情况。按照下图将类型较狭小的操作数进行提升:

image-20220303161659570

注意:只要双目运算符左右的数据有一个的类型是某一个类型,那么另一个比其等级低的类型将会向上进行转换。也就是说,如果一个操作数的类型为long double,那么另一个操作数的类型转换成long double。

  • 两个操作数的类型都不是浮点类型的情况。首先对其两个操作数进行整值提升(保证没有一个操作数的是字符类型或短整型)。然后按照下图对类型较狭小的操作数进行提升:

image-20220303162706100

有一种特殊情况,只有在long int类型和unsigned int类型长度(比如36位)相同时才会发生。在这种情况下,如果一个操作数的类型是long int,而另一个的类型是unsigned int,那么两个操作数都会转换成unsigned long int类型。

注意:strlen()函数和sizeof()操作数的类型都是unsigned int类型。

7.4.2 赋值过程中的转换

常用算术转换不适用于赋值运算。C语言会遵循另一条简单的转换规则,那就是把赋值运算右边的表达式转换成左边变量的类型。如果变量的类型至少和表达式类型一样“宽”,那么这种转换都将没有任何障碍。当然,把某种类型的值赋给类型更狭小的变量,也将会得到无意义的结果。

下面是一个例子:

int a = 0;
unsigned x = 5;
int y = 5;
a = x + y;
//上面这个表达式将会发生两次类型转换,第一次,y将从有符号类型转换为有符号类型,第二次,x+y表达式的结果,将从无符号类型转换成有符号类型。

7.4.3 C99中的隐式转换

为了定义转换规则,C99中允许每个整数类型具有“整数转换等级”。下面按从最高级到最低级的顺序排列。

  1. long long int、unsigned long long int
  2. long int、unsigned long int
  3. int、unsigned int
  4. short int、unsigned short int
  5. char、signed char、unsigned char
  6. _Bool

C99用整数提升取代了C89中的整值提升,可以将任何等级低于int和unsigned int的类型转换为itn(只要该类型的所有值都可以用int类型表示)或unsigned int。

C99中执行常用算术替换的规则可以划分为两种情况:

  • 任一操作数的类型是浮点类型的情况。只要两个操作数的都不是复数型,规则与前面一样。
  • 两个操作数的类型都不是浮点类型的情况。首先对两个数进行整数提升,如果这时两个操作数的类型相同,过程结束。否则,依次尝试下面的规则,一旦遇到可应用的规则就不再考虑其它的规则:
    • 如果两个操作数都是有符号型或者都是无符号型,将整数转换等级较低的操作数转换为等级较高的操作数的类型。
    • 如果无符号数的等级高于或等于有符号操作数的等级,将有符号操作数转换为无符号操作数的类型。
    • 如果有符号操作数类型可以表示无符号操作数类型的所有值,将无符号操作数转换为有符号操作数的类型。
    • 否则,将两个操作数都转换为与有符号操作数的类型相对应的无符号类型。

另外,==所有算术类型都可以转换为_Bool类型。==如果原始值为0则转换结果为0,否则结果为1。

7.4.4 强制类型转换
  1. C语言把(类型名)视为一元运算符。一元运算符的优先级高于二元运算符。所以编译器会把表达式
(float)dividend / divisor

解释为

((float)dividend)/divisor

  1. 有时候,需要使用强制类型转换来避免溢出。
long i;
int j = 1000;
i = j*j;

当两个int类型值相乘时,结果也应该是int类型的,但是j*j的结果太大,以致在机器上无法表示成int型,从而导致溢出,此时就可以使用强制类型转换避免这种问题的发生:

i = (long)j*j;

7.5 类型定义

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

0004145)]
[外链图片转存中…(img-UjeAFDyj-1715820004145)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值