龙空技术网

C|类型混合运算、赋值、函数传参和返回的转换及副作用

小智雅汇 478

前言:

目前同学们对“c语言unsigned什么意思”大概比较关怀,看官们都想要分析一些“c语言unsigned什么意思”的相关文章。那么小编也在网摘上汇集了一些有关“c语言unsigned什么意思””的相关知识,希望大家能喜欢,你们一起来学习一下吧!

计算机有其强大的地方,但也有其本身的限制。

总是用有限个内存字节来表示数量,自然总会溢出的可能。

对于二进制小数,其精度总是局限于k*1/(2^n)(k,n都是整数),如0.5、0.25、0.125、0.0625……的整数倍及其加减。

不同类型数据的存储长度和存储方式不同,一般不能直接混合运算,需要进行类型的转换。例如:

100+0.5

100是整型,0.5是实型,二者存储形式完全不同,需要统一为一种类型 (double)才能相加。

为了提高编程效率,增加应用的灵活性,C语言允许不同数据类型相互转换。

C语言的类型转换分为自动类型转换和强制类型转换。

1 自动类型转换

1.1 一般自动转换(系统自动转换)

signed和unsigned类型混合运算时,signed转换为unsigned;

char和short运算时转换为int,float运算时转换为double;

低级别类型和高级别类型混合运算时,低级别类型转换为高级别类型

假设变量c、i、f、d的类型分别是char、int、float、double,则:

c+i // c自动转换为int,结果为intc+i+f // c自动转换为int,和i运算后,结果为int,转换为double, // f自动转换为double,运算最后结果为floatc+i+f+d // c自动转换为int,和i运算后,结果为int,转换为double, // f自动转换为double,运算结果转为double,和d运算,最后为double

可以通过sizeof(表达式)来推断类型:

#include "stdio.h"int main() { char c='A'; int i=1; float f=3.0; double d=4.0; printf("%d\n",sizeof(c)); // 1 printf("%d\n",sizeof(c+i)); // 4 printf("%d\n",sizeof(c+i+f)); // 4 printf("%d\n",sizeof(c+i+f+d)); // 8 return 0;}

1.2 赋值类型转换

int a;a=3.1415926 + 100;

1.3 函数传参和返回值类型转换

int sum(int x, int y){    double z=4.5;     z=z+x+y;     return z;}int s = 0;s += sum(2.3,3.4); // 参数传入和函数返回都有自动类型转换,类似于赋值的自动类型转换2 强制类型转换

系统无法自动进行的类型转换需要程序员采用强制类型转换的方法来处理,强制类型转换又称显式转换。

(类型名) (表达式)

例如:

(int) (2+2.56789) // 浮点类型转换为int型,结果为4,小数部分截去

四舍五入需要稍微构造一下:

(int)(3.1415926*1000+0.5)/1000.0

3.1415926*1000+0.5等于3142.0926,转换为int值3142,再除以1000.0得到3.142。3.142是对3.1415926第4位小数的四舍五入后的结果。

3 指针类型的强制转换

指针类型依赖于所指向的数据的类型,使用强制类型转换可以改变指针的类型,例如:

char a[]="ABCD"; long *p;p=(long *)a; // a是char *类型指针,强制转换为long *类型指针printf("%X\n",*p); // 44434241,*p取出4个字节的数据,如果是*a只能取1个字节的数据

将a转换为long *型后赋值给p,输出p指向的数据,得到4个字节的数据,44对应’D’,43对应’C’, 42对应’B’,41对应’A’,从而一次性得到数组a中4个元素的实际存储形式。

float x=0.5;printf("%lX",*((long *)(&x)));

指针类型转换相当对于内存中的二进制位强制按某种类型进行解析。

int val = 0x087654321; char firstByte = *(char*)&val; printf("%x",firstByte); //21char* ch = (char*)(&val);printf("%x\n",*ch); //214 数据类型转换的副作用

类型转换的副作用包括:类型级别的提升与降低、符号位扩展、符号位零扩展、误差与溢出等。

在程序设计中要合理设定数据类型,避免数值的变化和精度的丢失。

4.1 数据类型级别的提升与降低

产生类型提升效果的有:

短数据转换成长数据;

整数转换成实数;

signed型转换成unsigned型;

与此相反的转换将产生类型级别降低的效果。

4.2 零扩展与符号位扩展

int a='A';short b=-1;int c=b;

4.3 截断和精度丢失

高级别的类型转换为低级别的类型时难免出现问题。

较长的整型转换为较短的整型或字符型时将去除高位字节,例如:

int a=65,b=321;char c1=a; // 能保持准确度,c1等于'A',相当于65char c2=b; // 不能保持准确度,c2将等于65

实数转换成整数时,由于截去小数将丢失精度,例如:

int a=3.1415926; // a将等于3

double型转换成float型时,有效数字减少(四舍五入),精度丢失,例如:

double x=3.1456789012345;float y=x; // y将等于3.145679,7位有效数字float d = (float)x; // 也是四舍五入//注意上述提到的(int) (2+2.56789) // 浮点类型转换为int型,结果为4,小数部分截去

long型转换成float型时,将变成只有7位有效数字的浮点数,精度也会丢失,但由于数的范围扩大了,数据类型从较低级提升到较高级,例如:

long x=123456789; float y=x;

y将等于123456790.0(实际输出除了12345679外,可能有其他无效的数字)

程序员在数据类型转换时,遇到级别降低的情况时,需要判断这种转换的代价是否在合理或可控制的范围内,避免转换后影响程序运行的结果。

C函数如果不能自动进行类型转换,程序员需要进行强制类型转换。例如前面的输出:

printf("%d\n",3.14);printf("%f\n",300);

改成:

printf("%d\n",(int)3.14);printf("%f\n",(float)300);

4.4 误差

不同精度的实型数据混合运算时,由于有效数字的局限性,会出现计算误差,例如:

float x, y; x = 123456789.012345; y = x + 0.1234567;

x无法存储给定的常量,只能存储7位有效数字,0.1234567也无法计算并存储到y中,x+0.1234567是无效的计算。

当一个大数和小数混合运算时,容易出现误差,小数通常被忽略。

在设计C语言程序时,我们应尽量避免出现以上实型数据的舍入误差。

4.5 溢出

把大杯的水倒入一个小杯中,水可能会溢出,同样,因为存储的局限性,数据有一定的值范围,不合适的计算会导致超出范围,导致数据溢出。例如:

char c=127; c=c+1;

因为char型能存储的最大数是127,二进制形式为01111111,加1后应为128,但因为存储的局限性,无法正确保存,将产生值的溢出,c实际存储的是-1,二进制形式为10000000。如果c定义为unsigned char就可以了。

-End-

标签: #c语言unsigned什么意思