说明符的顺序没有什么影响,所以unsigned short int 和short unsigned int是一样的。
标准要求int类型不能比short int类型短,long int类型不能比int类型段。但是short int 类型的取值范围有可能和int类型的范围是一样的,int类型的取值范围也可以和long int的一样。
注意:无论是哪一种类型,它们的取值范围都不是C标准强制的,会随着编译器的不同而不同。对于特定的实现,确定整数类型范围的一种方法是检查<limits.h>头。该头是标准库的一部分,其中定义了表示每种整数类型的最大值和最小值的宏。
八进制常量只包含0~7中的数字,而且必须要以0开头。
十六进制常量包含0~9中的数字和a~f中的字母,而且总是以0x开头。
注意:十六进制常量中的字母既可以是大写字母,也可以是小写字母。
为了强制编译器把常量当作长整数来处理,只需要在后边加上一个字母L(或l),为了指明是无符号常量,可以在常量后边加上字母U(或u),U和L可以结合使用(字母U、L的顺序和大小写无所谓)。
有符号整数运算中发生溢出时,程序的行为是未定义的。
无符号整数运算过程中发生溢出时,结果是有定义的:正确答案是对2n取模,其中n是用于存储结果的位数。例如,如果无符号的16位数65535加1,其结果可以保证为0。
假设有一个程序因为其中一个int变量发生溢出而无法工作。我们的第一反应是把变量的类型从int变为long int。但仅仅这样是不够的,我们还必须检查数据类型的改变对程序其它部分的影响,尤其是需要检查该变量是否用在printf函数或者scanf函数的调用中。如果用了,需要改变调用的格式串,因为%d只适用于int类型。
long double支持极高精度的要求,很少会用到。
默认情况下,浮点常量都以双精度的形式进行存储。
为了表明只需要单精度,可以在常量的末尾处加上字母F或f;而为了说明常量必须以long double格式存储,可以在常量的末尾处加上字母L或l。
转换说明符%e、%f和%g用于读写单精度浮点数。
C99允许printf函数调用中使用%le、%lf和%lg,不过字母l不起作用。
字符常量需要用单引号括起来,而不是双引号。
标准C允许使用单词signed和unsigned来修饰char类型:
unsigned char x;
signed char x;
可移植性技巧 不要假设char类型默认为signed或unsigned。如果有区别,用signed char或unsigned char代替char。
名称 | 转义序列 |
---|---|
警报(响铃)符 | \a |
回退符 | \b |
换页符 | \f |
换行符 | \n |
回车符 | \r |
水平制表符 | \t |
垂直制表符 | \v |
反斜杠 | \ |
问号 | ? |
单引号 | \’ |
双引号 | " |
toupper()函数在被调用时检测参数是否为小写字母,如果是,他会把参数转换成相应的大写字母;否则,该函数会返回参数的值。
调用toupper函数的程序要添加预处理指令包含相应的头文件<ctype.h>。
scanf函数不会跳过空白字符。为了强制scanf函数在读入字符前跳过空白字符,需要在格式串中的转换说明%c前面加上一个 空格。
注意:scanf格式串中的空白意味着“跳过零个或多个空白字符”。
注意:getchar含糊返回的是一个int类型的值而不是char类型的值。和scanf函数一样,getchar函数也不会在读取时跳过空白字符。
在执行程序时,使用getchar函数和putchar函数可以节约不少时间(胜于scanf和printf)。原因有两个:
惯用法:
while(getchar()!='\n')
···
while((ch = getchar())==' ')
···
隐式转换:
整值提升:它把字符或短整型整数转换成int类型(或者某些情况下是unsigned int类型)。
整值提升有下列两种情况:
注意:只要双目运算符左右的数据有一个的类型是某一个类型,那么另一个比其等级低的类型将会向上进行转换。也就是说,如果一个操作数的类型为long double,那么另一个操作数的类型转换成long double。
有一种特殊情况,只有在long int类型和unsigned int类型长度(比如36位)相同时才会发生。在这种情况下,如果一个操作数的类型是long int,而另一个的类型是unsigned int,那么两个操作数都会转换成unsigned long int类型。
注意:strlen()函数和sizeof()操作数的类型都是unsigned int类型。
常用算术转换不适用于赋值运算。C语言会遵循另一条简单的转换规则,那就是把赋值运算右边的表达式转换成左边变量的类型。如果变量的类型至少和表达式类型一样“宽”,那么这种转换都将没有任何障碍。当然,把某种类型的值赋给类型更狭小的变量,也将会得到无意义的结果。
下面是一个例子:
int a = 0;
unsigned x = 5;
int y = 5;
a = x + y;
//上面这个表达式将会发生两次类型转换,第一次,y将从有符号类型转换为有符号类型,第二次,x+y表达式的结果,将从无符号类型转换成有符号类型。
为了定义转换规则,C99中允许每个整数类型具有“整数转换等级”。下面按从最高级到最低级的顺序排列。
C99用整数提升取代了C89中的整值提升,可以将任何等级低于int和unsigned int的类型转换为itn(只要该类型的所有值都可以用int类型表示)或unsigned int。
C99中执行常用算术替换的规则可以划分为两种情况:
任一操作数的类型是浮点类型的情况。只要两个操作数的都不是复数型,规则与前面一样。
两个操作数的类型都不是浮点类型的情况。首先对两个数进行整数提升,如果这时两个操作数的类型相同,过程结束。否则,依次尝试下面的规则,一旦遇到可应用的规则就不再考虑其它的规则:
如果两个操作数都是有符号型或者都是无符号型,将整数转换等级较低的操作数转换为等级较高的操作数的类型。
如果无符号数的等级高于或等于有符号操作数的等级,将有符号操作数转换为无符号操作数的类型。
如果有符号操作数类型可以表示无符号操作数类型的所有值,将无符号操作数转换为有符号操作数的类型。
否则,将两个操作数都转换为与有符号操作数的类型相对应的无符号类型。
另外,==所有算术类型都可以转换为_Bool类型。==如果原始值为0则转换结果为0,否则结果为1。
(float)dividend / divisor
解释为
((float)dividend)/divisor
long i;
int j = 1000;
i = j*j;
当两个int类型值相乘时,结果也应该是int类型的,但是j*j的结果太大,以致在机器上无法表示成int型,从而导致溢出,此时就可以使用强制类型转换避免这种问题的发生:
i = (long)j*j;
类型定义可以设置一个新类型。
typedef int Bool;
==注意:所定义的类型的名字放在最后。(#define是把新的名字(我们使用的字符名)放在前面)==同时,我们常常将定义的类型名的首字母设置为大写。
#define Pint int*;
typedef int* Ptr_int;
Pint a,b;//被替换后是这样的 int *a,b;
Ptr_int c,d;
此处a是指针类型,b是整型类型,c和d都是整型指针数据类型。
类型定义能够使程序具有更好的可移植性。
在C99中,<stdint.h>头使用typedef定义占用特定位数的整数类型名,例如,int 32_t是恰好占用32位的有符号类型。这是一种有效的定义方式,能使程序更易于移植。
sizeof(表达式);
注意:
虽然在sizeof()括号中变量a进行了++操作,但是a仍然没有改变。
注意:在C89中,编译器本身通常就能确定sizeof表达式的值。但是编译器不能确定变长数组的大小,因为数组中的元素个数在程序执行期间是可变的。
答:只要有符号整数的值不是负值,就可以用%o和%x显示。这些转换导致print函数会把有符号整数看成是无符号的;换句话说,printf函数将假设符号位是数的绝对值部分。只要符号位为0,就没有问题。如果符号位为1,那么print函数将显示出一个超出预取的大数。
答:我们可以判定这个数是否是负数,然后自己显示一个负号:
if(i < 0)
printf("-%x",-i);
else
printf("%x",i);
答:这是一个十分难回答的问题。首先,注意,scanf函数和printf函数都是不同寻常的函数,因为它们都没有将函数的参数限制为固定数量。scanf函数和prinf函数有可变长度的参数列表。当调用带有可变长度参数列表的函数时,编译器会安排float参数自动转换成为double类型,其结果是printf函数无法区分float类型和double类型的参数。这解释了在printf函数调用中为何可以用%f既表示float类型又表示double类型的参数。
另一方面,scanf函数是通过指针指向变量的。%f告诉scanf函数在所传地址位置上存储一个float类型值,而%lf告诉scanf函数在该地址上存储一个double类型值。这里float和double的区别是非常重要的。如果给出了错误的转换说明,那么scanf函数将可能存储错误的字节数量(没有提到的是,float类型的位模式可能不同于double类型的位模式)。
答:转义序列?与三字符序列有关,因为三字符序列以??开头。如果需要在字符串中加入??,那么编译器很可能会把它当作三字符序列的开始。用?代替第二个?可以解决这个问题。
答:虽然scanf函数没有getchar速度快,但是它更加灵活。正如前面已经看到的,格式串"%c",可以使scanf函数读入下一个输入字符;" %c"可以读入下一个非空白字符。而且,scanf很擅长读取混入了其它数据类型的字符。
答:如果int型整数没有大到足以包含所有可能的原始类型值,整值提升会产生unsigned int类型。因为字符通常是8位的长度,几乎总会转化为int类型(可以保证int类型至少为16位长度)。有符号短整数也总可以转换为int类型,但无符号短整数却是有疑问的。如果短整数和普通整数的长度相同(例如在16位机上),那么无符号短整数必须转化为unsigned int类型,因为最大的无符号短整数(在16位机上为65535)要大于最大的int类型整数(32767)。
答:如果是整值类型并且变量是无符号类型,那么会丢掉超出的位数:如果变量是有符号类型,那么结果是由实现定义的。把符号数赋值给整型或浮点型变量的话,如果变量太小而无法承受,会产生未定义的行为:任何事都有可能发生,包括程序终止。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_57304511/article/details/124060741
内容来源于网络,如有侵权,请联系作者删除!