精华内容
下载资源
问答
  • c语言除法(c语言除法保留小数)
    万次阅读
    2021-05-18 15:30:03

    除法分为整除和精确除 例如a/b 当a,b同时为整数时,是整除,例3/5=0,5/3=1,14/5=2就是只要整数部分,而如果a,b两个有一个或者两个都是小数的话,就是精确除,和数学.

    除法 c=b/a b=b/a等价b/=a 余数 c=b%a,也就是b整除a 的余数为c b=b%a等价b%=a

    除法比如a除以b 表示为:a/b 但是结果是取商 a除以b取余 a%b 结果是取余数

    如何同时保留整数部分和小数部分?

    需要把参与运算的数据类型改为float或double 例:int a=5,b=3; float c=5/2;//在这种情况下,虽然c是float,但是除号只根据它的被除数和除数来输出结果,此时"/"当作".

    第二种得到0.50000 而且貌似只有除法运算有这个问题。。求助

    第一种:float m; m=1/2;1,为整数,2为整数, 1/2 = 0 ,整数除整数,按照C语言规定,只保留整数位 m = (float)0 = 0.000000 , 将整数0转化为浮点数0.000000 第二种 m,.

    5/2是取整舍余除法,即其结果为2 5.0/2.0才是保留小数点后面的除法。 那么.

    c=(float)a/b;强制类型转换就可以了

    问题是什么意思?在计算C语言算术表达式的结果时,特别是除法,需要注意计算过程中运算对象的数据类型转换。相同数据类型的数据、变量进行运算,结果保持原有数.

    除法:a/b 取整:floor(a)

    输入的时候写成小数,如5/2=2,而5.0/2=2.5或5/2.0=2.5.

    请问 4.0/16 等于 0.2 还是 0.25 ? 结果与被除数一致 是不是小数位数也要一致。

    #include void main() { printf("%f\n",4.0/16); } 如果是以上这样的话,结. 就变成0了.(在这里C语言没有四舍五入,一律舍!) 不知道是不是你想要的答案?.

    写出下列程序的输出结果 #include void main() { int x[4][4]={{1,2,3,4},{3,4,5,6},。

    这个程序的作用关键在这 *(*(x+i)+j)/=*(*(x+i)+i); 作用是:a[i][j]=a[i][j]/a[i][i] 然后就是要注意,这是两个int型数据相除,取整,例如,3/4=0; 还有,当执行过a[i].

    一个程序中5/9怎么为0

    1 C语言中的除用符号 / (正斜杠)表示2 用法 (1)当被除数和除数均为整型时,结果为整型 如1/2的结果是0,9/2的结果是4 (2)当被除数和除数任意一个为浮点数时,结果.

    C语言中,一般如果直接输入5/2会得到等于2,怎样编辑才能得到2.5这个确切。

    5/2是整型相除,结来果就是整型 如果你把除数或者被除数改为自浮点型的话 然后输出加以控制如:printf("%0.1f",x); 结果为2.5 得到的结果就会含有小数!zd#include<.>

    程序要求:用户不管输入几个数都可以正确的进行运算,需要有参数有返回值

    #include int main() { int iDivisor = 0;//除数 int iDividend = 0; //被除数 int iResult = 0; //结果 printf("输入被除数:"); scanf("%d", &iDividend); printf("输入除数.

    用C语言用“/”是算两个整数的除法,算小数间的除法而且结果也是小数的应.

    格式化输出结果就行了,简单示例如下:#include int main() { float i= 2.2, j=1.1; printf("%.2f\n",i/j); return 0; }输出结果是:2.00

    5/2是取整舍余除法,即其结果为2 5.0/2.0才是保留小数点后面的除法。 那么.

    int a,b那么a,b就是整型了,整型相除当然得出的也是整型了。你要float a,b;scanf("%f%f",&a,&b);

    #include int main() { double n,m; printf("请输入两个数:"); while(scanf("%lf%lf",&n,&m)!=EOF) { printf("%.lf + %.lf=%.lf\n",n,m,n+m); printf("%.lf - %.lf.

    不一样。 如1/2=0,而1÷2=0.5,1.0/2=1/2.0=1.0/2.0=0.5 对于除运算符(/),如果两个数均为整数则执行整数除,结果也是整数,值为商的整数部分,小数部分被截去;若.

    #include#includeint main(){ double d,z,k; printf("输入两个数字:\n",d,z); .

    int a,b;float c;scanf("%d%d",&a,&b);c=(float)a/b;printf("c=%f\n",c);你的程序在运算a/b时,由于a和b都是整型,计算机就按照整型来算,结果也是整数,然后赋值给整.

    更多相关内容
  • c语言数据类型运算的注意来源:华强电子网作者:华仔浏览:966时间:2016-08-10 14:18标签:摘要:在C语言程序的表达式或变量赋值运算中,有时会出现运算对象的数据不一致的情况。C语言允许任何标准数据类型之间的...

    c语言数据类型运算的注意

    来源:华强电子网

    作者:华仔

    浏览:966

    时间:2016-08-10 14:18

    标签:

    摘要:

    在C语言程序的表达式或变量赋值运算中,有时会出现运算对象的数据不一致的情况。C语言允许任何标准数据类型之间的隐式转换。所谓隐式转换是指系统会自动对相关数据类型进行转换,不需要强制干预。隐式转换按以下从左到右的优先级自动进行:bit-char-int-long-float       对于有符号和无符号型数据,无符号型数据的优先级大于有符号型数据:unsign

    在C语言程序的表达式或变量赋值运算中,有时会出现运算对象的数据不一致的情况。C语言允许任何标准数据类型之间的隐式转换。所谓隐式转换是指系统会自动对相关数据类型进行转换,不需要强制干预。隐式转换按以下从左到右的优先级自动进行:bit-char-int-long-float

    对于有符号和无符号型数据,无符号型数据的优先级大于有符号型数据:unsigned>signed

    隐式数据转换时,低优先级的数据类型转为高优先级的数据类型,不一定非要按照上面的顺序逐级转换,可以隔级转换,例如将bit型赋值给int型变量时,bit型数据直接转换为int型,而不是先将bit型转换为char型,然后再转换为int型,

    1.浮点类型的不能做“模”运算。 例如:float a=1234.56;    a=a%10;  这是错误的。只有整形才能做“模”int a=12345;  a=a%10;

    2.如果你想做普通的四则运算。那肯定是浮点数的运算。整形的除法不是我们平时的除法,它是舍去了余数,即小数部分。例如:int a=1;   a=a/10;   结果会得到0;因为只有商被保留下来。正确的是: float  a=1;   a=a/10;   得到结果是:0.1

    3.四则运算中常量之间做除法是特别注意:要加小数部分,不管它有没有小数部分;例如:float a; a=12/36; 这是错误的,只能得到0。正确的应该是:float  a;   a=12.0/36.0;   加上小数点就对了,得到结果 0.3   。不过,赋值运算符右边只要有一个变量或常量是浮点型就可以了。即:a=12.0/36;   也得到a=0.3;因为C语言能自动想高一级转换类型。但是注意:int 与浮点“常量”做运算并不能把他的范围扩大,除非计算式里有浮点“变量”例如:int a=5,llong int b;  b=a*3.0+65536;是错误的,第二次加法还是会超范围(int )。平时我们应该养成浮点数加小数点的习惯。同时注意:常量也分数据类型的。 “12”代表是非浮点型(整型int或字符型char)“12.0”则是浮点型(float)

    4. 对于不同类型的变量做计算时,要考虑计算的每一步的值否超过了变量类型的范围。注意:是每一步的计算结果,不单是最终结果。否则会出错,带来不必要的麻烦。 例如 unsigned int  a,b=7;   a=b+65536;得到的结果不会是65543,因为它已经超出了a的最大值 65536;  又如 a=b-65536;也不会得到负数.  a=b*65536;也超出范围。a=b/65536.0;也不会得到小数。对于多次计算更要特别注意,每一部分是否有可能超出范围,对超出范围的做相应处理。例如:unsinged int a,b=123;  a=b*5000.0/1000000.0;  这样得到的结果不会是你想要的,因为第一次乘法已经超出了范围,第二次做除法时要使用的上次结果已经是个错误的值了。

    可见:四则运算要注意三点:

    1。数据类型。

    2.。精度问题 。

    3。计算超范围问题。 特别是变量与常量的四则运算加倍注意是否超范围。

    技术资讯 技术方案 技术应用 技术新品 技术前沿 行业资讯 行业方案 行业应用 行业新品 行业前沿

    分享到:

    90da879458bf0f4491d5f6f37b03a631.png

    展开全文
  • 大整数除法C语言实现

    2018-12-10 17:59:05
    c语言实现的大整数除法, 新手小白程序设计入门参考。
  • 对计算机来说,除法与求模是整数算术运算中最复杂的运算。相对其他运算(如加法与减法)来说,这两种算法的执行速度非常慢。例如,ARM 硬件上不支持除法指令,编译器调用 C 库函数来实现除法运算。直接利用 C 库函数中...

    对计算机来说,除法与求模是整数算术运算中最复杂的运算。相对其他运算(如加法与减法)来说,这两种算法的执行速度非常慢。例如,ARM 硬件上不支持除法指令,编译器调用 C 库函数来实现除法运算。直接利用 C 库函数中的标准整数除法程序要花费 20~100 个周期,消耗较多资源。

    在非嵌入式领域,因为 CPU 运算速度快、存储器容量大,所以执行除法运算和求模运算消耗的这些资源对计算机来说不算什么。但是在嵌入式领域,消耗大量资源带来的影响不言而喻。因此,从理论上讲,我们应该在程序表达式中尽量减少对除法运算与求模运算的使用,尽量使用其他方法来代替除法与求模运算。例如,对于下面的示例代码:

    if (x/y>z) { // ... }

    我们可以将其修改成如下形式:

    if (((y>0)&&(x>y*z))||((y<0)&&(x

    这样就简单地避免了一些除法运算。同时,也可以在表达式中通过合并除法的方式来减少除法运算,下面通过示例来讲解。对于如下代码:

    double x=a/b/c; double y=a/b+c/b;

    根据数学结合原则,上面的代码可以通过合并的方式减少代码中的除法运算,修改后的代码如下:

    double x=a/(b*c); double y=(a+c)/b;

    同样,对于求模运算,也可以采用相应的方法来代替,如下面的示例代码:

    a=a%8;

    可以修改为:

    a=a&7;

    对于下面的表达式:

    x=(x+y)%z;

    可以通过如下方式来避免使用模操作符:

    x+=y; while(x>=z) { x-=z; }

    通过上面的阐述,相信大家对如何减少使用除法与模运算有了初步了解。下面将详细讨论如何优化除法运算与求模运算。

    用倒数相乘来实现除法运算

    何为倒数相乘?其实很简单,它的核心思想就是利用乘法来代替实现除法运算。例如,在 IA-32 处理器中,乘法指令的运算速度比除法指令要快 4~6 倍。因此,在某些情况下尽量使用乘法指令来代替除法指令。

    那么,我们该如何利用乘法来代替实现除法运算呢?原理就是被除数乘以除数的倒数,用公式表现为:

    x/y=x*(1/y)

    例如,计算 10/5,可以根据公式 x/y=x*(1/y) 这样来计算:

    10/5=10*(1/5)=10*0.2=2

    在实际应用中,一些编译器也正是基于这个原理才得以将除法运算转换为乘法运算的。现在我们来看一个除法运算示例:

    #include int main(void) { int x = 3/2; float y = 3.0/2.0; printf("3/2 = %drn3.0/2.0 = %1.1fn",x,y); return 0; }

    运算结果为:

    3/2 = 1

    3.0/2.0 = 1.5

    通过该除法运算示例可以看出,很明显没能充分考虑到浮点类型。另外,在 C 语言中,一般情况下 1 除以任何数其结果皆为 0。那么怎样才能解决这个问题呢?编译器采用了一种称为“定点运算”(fixed-point arithmetic)的方法。

    那么何为定点运算,定点运算有什么特点呢?

    前面已经阐述过,由于计算机表示实数时为了在固定位数内能表示尽量精确的实数值,分配给表示小数部分的位数并不是固定的,也就是说“小数点是浮动的”,因此计算机表示的实数数据类型也称为浮点数。

    相对于“小数点是浮动的”来讲,定点运算根据字面意思来理解就是“小数点是固定的”。有了定点运算,表示小数时不再用阶码(exponent component,即小数点在浮点数据类型中的位置),而是要保持小数点的位置固定不变。这和硬件浮点数机制截然不同,硬件浮点数机制是由硬件负责向整数部分和小数部分分配可用的位数。有了这种机制,浮点数就可以表示很大范围的数——从极小的数(在 0~1 的实数)到极大的数(在小数点前有数十个 0)。这种小数的定点表示法有很多优点,尤其能极大地提高效率。当然,作为代价,同样也必须承受随之而来的精度上的损失。

    对于定点数表示法(fixed-point),相信大家并不陌生。所谓定点格式,即约定机器中所有数据的小数点位置是固定不变的。在计算机中通常采用两种简单的约定:将小数点的位置固定在数据的最高位之前(即定点小数),或者固定在最低位之后(即定点整数)。

    其中,定点小数是纯小数,约定的小数点位置在符号位之后、有效数值部分的最高位之前。若数据 x 的形式为 x=x0x1x2…xn(其中 x0 为符号位,x1,…,xn 是数值的有效部分,也称为尾数,x1 为最高有效位),则在计算机中的表示形式为:

    6af04a3241176bafea871fbb5fd65fa1.png

    一般说来,如果最末位 xn=1,前面各位都为 0,则数的绝对值最小,即 |x|min=2-n;如果各位均为 1,则数的绝对值最大,即 |x|max=1-2-n。因此定点小数的表示范围是:

    d9c0f79324ef12c8641e4be979fd81e3.png

    定点整数是纯整数,约定的小数点位置在有效数值部分最低位之后。若数据 x 的形式为 x=x0x1x2…xn(其中 x0 为符号位,x1,…,xn 是尾数,xn 为最低有效位),则在计算机中的表示形式为:

    77610cb06e73949e4859e5add71c1301.png

    由此可知,定点整数的表示范围是:

    8567e6c5ab09e74b13399bdac08694c9.png

    当数据小于定点数能表示的最小值时,计算机将它作 0 处理,称为下溢;当数据大于定点数能表示的最大值时,计算机将无法表示,称为上溢,上溢和下溢统称为溢出。

    当计算机采用定点数表示时,对于既有整数又有小数的原始数据,需要设定一个比例因子,数据按该比例缩小成定点小数或扩大成定点整数再参加运算。在运算结果中,根据比例因子,将数据还原成实际数值。若比例因子选择不当,往往会使运算结果产生溢出或降低数据的有效精度。

    使用牛顿迭代法求除数的倒数

    在上一小节,我们阐述了如何使用倒数相乘(x/y=x*(1/y))的方法来实现除法运算。然而,对于如何能够快速有效地取倒数,牛顿迭代法(Newton’s method)是最佳方案。

    对于牛顿迭代法,相信学过高等数学的读者并不陌生,它又称为牛顿-拉夫逊方法(Newton-Raphson method),是牛顿在 17 世纪提出的一种在实数域和复数域上近似求解方程的方法,它将非线性方程线性化,从而得到迭代序列的一种方法。

    对于方程 f(x)=0,设 x0 为它的一个近似根,则函数 f(x) 在 x0 附近截断高次项可用一阶泰勒多项式展开为如下形式:

    f2c968e14ff6a40ec41cb69e15190d18.png

    这样,由式(1)我们可以将 f(x)=0 转化为如下形式:

    572520e5ad784d8c933f3320ae78b067.png

    在这里,我们设 f′(x)≠0,则有:

    a5c4f0316439cbbfaad37259757d3190.png

    取 x 作为原方程新的近似根 x1,再代入方程,如此反复,于是就产生了迭代公式:

    9eeac922e5a4af4465e437d932b6de73.png

    有了迭代公式(4)之后,现在我们继续来看如何用牛顿迭代公式来求倒数,即求除数 a 的倒数 1/a。

    这里我们设:

    c84ec14ca876aef2a4d4c3f8cf1c21f3.png

    式中 x 为 a 的倒数,方程 f(x)=0 为一非线性方程。现在把 f(x)=0 代入牛顿迭代序列式(4)中,就可以得出求倒数的公式,如下所示:

    95010aaa1f23dd02a95351fd580b4284.png

    在式(5)中,xn 为第 n 次迭代的近似根。

    如式(5)所示,用牛顿迭代法求倒数,每次迭代需要一次减法与两次乘法,所用的迭代次数决定最终的计算速度和精度。迭代次数越多,则精度越高。但迭代次数越多,速度也越慢,因此实际运用时应综合考虑速度和精度两方面的因素,选择合适的迭代次数。

    其实,牛顿迭代法在程序中应用得非常广泛,如最常用的开方、开方求倒数等。在 QuakeⅢ 源码中,在 game/code/q_math.c 文件中就有一个函数 Q_rsqrt,它的作用是将一个数开平方后取倒,其运行效率也非常高。其函数实现为:

    float Q_rsqrt(float number) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * (long * ) &y; i = 0x5f3759df - (i >> 1); y = * ( float * ) &i; // 第一次迭代 y = y * ( threehalfs - ( x2 * y * y )); // 第二迭代 // y = y * ( threehalfs - ( x2 * y * y ) ); return y; }

    从代码中可以看出,程序首先猜测出一个接近 1.0/sqrt(number) 的近似值,然后两次使用牛顿迭代法进行迭代(实际只需要使用一次)。这里需要特别注意的是 0x5f3759df 这个值,因为通过执行语句“0x5f3759df-(i>>1)”,得出的值出人意料地接近 1/sqrt(number) 的值,因此,我们只需要一次迭代就可以求得近似解,或许这就是数学的神奇。

    用减法运算来实现整数除法运算

    我们知道,减法运算比除法运算要快得多。因此,对整数除法运算来说,如果知道被除数是除数很小的倍数,那么可以使用减法运算来代替除法运算。例如,对于下面的示例代码:

    unsigned int x=300; unsigned int y=100; unsigned int z=x/y;

    我们可以将“z=x/y”表达式修改成如下形式:

    unsigned int x=300; unsigned int y=100; unsigned int z=0; while (x>=y) { x-=y; ++z; }

    这里使用减法来代替除法运算,虽然代码看起来不是很直观,但是在运行效率上确实要快许多。当然,具体效率也要取决于被除数与除数的倍数。如果倍数比较大,那么相应的循环次数就会增多,采取这种方法就得不偿失了。

    用移位运算实现乘除法运算

    用移位运算来实现乘除法运算的方法,相信大家并不陌生,实际上有很多 C 编译器都能够自动地做好这个优化。通常,如果需要乘以或除以 2n,都可以用移位的方法代替。例如:

    a=a*2; b=b/2;

    可以修改为如下形式:

    a=a<<1; b=b>>1;

    其中,除以 2 等价于右移 1 位,乘以 2 等价于左移 1 位。同理,除以 4 等价于右移 2 位,乘以 4 等价于左移 2 位;除以 8 等价于右移 3 位,乘以 8 等价于左移 3 位,以此类推。

    其实,利用上面的原理,只要是乘以或除以一个整数,均可以用移位运算的方法来得到结果,例如:

    a=a*5;

    可以将其分解为 a*(4+1),即 a*4+a*1。由此,我们就可以很简单地得到下面的程序表达式:

    a=(a<<2)+a

    尽量将浮点除法转化为相应的整数除法运算

    有时候,如果不能够在代码中避免除法运算,那么尽量使除数和被除数是无符号类型的整数。实际上,有符号的除法运算执行起来比无符号的除法运算更加慢,因为有符号的除法运算要先取得除数和被除数的绝对值,再调用无符号除法运算,最后再确定结果的符号。

    同时,对于浮点除法运算,可以先将浮点除法运算转化为相应的整数除法运算,最后对结果进行相应处理。例如,可以将浮点除法运算的分子和分母同时放大相同的倍数,就可以将浮点除法运算转换成相同功能的整数除法运算。

    展开全文
  • C语言基本数据类型有哪些?

    千次阅读 2022-03-15 20:49:28
    本节将详细介绍C语言的基本数据类型,包括如何声明变量、如何表示字面值常量(如,5或2.78),以及典型的用法。一些老式的C语言编译器无法支持这里提到的所有类型,请查阅你使用的编译器文档,了解可以使用哪些类型...

    本节将详细介绍C语言的基本数据类型,包括如何声明变量、如何表示字面值常量(如,5或2.78),以及典型的用法。一些老式的C语言编译器无法支持这里提到的所有类型,请查阅你使用的编译器文档,了解可以使用哪些类型。

    3.4.1 int类型

    C语言提供了许多整数类型,为什么一种类型不够用?因为C语言让程序员针对不同情况选择不同的类型。特别是,C语言中的整数类型可表示不同的取值范围和正负值。一般情况使用int类型即可,但是为满足特定任务和机器的要求,还可以选择其他类型。

    int类型是有符号整型,即int类型的值必须是整数,可以是正整数、负整数或零。其取值范围依计算机系统而异。一般而言,储存一个int要占用一个机器字长。因此,早期的16位IBM PC兼容机使用16位来储存一个int值,其取值范围(即int值的取值范围)是-32768~32767。目前的个人计算机一般是32位,因此用32位储存一个int值。现在,个人计算机产业正逐步向着64位处理器发展,自然能储存更大的整数。ISO C规定int的取值范围最小为-32768~32767。一般而言,系统用一个特殊位的值表示有符号整数的正负号。第15章将介绍常用的方法。

    1.声明int变量

    第2章中已经用int声明过基本整型变量。先写上int,然后写变量名,最后加上一个分号。要声明多个变量,可以单独声明每个变量,也可在int后面列出多个变量名,变量名之间用逗号分隔。下面都是有效的声明:

    int erns;
    int hogs, cows, goats;

    可以分别在4条声明中声明各变量,也可以在一条声明中声明4个变量。两种方法的效果相同,都为4个int大小的变量赋予名称并分配内存空间。

    以上声明创建了变量,但是并没有给它们提供值。变量如何获得值?前面介绍过在程序中获取值的两种途径。第1种途径是赋值:

    cows = 112;

    第2种途径是,通过函数(如,scanf())获得值。接下来,我们着重介绍第3种途径。

    2.初始化变量

    初始化(initialize)变量就是为变量赋一个初始值。在C语言中,初始化可以直接在声明中完成。只需在变量名后面加上赋值运算符(=)和待赋给变量的值即可。如下所示:

    int hogs = 21;
    int cows = 32, goats = 14;
    int dogs, cats = 94; /* 有效,但是这种格式很糟糕 */

    以上示例的最后一行,只初始化了cats,并未初始化dogs。这种写法很容易让人误认为dogs也被初始化为94,所以最好不要把初始化的变量和未初始化的变量放在同一条声明中。

    简而言之,声明为变量创建和标记存储空间,并为其指定初始值(如图3.4所示)。

    图3.4 定义并初始化变量

    3.int类型常量

    上面示例中出现的整数(21、32、14和94)都是整型常量或整型字面量。C语言把不含小数点和指数的数作为整数。因此,22和-44都是整型常量,但是22.0和2.2E1则不是。C语言把大多数整型常量视为int类型,但是非常大的整数除外。详见后面“long常量和long long常量”小节对long int类型的讨论。

    4.打印int值

    可以使用printf()函数打印int类型的值。第2章中介绍过,%d指明了在一行中打印整数的位置。%d称为转换说明,它指定了printf()应使用什么格式来显示一个值。格式化字符串中的每个%d都与待打印变量列表中相应的int值匹配。这个值可以是int类型的变量、int类型的常量或其他任何值为int类型的表达式。作为程序员,要确保转换说明的数量与待打印值的数量相同,编译器不会捕获这类型的错误。程序清单3.2演示了一个简单的程序,程序中初始化了一个变量,并打印该变量的值、一个常量值和一个简单表达式的值。另外,程序还演示了如果粗心犯错会导致什么结果。

    程序清单3.2 print1.c程序

    /* print1.c - 演示printf()的一些特性 */
    #include <stdio.h>
    int main(void)
    {
        int ten = 10;
        int two = 2;
    
        printf("Doing it right: ");
        printf("%d minus %d is %d\n", ten, 2, ten - two);
        printf("Doing it wrong: ");
        printf("%d minus %d is %d\n", ten);  // 遗漏2个参数
    
        return 0;
    }

    编译并运行该程序,输出如下:

    Doing it right: 10 minus 2 is 8
    Doing it wrong: 10 minus 16 is 1650287143

    在第一行输出中,第1个%d对应int类型变量ten;第2个%d对应int类型常量2;第3个%d对应int类型表达式ten - two的值。在第二行输出中,第1个%d对应ten的值,但是由于没有给后两个%d提供任何值,所以打印出的值是内存中的任意值(读者在运行该程序时显示的这两个数值会与输出示例中的数值不同,因为内存中储存的数据不同,而且编译器管理内存的位置也不同)。

    你可能会抱怨编译器为何不能捕获这种明显的错误,但实际上问题出在printf()不寻常的设计。大部分函数都需要指定数目的参数,编译器会检查参数的数目是否正确。但是,printf()函数的参数数目不定,可以有1个、2个、3个或更多,编译器也爱莫能助。记住,使用printf()函数时,要确保转换说明的数量与待打印值的数量相等。

    5.八进制和十六进制

    通常,C语言都假定整型常量是十进制数。然而,许多程序员很喜欢使用八进制和十六进制数。因为8和16都是2的幂,而10却不是。显然,八进制和十六进制记数系统在表达与计算机相关的值时很方便。例如,十进制数65536经常出现在16位机中,用十六进制表示正好是10000。另外,十六进制数的每一位的数恰好由4位二进制数表示。例如,十六进制数3的二进制数是0011,十六进制数5是的二进制数0101。因此,十六进制数35的位组合(bit pattern)是00110101,十六进制数53的位组合是01010011。这种对应关系使得十六进制和二进制的转换非常方便。但是,计算机如何知道10000是十进制、十六进制还是二进制?在C语言中,用特定的前缀表示使用哪种进制。0x或0X前缀表示十六进制值,所以十进制数16表示成十六进制是0x10或0X10。与此类似,0前缀表示八进制。例如,十进制数16表示成八进制是020。第15章将更全面地介绍进制相关的内容。

    要清楚,使用不同的进制数是为了方便,不会影响数被储存的方式。也就是说,无论把数字写成16、020或0x10,储存该数的方式都相同,因为计算机内部都以二进制进行编码。

    6.显示八进制和十六进制

    在C程序中,既可以使用也可以显示不同进制的数。不同的进制要使用不同的转换说明。以十进制显示数字,使用%d;以八进制显示数字,使用%o;以十六进制显示数字,使用%x。另外,要显示各进制数的前缀0、0x和0X,必须分别使用%#o、%#x、%#X。程序清单3.3演示了一个小程序(回忆一下,在某些集成开发环境(IDE)下编写的代码中插入getchar();语句,程序在执行完毕后不会立即关闭执行窗口)。

    程序清单3.3 bases.c程序

    /* bases.c--以十进制、八进制、十六进制打印十进制数100 */
    #include <stdio.h>
    int main(void)
    {
        int x = 100;
    
        printf("dec = %d; octal = %o; hex = %x\n", x, x, x);
        printf("dec = %d; octal = %#o; hex = %#x\n", x, x, x);
    
        return 0;
    }

    编译并运行该程序,输出如下:

    dec = 100; octal = 144; hex = 64
    dec = 100; octal = 0144; hex = 0x64

    该程序以3种不同记数系统显示同一个值。printf()函数做了相应的转换。注意,如果要在八进制和十六进制值前显示0和0x前缀,要分别在转换说明中加入#。

    3.4.2 其他整数类型

    初学C语言时,int类型应该能满足大多数程序的整数类型需求。尽管如此,还应了解一下整型的其他形式。当然,也可以略过本节跳至3.4.3节阅读char类型的相关内容,以后有需要时再阅读本节。

    C语言提供3个附属关键字修饰基本整数类型:short、long和unsigned。应记住以下几点。

    • short int类型(或者简写为short)占用的存储空间可能比int类型少,常用于较小数值的场合以节省空间。与int类似,short是有符号类型。
    • long int或long占用的存储空间可能比int多,适用于较大数值的场合。与int类似,long是有符号类型。
    • long long int或long long(C99标准加入)占用的储存空间可能比long多,适用于更大数值的场合。该类型至少占64位。与int类似,long long是有符号类型。
    • unsigned int或unsigned只用于非负值的场合。这种类型与有符号类型表示的范围不同。例如,16位unsigned int允许的取值范围是0~65535,而不是-32768~32767。用于表示正负号的位现在用于表示另一个二进制位,所以无符号整型可以表示更大的数。
    • 在C90标准中,添加了unsigned long int或unsigned long和unsigned short int或unsigned short类型。C99标准又添加了unsigned long long int或unsigned long long。
    • 在任何有符号类型前面添加关键字signed,可强调使用有符号类型的意图。例如,short、short int、signed short、signed short int都表示同一种类型。

    1.声明其他整数类型

    其他整数类型的声明方式与int类型相同,下面列出了一些例子。不是所有的C编译器都能识别最后3条声明,最后一个例子所有的类型是C99标准新增的。

    long int estine;
    long johns;
    short int erns;
    short ribs;
    unsigned int s_count;
    unsigned players;
    unsigned long headcount;
    unsigned short yesvotes;
    long long ago;

    2.使用多种整数类型的原因

    为什么说short类型“可能”比int类型占用的空间少,long类型“可能”比int类型占用的空间多?因为C语言只规定了short占用的存储空间不能多于int,long占用的存储空间不能少于int。这样规定是为了适应不同的机器。例如,过去的一台运行Windows 3.x的机器上,int类型和short类型都占16位,long类型占32位。后来,Windows和苹果系统都使用16位储存short类型,32位储存int类型和long类型(使用32位可以表示的整数数值超过20亿)。现在,计算机普遍使用64位处理器,为了储存64位的整数,才引入了long long类型。

    现在,个人计算机上最常见的设置是,long long占64位,long占32位,short占16位,int占16位或32位(依计算机的自然字长而定)。原则上,这4种类型代表4种不同的大小,但是在实际使用中,有些类型之间通常有重叠。

    C标准对基本数据类型只规定了允许的最小大小。对于16位机,short和int的最小取值范围是[−32767,32767];对于32位机,long的最小取值范围是[−2147483647,2147483647]。对于unsigned short和unsigned int,最小取值范围是[0,65535];对于unsigned long,最小取值范围是[0,4294967295]。long long类型是为了支持64位的需求,最小取值范围是[−9223372036854775807,9223372036854775807];unsigned long long的最小取值范围是[0,18446744073709551615]。如果要开支票,这个数是一千八百亿亿六千七百四十四万亿零七百三十七亿零九百五十五万一千六百一十五。但是,谁会去数?

    int类型那么多,应该如何选择?首先,考虑unsigned类型。这种类型的数常用于计数,因为计数不用负数。而且,unsigned类型可以表示更大的正数。

    如果一个数超出了int类型的取值范围,且在long类型的取值范围内时,使用long类型。然而,对于那些long占用的空间比int大的系统,使用long类型会减慢运算速度。因此,如非必要,请不要使用long类型。另外要注意一点:如果在long类型和int类型占用空间相同的机器上编写代码,当确实需要32位的整数时,应使用long类型而不是int类型,以便把程序移植到16位机后仍然可以正常工作。类似地,如果确实需要64位的整数,应使用long long类型。

    如果在int设置为32位的系统中要使用16位的值,应使用short类型以节省存储空间。通常,只有当程序使用相对于系统可用内存较大的整型数组时,才需要重点考虑节省空间的问题。使用short类型的另一个原因是,计算机中某些组件使用的硬件寄存器是16位。

    3.long常量和long long常量

    通常,程序代码中使用的数字(如,2345)都被储存为int类型。如果使用1000000这样的大数字,超出了int类型能表示的范围,编译器会将其视为long int类型(假设这种类型可以表示该数字)。如果数字超出long可表示的最大值,编译器则将其视为unsigned long类型。如果还不够大,编译器则将其视为long long或unsigned long long类型(前提是编译器能识别这些类型)。

    八进制和十六进制常量被视为int类型。如果值太大,编译器会尝试使用unsigned int。如果还不够大,编译器会依次使用long、unsigned long、long long和unsigned long long类型。

    有些情况下,需要编译器以long类型储存一个小数字。例如,编程时要显式使用IBM PC上的内存地址时。另外,一些C标准函数也要求使用long类型的值。要把一个较小的常量作为long类型对待,可以在值的末尾加上l(小写的L)或L后缀。使用L后缀更好,因为l看上去和数字1很像。因此,在int为16位、long为32位的系统中,会把7作为16位储存,把7L作为32位储存。l或L后缀也可用于八进制和十六进制整数,如020L和0x10L。

    类似地,在支持long long类型的系统中,也可以使用ll或LL后缀来表示long long类型的值,如3LL。另外,u或U后缀表示unsigned long long,如5ull、10LLU、6LLU或9Ull。

    整数溢出

    如果整数超出了相应类型的取值范围会怎样?下面分别将有符号类型和无符号类型的整数设置为比最大值略大,看看会发生什么(printf()函数使用%u说明显示unsigned int类型的值)。

    /* toobig.c-- 超出系统允许的最大int值*/ #include <stdio.h> int main(void) { int i = 2147483647; unsigned int j = 4294967295; printf("%d %d %d\n", i, i+1, i+2); printf("%u %u %u\n", j, j+1, j+2); return 0; }

    在我们的系统下输出的结果是:

    2147483647 -2147483648 -2147483647 4294967295 0 1

    可以把无符号整数j看作是汽车的里程表。当达到它能表示的最大值时,会重新从起始点开始。整数i也是类似的情况。它们主要的区别是,在超过最大值时,unsigned int类型的变量j从0开始;而int类型的变量i则从−2147483648开始。注意,当i超出(溢出)其相应类型所能表示的最大值时,系统并未通知用户。因此,在编程时必须自己注意这类问题。

    溢出行为是未定义的行为,C标准并未定义有符号类型的溢出规则。以上描述的溢出行为比较有代表性,但是也可能会出现其他情况。

    4.打印short、long、long long和unsigned类型

    打印unsigned int类型的值,使用%u转换说明;打印long类型的值,使用%ld转换说明。如果系统中int和long的大小相同,使用%d就行。但是,这样的程序被移植到其他系统(int和long类型的大小不同)中会无法正常工作。在x和o前面可以使用l前缀,%lx表示以十六进制格式打印long类型整数,%lo表示以八进制格式打印long类型整数。注意,虽然C允许使用大写或小写的常量后缀,但是在转换说明中只能用小写。

    C语言有多种printf()格式。对于short类型,可以使用h前缀。%hd表示以十进制显示short类型的整数,%ho表示以八进制显示short类型的整数。h和l前缀都可以和u一起使用,用于表示无符号类型。例如,%lu表示打印unsigned long类型的值。程序清单3.4演示了一些例子。对于支持long long类型的系统,%lld和%llu分别表示有符号和无符号类型。第4章将详细介绍转换说明。

    程序清单3.4 print2.c程序

    /* print2.c--更多printf()的特性 */
    #include <stdio.h>
    int main(void)
    {
        unsigned int un = 3000000000; /* int为32位和short为16位的系统 */
        short end = 200;
        long big = 65537;
        long long verybig = 12345678908642;
    
        printf("un = %u and not %d\n", un, un);
        printf("end = %hd and %d\n", end, end);
        printf("big = %ld and not %hd\n", big, big);
        printf("verybig= %lld and not %ld\n", verybig, verybig);
    
        return 0;
    }

    在特定的系统中输出如下(输出的结果可能不同):

    un = 3000000000 and not -1294967296
    end = 200 and 200
    big = 65537 and not 1
    verybig= 12345678908642 and not 1942899938

    该例表明,使用错误的转换说明会得到意想不到的结果。第1行输出,对于无符号变量un,使用%d会生成负值!其原因是,无符号值3000000000和有符号值−129496296在系统内存中的内部表示完全相同(详见第15章)。因此,如果告诉printf()该数是无符号数,它打印一个值;如果告诉它该数是有符号数,它将打印另一个值。在待打印的值大于有符号值的最大值时,会发生这种情况。对于较小的正数(如96),有符号和无符号类型的存储、显示都相同。

    第2行输出,对于short类型的变量end,在printf()中无论指定以short类型(%hd)还是int类型(%d)打印,打印出来的值都相同。这是因为在给函数传递参数时,C编译器把short类型的值自动转换成int类型的值。你可能会提出疑问:为什么要进行转换?h修饰符有什么用?第1个问题的答案是,int类型被认为是计算机处理整数类型时最高效的类型。因此,在short和int类型的大小不同的计算机中,用int类型的参数传递速度更快。第2个问题的答案是,使用h修饰符可以显示较大整数被截断成short类型值的情况。第 3 行输出就演示了这种情况。把 65537 以二进制格式写成一个 32 位数是
    00000000000000010000000000000001。使用%hd,printf()只会查看后16位,所以显示的值是1。与此类似,输出的最后一行先显示了verybig的完整值,然后由于使用了%ld,printf()只显示了储存在后32位的值。

    本章前面介绍过,程序员必须确保转换说明的数量和待打印值的数量相同。以上内容也提醒读者,程序员还必须根据待打印值的类型使用正确的转换说明。

    提示

    匹配printf()说明符的类型

    在使用printf()函数时,切记检查每个待打印值都有对应的转换说明,还要检查转换说明的类型是否与待打印值的类型相匹配。

    3.4.3 使用字符:char类型

    char类型用于储存字符(如,字母或标点符号),但是从技术层面看,char是整数类型。因为char类型实际上储存的是整数而不是字符。计算机使用数字编码来处理字符,即用特定的整数表示特定的字符。美国最常用的编码是ASCII编码,本书也使用此编码。例如,在ASCII码中,整数65代表大写字母A。因此,储存字母A实际上储存的是整数65(许多IBM的大型主机使用另一种编码——EBCDIC,其原理相同。另外,其他国家的计算机系统可能使用完全不同的编码)。

    标准ASCII码的范围是0~127,只需7位二进制数即可表示。通常,char类型被定义为8位的存储单元,因此容纳标准ASCII码绰绰有余。许多其他系统(如IMB PC和苹果Macs)还提供扩展ASCII码,也在8位的表示范围之内。一般而言,C语言会保证char类型足够大,以储存系统(实现C语言的系统)的基本字符集。

    许多字符集都超过了127,甚至多于255。例如,日本汉字(kanji)字符集。商用的统一码(Unicode)创建了一个能表示世界范围内多种字符集的系统,目前包含的字符已超过110000个。国际标准化组织(ISO)和国际电工技术委员会(IEC)为字符集开发了ISO/IEC 10646标准。统一码标准也与ISO/IEC 10646标准兼容。

    C语言把1字节定义为char类型占用的位(bit)数,因此无论是16位还是32位系统,都可以使用char类型。

    1.声明char类型变量

    char类型变量的声明方式与其他类型变量的声明方式相同。下面是一些例子:

    char response;
    char itable, latan;

    以上声明创建了3个char类型的变量:response、itable和latan。

    2.字符常量和初始化

    如果要把一个字符常量初始化为字母A,不必背下ASCII码,用计算机语言很容易做到。通过以下初始化把字母A赋给grade即可:

    char grade = 'A';

    在C语言中,用单引号括起来的单个字符被称为字符常量(character constant)。编译器一发现'A',就会将其转换成相应的代码值。单引号必不可少。下面还有一些其他的例子:

    char broiled;        /* 声明一个char类型的变量 */
    broiled = 'T';       /* 为其赋值,正确 */
    broiled = T;         /* 错误!此时T是一个变量 */
    broiled = "T";       /* 错误!此时"T"是一个字符串 */

    如上所示,如果省略单引号,编译器认为T是一个变量名;如果把T用双引号括起来,编译器则认为"T"是一个字符串。字符串的内容将在第4章中介绍。

    实际上,字符是以数值形式储存的,所以也可使用数字代码值来赋值:

    char grade = 65; /* 对于ASCII,这样做没问题,但这是一种不好的编程风格 */

    在本例中,虽然65是int类型,但是它在char类型能表示的范围内,所以将其赋值给grade没问题。由于65是字母A对应的ASCII码,因此本例是把A赋给grade。注意,能这样做的前提是系统使用ASCII码。其实,用'A'代替65才是较为妥当的做法,这样在任何系统中都不会出问题。因此,最好使用字符常量,而不是数字代码值。

    奇怪的是,C语言将字符常量视为int类型而非char类型。例如,在int为32位、char为8位的ASCII系统中,有下面的代码:

    char grade = 'B';

    本来'B'对应的数值66储存在32位的存储单元中,现在却可以储存在8位的存储单元中(grade)。利用字符常量的这种特性,可以定义一个字符常量'FATE',即把4个独立的8位ASCII码储存在一个32位存储单元中。如果把这样的字符常量赋给char类型变量grade,只有最后8位有效。因此,grade的值是'E'。

    3.非打印字符

    单引号只适用于字符、数字和标点符号,浏览ASCII表会发现,有些ASCII字符打印不出来。例如,一些代表行为的字符(如,退格、换行、终端响铃或蜂鸣)。C语言提供了3种方法表示这些字符。

    第1种方法前面介绍过——使用ASCII码。例如,蜂鸣字符的ASCII值是7,因此可以这样写:

    char beep = 7;

    第2种方法是,使用特殊的符号序列表示一些特殊的字符。这些符号序列叫作转义序列(escape sequence)。表3.2列出了转义序列及其含义。

    把转义序列赋给字符变量时,必须用单引号把转义序列括起来。例如,假设有下面一行代码:

    char nerf = '\n';

    稍后打印变量nerf的效果是,在打印机或屏幕上另起一行。

    表3.2 转义序列

    转义序列

    含义

    \a

    警报(ANSI C)

    \b

    退格

    \f

    换页

    \n

    换行

    \r

    回车

    \t

    水平制表符

    \v

    垂直制表符

    \\

    反斜杠(\)

    \'

    单引号

    \"

    双引号

    \?

    问号

    \0oo

    八进制值(oo必须是有效的八进制数,即每个o可表示0~7中的一个数)

    \xhh

    十六进制值(hh必须是有效的十六进制数,即每个h可表示0~f中的一个数)

    现在,我们来仔细分析一下转义序列。使用C90新增的警报字符(\a)是否能产生听到或看到的警报,取决于计算机的硬件,蜂鸣是最常见的警报(在一些系统中,警报字符不起作用)。C标准规定警报字符不得改变活跃位置。标准中的活跃位置(active position)指的是显示设备(屏幕、电传打字机、打印机等)中下一个字符将出现的位置。简而言之,平时常说的屏幕光标位置就是活跃位置。在程序中把警报字符输出在屏幕上的效果是,发出一声蜂鸣,但不会移动屏幕光标。

    接下来的转义字符\b、\f、\n、\r、\t和\v是常用的输出设备控制字符。了解它们最好的方式是查看它们对活跃位置的影响。换页符(\f)把活跃位置移至下一页的开始处;换行符(\n)把活跃位置移至下一行的开始处;回车符(\r)把活跃位置移动到当前行的开始处;水平制表符(\t)将活跃位置移至下一个水平制表点(通常是第1个、第9个、第17个、第25个等字符位置);垂直制表符(\v)把活跃位置移至下一个垂直制表点。

    这些转义序列字符不一定在所有的显示设备上都起作用。例如,换页符和垂直制表符在PC屏幕上会生成奇怪的符号,光标并不会移动。只有将其输出到打印机上时才会产生前面描述的效果。

    接下来的3个转义序列(\\、\'、\")用于打印\、'、"字符(由于这些字符用于定义字符常量,是printf()函数的一部分,若直接使用它们会造成混乱)。如果打印下面一行内容:

    Gramps sez, "a \ is a backslash."

    应这样编写代码:

    printf("Gramps sez, \"a \\ is a backslash.\"\n");

    表3.2中的最后两个转义序列(\0oo和\xhh)是ASCII码的特殊表示。如果要用八进制ASCII码表示一个字符,可以在编码值前面加一个反斜杠(\)并用单引号括起来。例如,如果编译器不识别警报字符(\a),可以使用ASCII码来代替:

    beep = '\007';

    可以省略前面的0,'\07'甚至'\7'都可以。即使没有前缀0,编译器在处理这种写法时,仍会解释为八进制。

    从C90开始,不仅可以用十进制、八进制形式表示字符常量,C语言还提供了第3种选择——用十六进制形式表示字符常量,即反斜杠后面跟一个x或X,再加上1~3位十六进制数字。例如,Ctrl+P字符的ASCII十六进制码是10(相当于十进制的16),可表示为'\x10'或'\x010'。图3.5列出了一些整数类型的不同进制形式。

    图3.5 int系列类型的常量写法示例

    使用ASCII码时,注意数字和数字字符的区别。例如,字符4对应的ASCII码是52。'4'表示字符4,而不是数值4。

    关于转义序列,读者可能有下面3个问题。

    • 上面最后一个例子(printf("Gramps sez, \"a \\ is a backslash.\"\n");),为何没有用单引号把转义序列括起来?无论是普通字符还是转义序列,只要是双引号括起来的字符集合,就无需用单引号括起来。双引号中的字符集合叫作字符串(详见第4章)。注意,该例中的其他字符(G、r、a、m、p、s等)都没有用单引号括起来。与此类似,printf("Hello!\007\n");将打印Hello!并发出一声蜂鸣,而printf("Hello!7\n");则打印Hello!7。不是转义序列中的数字将作为普通字符被打印出来。
    • 何时使用ASCII码?何时使用转义序列?如果要在转义序列(假设使用'\f')和ASCII码('\014')之间选择,请选择前者(即'\f')。这样的写法不仅更好记,而且可移植性更高。'\f'在不使用ASCII码的系统中,仍然有效。
    • 如果要使用ASCII码,为何要写成'\032'而不是032?首先,'\032'能更清晰地表达程序员使用字符编码的意图。其次,类似\032这样的转义序列可以嵌入C的字符串中,如printf("Hello!\007\n");中就嵌入了\007。

    4.打印字符

    printf()函数用%c指明待打印的字符。前面介绍过,一个字符变量实际上被储存为1字节的整数值。因此,如果用%d转换说明打印char类型变量的值,打印的是一个整数。而%c转换说明告诉printf()打印该整数值对应的字符。程序清单3.5演示了打印char类型变量的两种方式。

    程序清单3.5 charcode.c程序

    /* charcode.c-显示字符的代码编号 */
    #include <stdio.h>
    int main(void)
    {
        char ch;
    
        printf("Please enter a character.\n");
        scanf("%c", &ch);   /* 用户输入字符 */
        printf("The code for %c is %d.\n", ch, ch);
    
        return 0;
    }

    运行该程序后,输出示例如下:

    Please enter a character.
    C
    The code for C is 67.

    运行该程序时,在输入字母后不要忘记按下EnterReturn键。随后,scanf()函数会读取用户输入的字符,&符号表示把输入的字符赋给变量ch。接着,printf()函数打印ch的值两次,第1次打印一个字符(对应代码中的%c),第2次打印一个十进制整数值(对应代码中的%d)。注意,printf()函数中的转换说明决定了数据的显示方式,而不是数据的储存方式(见图3.6)。

    图3.6 数据显示和数据存储

    5.有符号还是无符号

    有些C编译器把char实现为有符号类型,这意味着char可表示的范围是-128~127。而有些C编译器把char实现为无符号类型,那么char可表示的范围是0~255。请查阅相应的编译器手册,确定正在使用的编译器如何实现char类型。或者,可以查阅limits.h头文件。下一章将详细介绍头文件的内容。

    根据C90标准,C语言允许在关键字char前面使用signed或unsigned。这样,无论编译器默认char是什么类型,signed char表示有符号类型,而unsigned char表示无符号类型。这在用char类型处理小整数时很有用。如果只用char处理字符,那么char前面无需使用任何修饰符。

    3.4.4 _Bool类型

    C99标准添加了_Bool类型,用于表示布尔值,即逻辑值true和false。因为C语言用值1表示true,值0表示false,所以_Bool类型实际上也是一种整数类型。但原则上它仅占用1位存储空间,因为对0和1而言,1位的存储空间足够了。

    程序通过布尔值可选择执行哪部分代码。我们将在第6章和第7章中详述相关内容。

    3.4.5 可移植类型:stdint.h和inttypes.h

    C语言提供了许多有用的整数类型。但是,某些类型名在不同系统中的功能不一样。C99新增了两个头文件stdint.h和inttypes.h,以确保C语言的类型在各系统中的功能相同。

    C语言为现有类型创建了更多类型名。这些新的类型名定义在stdint.h头文件中。例如,int32_t表示32位的有符号整数类型。在使用32位int的系统中,头文件会把int32_t作为int的别名。不同的系统也可以定义相同的类型名。例如,int为16位、long为32位的系统会把int32_t作为long的别名。然后,使用int32_t类型编写程序,并包含stdint.h头文件时,编译器会把int或long替换成与当前系统匹配的类型。

    上面讨论的类型别名是精确宽度整数类型(exact-width integer type)的示例。int32_t表示整数类型的宽度正好是32位。但是,计算机的底层系统可能不支持。因此,精确宽度整数类型是可选项。

    如果系统不支持精确宽度整数类型怎么办?C99和C11提供了第2类别名集合。一些类型名保证所表示的类型一定是至少有指定宽度的最小整数类型。这组类型集合被称为最小宽度类型(minimum width type)。例如,int_least8_t是可容纳8位有符号整数值的类型中宽度最小的类型的一个别名。如果某系统的最小整数类型是16位,可能不会定义int8_t类型。尽管如此,该系统仍可使用int_least8_t类型,但可能把该类型实现为16位的整数类型。

    当然,一些程序员更关心速度而非空间。为此,C99和C11定义了一组可使计算达到最快的类型集合。这组类型集合被称为最快最小宽度类型(fastst minimum width type)。例如,int_fast8_t被定义为系统中对8位有符号值而言运算最快的整数类型的别名。

    另外,有些程序员需要系统的最大整数类型。为此,C99定义了最大的有符号整数类型intmax_t,可储存任何有效的有符号整数值。类似地,uintmax_t表示最大的无符号整数类型。顺带一提,这些类型有可能比long long和unsigned long类型更大,因为C编译器除了实现标准规定的类型以外,还可利用C语言实现其他类型。例如,一些编译器在标准引入long long类型之前,已提前实现了该类型。

    C99和C11不仅提供可移植的类型名,还提供相应的输入和输出。例如,printf()打印特定类型时要求与相应的转换说明匹配。如果要打印int32_t类型的值,有些定义使用%d,而有些定义使用%ld,怎么办?C标准针对这一情况,提供了一些字符串宏(第4章中详细介绍)来显示可移植类型。例如,inttypes.h头文件中定义了PRId32字符串宏,代表打印32位有符号值的合适转换说明(如d或l)。程序清单3.6演示了一种可移植类型和相应转换说明的用法。

    程序清单3.6 altnames.c程序

    /* altnames.c -- 可移植整数类型名 */
    #include <stdio.h>
    #include <inttypes.h>  // 支持可移植类型
    int main(void)
    {
        int32_t me32;     // me32是一个32位有符号整型变量
    
        me32 = 45933945;
        printf("First, assume int32_t is int: ");
        printf("me32 = %d\n", me32);
        printf("Next, let's not make any assumptions.\n");
        printf("Instead, use a \"macro\" from inttypes.h: ");
        printf("me32 = %" "d" "\n", me32);
    
        return 0;
    }

    该程序最后一个printf()中,参数PRId32被定义在inttypes.h中的"d"替换,因而这条语句等价于:

    printf(“me32 = %d\n”, me32);

    在C语言中,可以把多个连续的字符串组合成一个字符串,所以这条语句又等价于:

    printf("me32 = %d\n", me32);

    下面是该程序的输出,注意,程序中使用了\"转义序列来显示双引号:

    First, assume int32_t is int: me32 = 45933945
    Next, let's not make any assumptions.
    Instead, use a "macro" from inttypes.h: me32 = 45933945

    篇幅有限,无法介绍扩展的所有整数类型。本节主要是为了让读者知道,在需要时可进行这种级别的类型控制。附录B中的参考资料VI“扩展的整数类型”介绍了完整的inttypes.h和stdint.h头文件。

    注意

    对C99/C11的支持

    C语言发展至今,虽然ISO已发布了C11标准,但是编译器供应商对C99的实现程度却各不相同。在本书第6版的编写过程中,一些编译器仍未实现inttypes.h头文件及其相关功能。

    3.4.6 float、double和long double

    各种整数类型对大多数软件开发项目而言够用了。然而,面向金融和数学的程序经常使用浮点数。C语言中的浮点类型有float、double和long double类型。它们与FORTRAN和Pascal中的real类型一致。前面提到过,浮点类型能表示包括小数在内更大范围的数。浮点数的表示类似于科学记数法(即用小数乘以10的幂来表示数字)。该记数系统常用于表示非常大或非常小的数。表3.3列出了一些示例。

    表3.3 记数法示例

    数字

    科学记数法

    指数记数法

    1000000000

    1.0×109

    1.0e9

    123000

    1.23×105

    1.23e5

    322.56

    3.2256×102

    3.2256e2

    0.000056

    5.6×10-5

    5.6e-5

    第1列是一般记数法;第2列是科学记数法;第3列是指数记数法(或称为e记数法),这是科学记数法在计算机中的写法,e后面的数字代表10的指数。图3.7演示了更多的浮点数写法。

    图3.7 更多浮点数写法示例

    C标准规定,float类型必须至少能表示6位有效数字,且取值范围至少是10-37~10+37。前一项规定指float类型必须能够表示33.333333的前6位数字,而不是精确到小数点后6位数字。后一项规定用于方便地表示诸如太阳质量(2.0e30千克)、一个质子的电荷量(1.6e-19库仑)或国家债务之类的数字。通常,系统储存一个浮点数要占用32位。其中8位用于表示指数的值和符号,剩下24位用于表示非指数部分(也叫作尾数或有效数)及其符号。

    C语言提供的另一种浮点类型是double(意为双精度)。double类型和float类型的最小取值范围相同,但至少必须能表示10位有效数字。一般情况下,double占用64位而不是32位。一些系统将多出的32位全部用来表示非指数部分,这不仅增加了有效数字的位数(即提高了精度),而且还减少了舍入误差。另一些系统把其中的一些位分配给指数部分,以容纳更大的指数,从而增加了可表示数的范围。无论哪种方法,double类型的值至少有13位有效数字,超过了标准的最低位数规定。

    C语言的第3种浮点类型是long double,以满足比double类型更高的精度要求。不过,C只保证long double类型至少与double类型的精度相同。

    1.声明浮点型变量

    浮点型变量的声明和初始化方式与整型变量相同,下面是一些例子:

    float noah, jonah;
    double trouble;
    float planck = 6.63e-34;
    long double gnp;

    2.浮点型常量

    在代码中,可以用多种形式书写浮点型常量。浮点型常量的基本形式是:有符号的数字(包括小数点),后面紧跟e或E,最后是一个有符号数表示10的指数。下面是两个有效的浮点型常量:

    -1.56E+12
    2.87e-3

    正号可以省略。可以没有小数点(如,2E5)或指数部分(如,19.28),但是不能同时省略两者。可以省略小数部分(如,3.E16)或整数部分(如,.45E-6),但是不能同时省略两者。下面是更多的有效浮点型常量示例:

    3.14159
    .2
    4e16
    .8E-5
    100.

    不要在浮点型常量中间加空格:1.56 E+12(错误!)

    默认情况下,编译器假定浮点型常量是double类型的精度。例如,假设some是float类型的变量,编写下面的语句:

    some = 4.0 * 2.0;

    通常,4.0和2.0被储存为64位的double类型,使用双精度进行乘法运算,然后将乘积截断成float类型的宽度。这样做虽然计算精度更高,但是会减慢程序的运行速度。

    在浮点数后面加上f或F后缀可覆盖默认设置,编译器会将浮点型常量看作float类型,如2.3f和9.11E9F。使用l或L后缀使得数字成为long double类型,如54.3l和4.32L。注意,建议使用L后缀,因为字母l和数字1很容易混淆。没有后缀的浮点型常量是double类型。

    C99标准添加了一种新的浮点型常量格式——用十六进制表示浮点型常量,即在十六进制数前加上十六进制前缀(0x或0X),用p和P分别代替e和E,用2的幂代替10的幂(即,p计数法)。如下所示:

    0xa.1fp10

    十六进制a等于十进制10,.1f是1/16加上15/256(十六进制f等于十进制15),p10是210或1024。0xa.1fp10表示的值是(10 + 1/16 + 15/256)×1024(即,十进制10364.0)。

    注意,并非所有的编译器都支持C99的这一特性。

    3.打印浮点值

    printf()函数使用%f转换说明打印十进制记数法的float和double类型浮点数,用%e打印指数记数法的浮点数。如果系统支持十六进制格式的浮点数,可用a和A分别代替e和E。打印long double类型要使用%Lf、%Le或%La转换说明。给那些未在函数原型中显式说明参数类型的函数(如,printf())传递参数时,C编译器会把float类型的值自动转换成double类型。程序清单3.7演示了这些特性。

    程序清单3.7 showf_pt.c程序

    /* showf_pt.c -- 以两种方式显示float类型的值 */
    #include <stdio.h>
    int main(void)
    {
        float aboat = 32000.0;
        double abet = 2.14e9;
        long double dip = 5.32e-5;
    
        printf("%f can be written %e\n", aboat, aboat);
        // 下一行要求编译器支持C99或其中的相关特性
        printf("And it's %a in hexadecimal, powers of 2 notation\n", aboat);
        printf("%f can be written %e\n", abet, abet);
        printf("%Lf can be written %Le\n", dip, dip);
    
        return 0;
    }

    该程序的输出如下,前提是编译器支持C99/C11:

    32000.000000 can be written 3.200000e+04
    And it's 0x1.f4p+14 in hexadecimal, powers of 2 notation
    2140000000.000000 can be written 2.140000e+09
    0.000053 can be written 5.320000e-05

    该程序示例演示了默认的输出效果。下一章将介绍如何通过设置字段宽度和小数位数来控制输出格式。

    4.浮点值的上溢和下溢

    假设系统的最大float类型值是3.4E38,编写如下代码:

    float toobig = 3.4E38 * 100.0f;
    printf("%e\n", toobig);

    会发生什么?这是一个上溢(overflow)的示例。当计算导致数字过大,超过当前类型能表达的范围时,就会发生上溢。这种行为在过去是未定义的,不过现在C语言规定,在这种情况下会给toobig赋一个表示无穷大的特定值,而且printf()显示该值为inf或infinity(或者具有无穷含义的其他内容)。

    当对一个很小的数做除法时,情况更为复杂。回忆一下,float类型的数以指数和尾数部分来储存。存在这样一个数,它的指数部分是最小值,即由全部可用位表示的最小尾数值。该数字是float类型能用全部精度表示的最小数字。现在把它除以2。通常,这个操作会减小指数部分,但是假设的情况中,指数已经是最小值了。所以计算机只好把尾数部分的位向右移,空出第1个二进制位,并丢弃最后一个二进制数。以十进制为例,把一个有4位有效数字的数(如,0.1234E-10)除以10,得到的结果是0.0123E-10。虽然得到了结果,但是在计算过程中却损失了原末尾有效位上的数字。这种情况叫作下溢(underflow)。C语言把损失了类型全精度的浮点值称为低于正常的(subnormal)浮点值。因此,把最小的正浮点数除以2将得到一个低于正常的值。如果除以一个非常大的值,会导致所有的位都为0。现在,C库已提供了用于检查计算是否会产生低于正常值的函数。

    还有另一个特殊的浮点值NaN(not a number的缩写)。例如,给asin()函数传递一个值,该函数将返回一个角度,该角度的正弦就是传入函数的值。但是正弦值不能大于1,因此,如果传入的参数大于1,该函数的行为是未定义的。在这种情况下,该函数将返回NaN值,printf()函数可将其显示为nan、NaN或其他类似的内容。

    浮点数舍入错误

    给定一个数,加上1,再减去原来给定的数,结果是多少?你一定认为是1。但是,下面的浮点运算给出了不同的答案:

    /* floaterr.c--演示舍入错误 */ #include <stdio.h> int main(void) { float a,b; b = 2.0e20 + 1.0; a = b - 2.0e20; printf("%f \n", a); return 0; }

    该程序的输出如下:

    0.000000 ←Linux系统下的老式gcc -13584010575872.000000 ←Turbo C 1.5 4008175468544.000000 ←XCode 4.5、Visual Studio 2012、当前版本的gcc

    得出这些奇怪答案的原因是,计算机缺少足够的小数位来完成正确的运算。2.0e20是2后面有20个0。如果把该数加1,那么发生变化的是第21位。要正确运算,程序至少要储存21位数字。而float类型的数字通常只能储存按指数比例缩小或放大的6或7位有效数字。在这种情况下,计算结果一定是错误的。另一方面,如果把2.0e20改成2.0e4,计算结果就没问题。因为2.0e4加1只需改变第5位上的数字,float类型的精度足够进行这样的计算。

    浮点数表示法

    上一个方框中列出了由于计算机使用的系统不同,一个程序有不同的输出。原因是,根据前面介绍的知识,实现浮点数表示法的方法有多种。为了尽可能地统一实现,电子和电气工程师协会(IEEE)为浮点数计算和表示法开发了一套标准。现在,许多硬件浮点单元都采用该标准。2011年,该标准被ISO/IEC/IEEE 60559:2011标准收录。该标准作为C99和C11的可选项,符合硬件要求的平台可开启。floaterr.c程序的第3个输出示例即是支持该浮点标准的系统显示的结果。支持C标准的编译器还包含捕获异常问题的工具。详见附录B.5,参考资料V。

    3.4.7 复数和虚数类型

    许多科学和工程计算都要用到复数和虚数。C99标准支持复数类型和虚数类型,但是有所保留。一些独立实现,如嵌入式处理器的实现,就不需要使用复数和虚数(VCR芯片就不需要复数)。一般而言,虚数类型都是可选项。C11标准把整个复数软件包都作为可选项。

    简而言之,C语言有3种复数类型:float _Complex、double _Complex和long double _Complex。例如,float _Complex类型的变量应包含两个float类型的值,分别表示复数的实部和虚部。类似地,C语言的3种虚数类型是float _Imaginary、double _Imaginary和long double _Imaginary。

    如果包含complex.h头文件,便可用complex代替_Complex,用imaginary代替_Imaginary,还可以用I代替-1的平方根。

    为何C标准不直接用complex作为关键字来代替_Complex,而要添加一个头文件(该头文件中把complex定义为_Complex)?因为标准委员会考虑到,如果使用新的关键字,会导致以该关键字作为标识符的现有代码全部失效。例如,之前的C99,许多程序员已经使用struct complex定义一个结构来表示复数或者心理学程序中的心理状况(关键字struct用于定义能储存多个值的结构,详见第14章)。让complex成为关键字会导致之前的这些代码出现语法错误。但是,使用struct _Complex的人很少,特别是标准使用首字母是下划线的标识符作为预留字以后。因此,标准委员会选定_Complex作为关键字,在不用考虑名称冲突的情况下可选择使用complex。

    3.4.8 其他类型

    现在已经介绍完C语言的所有基本数据类型。有些人认为这些类型实在太多了,但有些人觉得还不够用。注意,虽然C语言没有字符串类型,但也能很好地处理字符串。第4章将详细介绍相关内容。

    C语言还有一些从基本类型衍生的其他类型,包括数组、指针、结构和联合。尽管后面章节中会详细介绍这些类型,但是本章的程序示例中已经用到了指针〔指针(pointer)指向变量或其他数据对象位置〕。例如,在scanf()函数中用到的前缀&,便创建了一个指针,告诉scanf()把数据放在何处。

    小结:基本数据类型

    关键字:

    基本数据类型由11个关键字组成:int、long、short、unsigned、char、float、double、signed、_Bool、_Complex和_Imaginary。

    有符号整型:

    有符号整型可用于表示正整数和负整数。

    int ——系统给定的基本整数类型。C语言规定int类型不小于16位。short或short int ——最大的short类型整数小于或等于最大的int类型整数。C语言规定short类型至少占16位。long或long int ——该类型可表示的整数大于或等于最大的int类型整数。C语言规定long类型至少占32位。long long或long long int ——该类型可表示的整数大于或等于最大的long类型整数。long long类型至少占64位。

    一般而言,long类型占用的内存比short类型大,int类型的宽度要么和long类型相同,要么和short类型相同。例如,旧DOS系统的PC提供16位的short和int,以及32位的long;Windows 95系统提供16位的short以及32位的int和long。

    无符号整型:

    无符号整型只能用于表示零和正整数,因此无符号整型可表示的正整数比有符号整型的大。在整型类型前加上关键字unsigned表明该类型是无符号整型:unsigned int、unsigned long、unsigned short。单独的unsigned相当于unsigned int。

    字符类型:

    可打印出来的符号(如A、&和+)都是字符。根据定义,char类型表示一个字符要占用1字节内存。出于历史原因,1字节通常是8位,但是如果要表示基本字符集,也可以是16位或更大。

    char ——字符类型的关键字。有些编译器使用有符号的char,而有些则使用无符号的char。在需要时,可在char前面加上关键字signed或unsigned来指明具体使用哪一种类型。

    布尔类型:

    布尔值表示true和false。C语言用1表示true,0表示false。

    _Bool ——布尔类型的关键字。布尔类型是无符号int类型,所占用的空间只要能储存0或1即可。

    实浮点类型:

    实浮点类型可表示正浮点数和负浮点数。

    float ——系统的基本浮点类型,可精确表示至少6位有效数字。double ——储存浮点数的范围(可能)更大,能表示比float类型更多的有效数字(至少10位,通常会更多)和更大的指数。long double ——储存浮点数的范围(可能)比double更大,能表示比double更多的有效数字和更大的指数。

    复数和虚数浮点数:

    虚数类型是可选的类型。复数的实部和虚部类型都基于实浮点类型来构成:

    float _Complexdouble _Complexlong double _Complexfloat _Imaginarydouble _Imaginarylong double _Imaginary

    小结:如何声明简单变量

    1.选择需要的类型。

    2.使用有效的字符给变量起一个变量名。

    3.按以下格式进行声明:

    类型说明符 变量名;

    类型说明符由一个或多个关键字组成。下面是一些示例:

    int erest; unsigned short cash;

    4.可以同时声明相同类型的多个变量,用逗号分隔各变量名,如下所示:

    char ch, init, ans;

    5.在声明的同时还可以初始化变量:

    float mass = 6.0E24;

    3.4.9 类型大小

    如何知道当前系统的指定类型的大小是多少?运行程序清单3.8,会列出当前系统的各类型的大小。

    程序清单3.8 typesize.c程序

    /* typesize.c -- 打印类型大小 */
    #include <stdio.h>
    int main(void)
    {
        /* C99为类型大小提供%zd转换说明 */
        printf("Type int has a size of %zd bytes.\n", sizeof(int));
        printf("Type char has a size of %zd bytes.\n", sizeof(char));
        printf("Type long has a size of %zd bytes.\n", sizeof(long));
        printf("Type long long has a size of %zd bytes.\n",
                sizeof(long long));
        printf("Type double has a size of %zd bytes.\n",
                sizeof(double));
        printf("Type long double has a size of %zd bytes.\n",
                sizeof(long double));
        return 0;
    }

    sizeof是C语言的内置运算符,以字节为单位给出指定类型的大小。C99和C11提供%zd转换说明匹配sizeof的返回类型[2]。一些不支持C99和C11的编译器可用%u或%lu代替%zd。

    该程序的输出如下:

    Type int has a size of 4 bytes.
    Type char has a size of 1 bytes.
    Type long has a size of 8 bytes.
    Type long long has a size of 8 bytes.
    Type double has a size of 8 bytes.
    Type long double has a size of 16 bytes.

    该程序列出了6种类型的大小,你也可以把程序中的类型更换成感兴趣的其他类型。注意,因为C语言定义了char类型是1字节,所以char类型的大小一定是1字节。而在char类型为16位、double类型为64位的系统中,sizeof给出的double是4字节。在limits.h和float.h头文件中有类型限制的相关信息(下一章将详细介绍这两个头文件)。

    顺带一提,注意该程序最后几行printf()语句都被分为两行,只要不在引号内部或一个单词中间断行,就可以这样写。

    本文摘自《C Primer Plus(第6版)》中文版

    • 经久不衰的C语言畅销经典教程
    • 中文版累计销量近百万册
    • 针对C11标准进行全面更新

    本书详细讲解了C语言的基本概念和编程技巧。

    全书共17章。第1章、第2章介绍了C语言编程的预备知识。第3章~第15章详细讲解了C语言的相关知识,包括数据类型、格式化输入/输出、运算符、表达式、语句、循环、字符输入和输出、函数、数组和指针、字符和字符串函数、内存管理、文件输入输出、结构、位操作等。第16章、第17章介绍C预处理器、C库和高级数据表示。本书以完整的程序为例,讲解C语言的知识要点和注意事项。每章末尾设计了大量复习题和编程练习,帮助读者巩固所学知识和提高实际编程能力。附录给出了各章复习题的参考答案和丰富的参考资料。

    本书可作为C语言的教材,适用于需要系统学习C语言的初学者,也适用于巩固C语言知识或希望进一步提高编程技术的程序员。

    展开全文
  • 1.双目运算符: 加法运算: 减法运算: 乘法运算/ : 除法运算% : 求余运算(又叫模运算)重点说一下后两个运算符:除法运算符左右两边的数据类型决定了运算结果的类型。两边都是整数结果为整数,有任一方是小数,...
  • 一、常见的数据类型包括基本类型、枚举类型、空类型和派生类型。 基本类型又包括整型类型、浮点类型 整型类型 : {基本类型(int)、短整型(short int)、长整型(long int)、*双长整型(long long int)、字符型...
  • C语言:超详细的C语言中的数据类型

    千次阅读 多人点赞 2020-12-24 23:00:55
    数据类型:是程序设计语言预先做好的工具,每种类型处理一类数据(比如有处理整型数的工具,处理实型数的数据)。 如果要处理数据类型,一定要注意两个方面的东西: (1)数据的取值范围:这一个类型的数据,在...
  • C语言的基本数据类型

    千次阅读 2019-03-07 16:57:42
    目录 一、整型 二进制数、八进制数和十六进制数 ...int (整型)是基本的整数类型,short (短整型)和 long (长整型)是在 int 的基础上进行的扩展,short 可以节省内存,long 可以容纳更大的值...
  • 1.数据类型介绍 类型的意义 决定了这个类型开辟内存空间的大小 如何看待内存空间的视角 整形数据类型 字符型: char类型可以和int型进行转换 char虽然是字符类型,但字符类型存储的是ASCII码值,ASCII码是整数 ...
  •   如果在使用除法 “ / ” 时,包含了浮点型数据,那结果就不再是整数数据了,而是包含小数的商,下面我们可以看程序验证部分。 2、程序验证 1)C程序 #include <stdio.h> int main() { int i = 5; float...
  • 原文链接: http://wenda.tianya.cn/question/4e096f010317a93d除法运算符" / ",如果是两个整数相除结果为整数如果需要保留小数时 必须将其中一个除数转换为浮点数#include #include main(){float x;float y;printf...
  • c语言数据类型与进制转换一、 关键字1.1、c语言的关键字共有32个1.2、数据类型1.2.1、数据类型的定义二、进制三、原码、反码和补码 一、 关键字 1.1、c语言的关键字共有32个 1.数据类型的关键字(12个) char、short、...
  • C语言数据类型的定义

    千次阅读 2020-05-25 08:04:32
    数据类型的定义 1、数据类型的定义 变量的定义: 数据类型 变量名【标识符】 变量的赋值: 变量名 = 值; 数据类型 变量名【标识符】 = 值 标示符的命名规则: 1、字母、数字、下划线 2、不能以数字开头 3、见名知义...
  • C语言数据类型浮点型

    千次阅读 2019-03-06 22:05:20
    C语言数据类型浮点型 ** 写博文打卡第二波。今天记下C语言的浮点数据类型。 浮点数据类型:单精度(float)和双精度(double)。两者的原理是一样的。 1. 第一步:如何求解原码、反码、补码 我们以8位计算。 正数的原反...
  • C语言浮点数据
  • 原来的计算器如果输990/1.1就会出现899.999999999999986这串数字,而正确答案应是900整,这个问题应该...我一看到这个问题就想到了最近数学课上一直在叨唠的分数除法中的倒数(虽然我早学过了,但是学校刚教到这儿),...
  • 数据类型转换就是将数据(变量、表达式的结果)从一种类型转换到另一种类型。例如,为了保存小数你可以将int类型的变量转换为double类型。数据类型转换的一般格式为:(type_name) expressiontype_name为要转换到的数据...
  • c语言数据类型、运算符和表达式

    千次阅读 2021-05-22 01:33:46
    数据类型1.基本数据类型:基本数据类型最主要的特点是,其值不可以分解为其他类型。也就是说,基本数据类型是自我说明的2....在c语言中构造类型有以下几种:·数据类型·结构体类型·共同体(联合)类型3.指针类型:指...
  • C语言整数除法中怎么加上四舍五入

    千次阅读 2019-01-21 12:15:07
    要解决问题这有一个方法一步到位,且不用改变数据类型: 利用各位在5到9范围进位,只要乘上10进行计算后,加上5直接对四舍五入手动判断进位,再10捎去无用的个位,就行了 b = ((1000 * (c - x)) / x)+5; b=b/10;//...
  • 让你彻底明白c语言的浮点型及整型除法问题

    千次阅读 多人点赞 2021-05-12 15:03:54
    在C中,如果两个整型(int)变量做除法,如果出现了小数,那么,C只会取整数部分。 比如0.75,整数部分为0,小数部分为75,那么最终的结果应为0; 再比如1.25,最终结果应为1。 那么该如何解决这个问题? 第一种方法...
  • C语言学习(2)

    2021-05-21 18:26:01
    C语言代码编写规范第一个:注意缩进用tab键缩进对齐第二个:适当的空行第三个:注释,简明扼要C语言注释只有两种写法:第一种:单行注释 //注释文字第二种:块注释 /* 注释的内容 */,块注释不能嵌套尤其是重要的...
  • 整数除法的规范明确规定:该部门将结果舍入为零 当两个操作数具有相同符号时,结果为零或正,当两个操作数具有相反符号时,结果为零或负 如果左操作数是最小的可表示的int而右操作数是-1,则发生溢出。[...]它是实现...
  • 【【CC果冻633】C语言入门教程(一)程序中的一些定义】https://toutiao.com/group/6757091046095585803/?app=explore_article&timestamp=1573306878&req_id=2019110921411801001404813236EFF1BF&group_id...
  • C语言实现有理数数据类型(有理数库)系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结学习目标:学习内容:学习时间:学习产出:项目场景:问题描述:原因分析:解决方案: 前言 提示:...
  • C语言Double类型数据保证精度问题我用手算算出的数据为-1.35323517,但是在C语言里面为了保证数据精度,VC++运行的结果为-1.35323517024517,按说应该在-1.35323517后面补零,但是补的却是024517,补上这几位会严重...
  • C语言数据类型转换详解

    千次阅读 多人点赞 2020-02-20 10:46:56
    数据类型转换就是将数据(变量、数值、表达式的结果等)从一种类型转换为另一种类型。 自动类型转换 自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。 1 ....
  • 一、C语言的所有数据类型 二、常量与变量 三、标识符和关键字 四、整型数在计算机中的存储方式 五、有符号的数据类型和无符号的数据类型 六、运算符和表达式 一、C语言的所有数据类型 二、常量与变量 ...
  • C语言数据类型转换

    千次阅读 2021-05-22 08:27:12
    数据类型转换就是将数据(变量、表达式的结果)从一种类型转换到另一种类型。例如,为了保存小数你可以将int类型的变量转换为double类型。数据类型转换的一般格式为:(type_name) expressiontype_name为要转换到的数据...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,426
精华内容 14,970
关键字:

c语言除法的数据类型