目录
下一篇:c语言流程控制
变量概述
变量的名字是一种标识符
标识符的构造规则:标识符只能由字母、数字和下划线组成,数字不可以出现在第一个位置上,c元的关键字不可以做标识符
关键字:
赋值和初始化
初始化 int a=0
赋值a=b
对于一个变量没有初始化的情况下做加法会用一个没有意义的值(内存里原有的值)来计算
补充:c99可以在该变量第一次出现之前的任何地方定义变量,但是ANSI C必须在代码开头的地方定义变量
常量VS变量
固定不变的数,是常数。直接写在程序里,我们称作直接量(literal)
更好的方式,定义一个常量
const int AMOUNT=100
const是一个修饰符
加在int的前面,用来给这个变量加上一个const的属性。这个const的属性表示这个变量的值一旦初始化就不能再修改了,如果修改就会报错
一般const变量要全大写
一些变量类型
整型:两个整数运算结果只能是整数 打印用%d
浮点数:带小数点的数字,浮点指的是小数点是浮动的。对应的还有定点数:小数点是不动的,但在c语言中用不到 打印用%f
double:双精度浮点数
float:单精度浮点数
注意double输入输出要用%lf,float要用%f
c语言需要类型,但是对类型的安全检查不足够
整数
char、short、int、long、longlong 蓝色是c99类型
浮点数
float、double、longdouble
逻辑
bool
指针
自定义类型
类型名称:int、long、double
输入输出时的格式化:%d、%ld、%lf
所表达的数的范围:char<short<int<float<double
内存中所占据的大小:1个字节到16个字节
内存中的表达形式:二进制(补码)、编码
注意:浮点数是编码形式,不能直接做加减
sizeof:是一个运算符,给出某个类型或变量在内存中所占据的字节数
例如:
sizeof(int)
sizeof(i)
注意:sizeof是静态运算符,它的结果在编译时刻就决定了,换而言之在sizeof的括号里做运算,这些运算是不会做的
看如下代码
int a=6;
printf("%d\n",sizeof(a++));
printf("%d\n",a);
printf("%d\n",sizeof(a+1.0));
第一个和第二个输出是演示a++并没有执行
第三个在sizeof里做了一个类型转换,转换成成了double,sizeof能感知类型,所以输出了8
测试
printf("%d\n",sizeof(char));
printf("%d\n",sizeof(short));
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(long));
printf("%d\n",sizeof(long long));
注:32位环境下
也就是int代表的是寄存器的位数
![](https://i-blog.csdnimg.cn/blog_migrate/547b200fc3039ace03741650e1a71307.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0cdce3889751b694ecf109ac56f298c8.png)
补码的意义:就是拿补码和原码可以加出一个溢出的"零"
整数的范围
char c=255;//11111111
int i=255;//00000000 00000000 00000000 11111111
printf("c=%d,i=%d\n",c,i);
return 0;
由此结果可得11111111被当做二进制看待时是255,当做补码看待时是-1
根据补码,8位二进制能表示128为负数和127位正数。
unsigned:如果一个字面量常数想要表达自己是unsigned,可以在后面加u或U
例255U
同理用l或L表示long(long)
unsigned的初衷并非扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位
unsigned char c=255;//表示这个变量无负数部分
printf("c=%d\n",c);
整数越界
整数的输入输出
实验
char c=-1;
int i=-1;
printf("c=%u,i=%u\n",c,i);//-1以无符号位输出
return 0;
将八进制与十六进制以十进制输出
char c=012;
int i=0x12;
printf("c=%d,i=%d\n",c,i);
return 0;
也就是%d就是以10进制输出
分别以8进制和16进制输出
printf("c=%o,i=%x\n",c,i);
所以%o是以八进制输出,%x是以16进制输出
其中16进制中%x可以写为大写的X表示将16进制中的字母大写,反之小写
int i=0x1A;
printf("c=%o,i=%X\n",c,i);
选择整数类型
为了准确表达内存,做底层程序的需要
没有特殊需要,就选择int
现在的cpu字长普遍是32位或者64位,一次内存读写就是一个int,一次计算也是一个int,选择更短的类型不会更快,甚至更慢
现在的编译器一般会设计内存对其,所以更短的类型实际在内存中有可能也占据一个int的大小(虽然sizeof告诉你更小)
unsigned与否只是输出的不同,内部计算是一样的
浮点类型
由上图得对于float 0——10^-38是无法表达的,对于double是0——38^-308
_+inf表示+_无穷大 nan表示不是一个有效数字
输入和输出
%e表示科学计数法输出,大写E科学计数法的e会变为大写E
实验:
double ff=1E-10;
printf("%E,%.16f\n",ff,ff);//.16表示显示16位小数
但是做了4舍5入
第一个结果代表做了四舍五入
第二个结果代表在计算机内部0.0049不能正确的表达为0.0049,只能用离散的数去表达数,也就是拿离0.0049最近的那个数表达的0.0049
第三个结果代表,在四舍五入过程中出现了0也会带符号
inf表示超过范围的浮点数:+-∞
nan表示不存在的浮点数
浮点类型是没有精度的
float a,b,c;
a=1.345f;
b=1.123f;
c=a+b;
if (c==2.468)
printf("相等\n");
else
printf("不相等c=%.10f,或%f\n",c,c);
return 0;
运行结果
float只有7位有效
所以第一个结果才是正确的计算结果,第二个是经过舍入的结果
注意:这里a=1.345f,带f的原因是:带小数点的字面量是double而非float,float需要用f或者F来表名身份
一般判断浮点数相等使用如下代码:
if (fabs(c-2.468f)<1e-12)//fabs(f1-f2)<1e-12
printf("相等\n");
因为这个特性所以会导致误差累积,但是整数是没有误差的
选择标准:
如果没有特殊需要,只使用double
现代cpu能直接对double做硬件运算,性能不会比float差,在64位机器上,数据存储的速度也不会比float慢
字符类型
char是一种整数,也是一种特殊的类型:字符。这是因为:
用单引号表示的字符字面量: 'a','1'
'' 也是一个字符
printf和scanf用%c来输入输出字符
char c;
char d;
c=1;
d='1';
printf("%d\n",c);//以十进制输出
printf("%d\n",d);
printf("%c\n",c);//以字符输出,这里输出的是ASSIC中的控制字符
printf("%c\n",d);
scanf("%c",&c);//以字符格式输入
printf("c=%d\n",c);
printf("c='%c'\n",c);
if (49=='1')printf("49='1'");
混合输入
第一种情况
char c;
scanf("%d %c",&i,&c);
printf("i=%d,c=%d,c='%c'\n",i,c,c);
这里%d和%c之间有空格
这么输入就会先读入一个整数再读入一个字符
第一个和第二个输入间可以有多个空格
也可以在整数后面直接跟一个字符,输入12a,整数读到了12,字符读到了a
第二种情况
当%d和%c中没有空格了
scanf("%d%c",&i,&c);
printf("i=%d,c=%d,c='%c'\n",i,c,c);
就是没有空格分隔的连续输入,%d读到整数结束为止,后面的是%c
整数读到了12而字符读到了后面的空格对应第32为ASSIC码
连续输入就正常了
字符计算
char c='A';
c++;
printf("%c\n",c);
printf("%d",'Z'-'A');
大写变小写
printf("%c\n",65+'a'-'A');
小写变大写
printf("%c\n",97+'A'-'a');
逃逸字符
用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠"\"开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符
例如
printf("请分别输入身高的英尺和英寸,""如输入\"5 7\"表示5英寸7英寸:");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\b演示:
printf("123\b\n456\n");
注意\b是将输出位向前一格,并没有删除当前位3
当在\b后面在输出一个字符时就会替代后面那个3
printf("123\bA\n456\n");
\t就是一个tab键,tab键是行的固定位置,而不是决定于有多少个字符
printf("123\t456\n");
printf("12\t456\n");
发现无论前面有多少位,4是对齐的
回车和换行源自于打字机
回车指的是将打字机的纸回到初始位置
换行指将滚筒向上卷,使之换行
为什么之前只用了换行\n?因为,shell自动将\n翻译成了回车加换行。
注意:不同的shell对逃逸字符的翻译可能不一样
类型转换
自动类型转换
当运算符的两边出现不一致的类型时,会自动转换成较大(能表达的数的范围更大)的类型
char->short->int->long->long long
int->float->double
对于printf,任何小于int的类型都会被转换成int;float会被转换成double,所以输出double时用%f就可以了
但scanf不会,要输入short,需要%hd
强制类型转换:要把一个量强制转换成另一个类型(通常是较小类型),需要:
(类型)值
printf("%d\n",(short)32768);
printf("%d\n",(char)32768);
出现0是因为转换成char,32768=10。。。0(15个0),char取了最低8个bit就是0
强制类型转换是从那个变量计算出一个新的类型的值,并不会改变那个变量,无论是值还是类型都不会改变
int i=32768;
short s=(short)i;
printf("%d\n",i);
强制类型转换优先级高于四则运算
bool类型
c语言本身没有bool类型
#include<stdbool.h>之后就可以使用bool和true、false
该头文件的部分内容:
实际上就是一个整数,可以对其进行赋整型值