C语言基础知识-数据类型
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.常量与变量
1>.关键字
C的关键字共有32个。
1>.数据类型关键字(12个) char,short,int,long,float,double,unsigned,signed,struct,union,enum,viod
2>.控制语句关键字(12个)
if,else,switch,case,default,for,do,while,break,contiue,goto,return 3>.存储类型关键字(5个)
auto,extern,register,static,const 4>.其他关键字(3个)
sizeof,typedef,volatile
2>.数据类型
数据类型的作用:编译器预算对象(变量)分配的内存空间大小。
1>.数据类型的定义
变量的定义:
数据类型 变量名[也叫标识符],如:"char Habby;"
变量的赋值:
变量名 = 值,如:“NAME=Jason Yin;”
数据类型 变量名称[标识符] = 值,如:"int AGE = 10;"
2>.标识符的命名规则
字母,数字,下划线组成;
不能以数字开头(第一个字符必须为字母或下划线);
见名知意;
不能和同一函数内其他标识符重复;
不能使用C语言内置的关键字;
标识符中字母区分大小写;
3>.常量
常量的作用: 在程序运行过程中,其值不能被改变的量; 常量一般出现在表达式或赋值语句中; 举几个例子: 整型常量 : 100,200,-100,0 等 实型常量 : 3.14,9.18,1.44 等 字符型常量 : \'a\',\'b\',\'10\',\'\n\' 字符串常量 : "age","123","jason" 常量的定义: const 数据类型 常量名; #deifne 常量名 值 注意: 通过“#deifne”定义的常量是根据值来匹配数据类型的,推荐使用这种方式定义常量。 const修饰的常量是不安全的,可以通过指针来修改
4>.变量
变量的作用:
在程序运行过程中,其值可以改变;
变量在使用前必须先定义,定义变量前必须有相应的数据类型;
变量特点:
变量在编译时为其分配相应的内存空间;
可以通过其名称和地址访问相应内存;
5>.类型限定符
extenrn: 声明一个变量,extern声明的变量没有建立存储空间。 const: 定义一个常量,常量的值不能修改。例如 const int MONTH = 12; volatile: 防止编译器优化代码。 register: 定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令,如果CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,那么register无效。
6>.使用案例
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat variable_definitions.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> #define PI 3.1415926 int main(void) { //定义变量 int _age = 18; printf("Age={%d}\n",_age); //定义常量 const int MONTH = 12; printf("一年有{%d}个月\n",MONTH); //引用使用"#define"定义的变量 printf("圆周率为:{%f}\n",PI); } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o variable_definitions variable_definitions.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./variable_definitions Age={18} 一年有{12}个月 圆周率为:{3.141593} [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
二.进制
进制也就是进制位,是人们规定的一种进位方法。对于任何一种进制-X进制,就表示某一位置的数运算时逢x进一位。十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,依次类推,x进制就是逢x进位。
1>.二进制
二进制逢2进1,所有的数都是由0,1组成,如11+1=100。
十进制转二进制:
除二反序取余法(将十进制数每次除以2,取出余数,按照结果倒叙排序)。
二进制专十进制:
权值法(将二进制各个位数从0位开始乘以2的N次幂,将各个位数的结果相加)。
当前计算机系统使用的基本上都是二进制系统,数据在计算机中主要以补码的形式存储。以下一些术语大家可以了解一下:
bit(比特)
一个二进制代表以为,一个位只能表示0或1两种状态。数据传输是习惯以“位”(bit)为单位。
Byte(字节)
一个字节为8个二进制,称为8位,计算机中存储的最小单位是字节。数据存储是习惯以“字节”(Byte)为单位。
WORD(双字节)
2个字节,即16位。
DWORD
两个WORD,4个字节,即32位。
1b
1bit,1位。
1B
1Byte,1字节,8位。
1k,1K
1024B。
1M(1兆)
1024k,1024*1024。
1G
1024M。
1T
1024G。
1Kb(千位)
1024bit,1024位。
1Kb(千字节)
1024Byte,1024字节。
1Mb(兆位)
1024Kb = 1024 * 1024bit。
1MB(兆字节)
1024KB=1024 * 1024Byte
2>.八进制
八进制逢8进1,所有的数字是0到7组成。
十进制转八进制:
除八反序取余法(将十进制数每次除以8,取出余数,按照结果倒叙排序)。
二进制转化为八进制:
将二进制数字从右到左,每3个二进制数划分为一组,将每组数据的二进制转换成八进制对应的数字即可。
八进制转换为二进制:
八四二一法则(将八进制的每一个位数上的数字拆开,分别用二进制表示即可。)
3>.十进制
十进制逢10斤=1,有数字0-9组成,也是咱们生活中默认使用的进制。
十进制转换成二进制,八进制,十六进制的方法我这里就不啰嗦了,过于简单我这里就不啰嗦了,我这里重点说一下十进制的小数转换成二进制的方式。
十进制小数转换成二进制:
小数部分和2相乘,取整数,不足1取0,每次相乘都是小数部分,顺序看取整后的数就是转化后的结果。为了方便说明,我们看一下十进制的0.521如何用二进制表示:
0.521
* 2
---------
1.042 ---->第一次计算结果,取整数部分1,然后把小数部分0.042继续和2相乘
0.042 ---->这里的0.042就是上面计算的1.042的小数部分
* 2
----------
0.084 ----->第二次计算结果,取整数部分0,然后把小数部分0.084机型和2相乘
0.084 ----->这里的0.084是上面计算的0.084的小数部分
* 2
----------
0.168 ------>第三次计算结果,取整数部分0,并终止计算,因为十进制0.521只有3位小数,顾我们只需要取3位二进制位即可,最终结果为0.100
如上所述,我们来总结一下十进制转换成二进制的几个要点:
(1)乘的时候只乘小数部分;
(2)0.521只有3位,因此我们只需要算出3位二进制位置即可;
(3)0.521的二进制数为:0.100
4>.十六进制
十六进制逢16进1,由数字0-9和字母A-F组成。 十进制转化为十六进制 除十六反序取余法(将十进制数每次除以16,取出余数,按照结果倒叙排序,需要注意的是大于10的数字应该由A-F来表示) 十六进制转化为十进制 权值法(将二进制各个位数从0位开始乘以16的N次幂,将各个位数的结果相加)。 十六进制转换为二进制 八四二一法则(将十六进制的每一个位数上的数字拆开,分别用二进制表示即可。) 二进制转换为十六进制 将二进制数字从右到左,每4个二进制数划分为一组,将每组数据的二进制转换成八进制对应的数字即可。
十六进制转换为八进制
思路就是先将十六进制转换成二进制,再将二进制转换成八进制。
八进制转换成十六进制
思路就是先将八进制换转成二进制,再将二进制转换成十六进制。
5>.进制转换表
6>.在C程序中进制打印案例
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { //十进制数字10 int a = 10; printf("%d\n",a); //定义八进制 int b = 010; printf("%d\n",b); //定义十六进制 int c = 0x10; printf("%d\n",c); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 10 8 16 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { //十进制数字10 int a = 10; printf("%o\n",a); //定义八进制 int b = 010; printf("%o\n",b); //定义十六进制 int c = 0x10; printf("%o\n",c); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 12 10 20 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { //十进制数字10 int a = 10; printf("%x\n",a); //定义八进制 int b = 010; printf("%x\n",b); //定义十六进制 int c = 0x10; printf("%x\n",c); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion a 8 10 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { //十进制数字10 int a = 10; printf("%X\n",a); //定义八进制 int b = 010; printf("%X\n",b); //定义十六进制 int c = 0x10; printf("%X\n",c); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion A 8 10 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
三.sizeof关键字
sizeof不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型的大小,单位为字节;
sizeof的返回值为size_t; sizeof_t类型在32位操作系统下是unsigned int,是无符号的整数。
注意:下面结果是根据64位操作系统获取的数据类型大小,此时案例可参考下面的“使用sizeof查看各个数据类型占用内存大小案例”
char(字符型,1Byte) < short(短整型,2Byte) < int(整型,4Byte)|float(单精度浮点型,4Byte)|long(长整型,4Byte) < long long(长长整型,8Byte)|double(双精度浮点型,8Byte)
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat sizeof_demo.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int a; int b=sizeof(a); //sizeof得到指定值占用内存大小,单位为字节. printf("b=%d\n",b); size_t c = sizeof(a); //用无符号的方式输出c的值 printf("c=%u\n",c); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o sizeof_demo sizeof_demo.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./sizeof_demo b=4 c=4 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat sizeof_demo2.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int a = 10; //sizeof()求出数据类型在内存占用字节(Byte)大小 int len1 = sizeof(a); printf("%d\n",a); printf("int = %d\n",len1); //单精度浮点型 float b = 3.14; int len2 = sizeof(b); printf("%d\n",b); printf("float = %d\n",len2); //字符型 char c = \'A\'; int len3 = sizeof(c); printf("%d\n",c); printf("char = %d\n",len3); //双精度浮点型 double d = 9.18; int len4 = sizeof(d); printf("%d\n",d); printf("double = %d\n",len4); //短整型 short e = 10; int len5 = sizeof(e); printf("%d\n",e); printf("short = %d\n",len5); //长整型 long f = 10; int len6 = sizeof(f); printf("%d\n",f); printf("long = %d\n",len6); //长长整型 long long g = 10; int len7 = sizeof(g); printf("%d\n",g); printf("long long = %d\n",len7); } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o sizeof_demo2 sizeof_demo2.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./sizeof_demo2 10 int = 4 2147483640 float = 4 65 char = 1 2147483639 double = 8 10 short = 2 10 long = 8 10 long long = 8 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
四.计算机内存数值存储方式
1>.原码
一个数的原码(原始的二进制码)有如下特点: 最高位作为符号位,0表示正,1表示负; 其它数值部分都是数值本身绝对值的二进制数; 负数的原码是在其绝对值的基础上,最高位变为1; 举个例子,我们用一个字节的原码来表示+15,-15,+0,-0 +15 : 0000 1111 -15 : 1000 1111 +0 : 0000 0000 -0 : 1000 0000 原码表示方法简单易懂,带有符号数本身转换方便,只要符号位还原即可,但当两个整数相减或不同符号相加时,必须比较两个数哪个绝对值大,才能决定谁减谁,才能确定结果是正还是负,所以原码不便于加减运算。
2>.反码
一个数的反码(原始的二进制码)有如下特点: 对于正数,反码与原码相同; 对于负数,符号位不变,其它部位去反; 举个例子,我们用一个字节的反码来表示+15,-15,+0,-0 +15 : 0000 1111 -15 : 1111 0000 +0 : 0000 0000 -0 : 1111 1111
反码运算也不方便,通常用来作为求补码的中间过渡
3>.补码
在计算机中,数值一律用补码来存储。补码特点如下: 对于正数,原码,反码,补码相同; 对于负数,其补码为它的反码加1; 补码符号位不动,其他为求反,最后整个数加1,得到原码;
举个例子,我们用一个字节的补码来表示+15,-15,+0,-0
+15 : 0000 1111
-15 : 1111 0001
+0 : 0000 0000
-0 : 0000 0000
如果对补码还迷糊的小伙伴,可参考博主推荐阅读:https://www.cnblogs.com/yinzhengjie/p/8666354.html。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat complement.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int a = -15; printf("%x\n",a); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o complement complement.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./complement fffffff1 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# /* 如上所述,输出结果为“fffffff1”,改值用途二进制表示为:1111 1111 1111 1111 1111 1111 1111 0001 符号位不变,其他去反,我们查看该二进制的反码为:1000 0000 0000 0000 0000 0000 0000 1110 我们在反码的基础上加1,得到最终的补码为:1000 0000 0000 0000 0000 0000 0000 1111,即最高位是符号位,1代表负数,即改值二进制的补码表示的为-15. */
4>.补码的意义
在计算机系统中,数值一律使用补码来存储,主要原因如下:
统一了0的编码;
将符号位和其他位统一处理;
将减法运算转变为加法运算;
两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
五.整型(int)
1>.整型变量的定义和输出
%d 输出一个有符号的10进制int类型 %o(字母o) 输出8进制的int类型 %x 输出16进制的int类型,字母以小写输出 %X 输出16进制的int类型,字母以大写输出 %u 输出一个10进制的无符号数
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome1.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int a = 123; //定义变量a,以10进制方式赋值为123. int b = 0567; //定义变量b,以8进制方式赋值0567. int c = 0xabc; //定义变量c,以16进制方式赋值为0xabc. printf("a = %d\n",a); printf("8进制:b=%o\n",b); printf("10进制:b=%d\n",b); printf("16进制:c=%x\n",c); printf("16进制:c=%X\n",c); printf("16进制:c=%d\n",c); unsigned int d = 0xffffffff; //定义无符号int变量d,以16进制方式赋值 printf("有符号方式打印:d = %d\n",d); printf("无符号方式打印:d = %u\n",d); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome1 int_dome1.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome1 a = 123 8进制:b=567 10进制:b=375 16进制:c=abc 16进制:c=ABC 16进制:c=2748 有符号方式打印:d = -1 无符号方式打印:d = 4294967295 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
2>.整型变量的输入
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome2.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int num; printf("请输入a的值:>>> "); //不要加换行符"\n" scanf("%d",&num); //打印输入的int类型的值 printf("num = %d\n",num); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome2 int_dome2.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome2 请输入a的值:>>> 20190520 num = 20190520 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
3>.short,int,long,long long
short(短整型) 2字节 int(整型) 4字节 long(长整型) windows为4字节,Linux为4自己(32位),8字节(64位) long long(长长整型) 8字节
温馨提示:
整型数据在内存中占用的字节数与所选择的操作系统有关。虽然C语言标准中没有明确规定整型数据的长度,但long类型整型的长度不能短于int类型,short类型整数的长度长于int类型。
当一个小的数据类型赋值给一个大的数据类型,不会出错,因为编译器会自动转化。但是当一个大的类型赋值给一个小的数据类型,那么就可能丢失高位。
以下是整型常量及其所需类型
10
代表int类型
10l,10L
代表long类型
10ll,10LL
代表long long类型
10u,10U
代表unsigned int类型
10ul,10UL
代表unsigned long类型
10ull,10ULL
代表unsigned long long类型
接下来我们查看一下打印格式及其含义
%d
输出int类型
%l
输出long类型
%ll
输出long long类型
%hu
输出unsigned short类型
%u
输出unsigned int类型
%lu
输出unsigned long类型
%llu
输出unsigned long long类型
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome3.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { short a = 10; int b = 10; long c = 10L; long long d = 10LL; printf("sizeof(a) = %u\n",sizeof(a)); printf("sizeof(b) = %u\n",sizeof(b)); printf("sizeof(c) = %u\n",sizeof(c)); printf("sizeof(d) = %u\n",sizeof(d)); printf("short a = %hd\n",a); printf("int b = %d\n",b); printf("long c = %ld\n",c); printf("long long d = %lld\n",d); unsigned short a2 =20u; unsigned int b2 = 20u; unsigned long c2 = 20ul; unsigned long long d2 = 20ull; printf("unsigned short a = %hu\n",a2); printf("unsigned int b = %u\n",b2); printf("unsigned long c = %lu\n",c2); printf("unsigned long long d = %llu\n",d2); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome3 int_dome3.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome3 sizeof(a) = 2 sizeof(b) = 4 sizeof(c) = 8 sizeof(d) = 8 short a = 10 int b = 10 long c = 10 long long d = 10 unsigned short a = 20 unsigned int b = 20 unsigned long c = 20 unsigned long long d = 20 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
4>.有符号和无符号的区别
一个有符号的整型数据可以分为两部分:一部分是符号位,一部分是数字位。 无符号数据类型只包含数字位部分。 当我们写程序要处理一个不可能出现负数的时候,一般用无符号数,这样可以增大数的表达最大值。
有符号和无符号整型取值范围如下: short 占用2字节,取值范围在-32768到32767(-2的15次方到2的15次方减1)。 int 占用4字节,取值范围在-2147483648代2147483647(-2的31次方到2的31次方减1) long 占用4字节,取值范围在-2147483648代2147483647(-2的31次方到2的31次方减1) unsigned short 占用2自己,取值范围在0到65535(0到2的15次方减1) unsigned int 占用4字节,取值范围在0到4294967295(0到2的32次方减1) unsigned long 占用4字节,取值范围在0到4294967295(0到2的32次方减1)
六.字符型(char)
1>.字符变量的定义和输出
字符型变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号(\' \')把字符括起来。 字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的ASCII编码放到变量中的存储单元中。char的本质就是一个1字节大小的整型。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { char ch = \'a\'; printf("sizeof(ch) = %u\n",sizeof(ch)); printf("ch(%%c) = %c\n",ch); //输出字符串 putchar(ch); //该方法只能输出字符,该行及下面一行均是输出字符 putchar(\'\n\'); printf("ch(%%d) = %d\n",ch); //打印\'a\'对应的ASSCII的值 return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo char_demo.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo sizeof(ch) = 1 ch(%c) = a a ch(%d) = 97 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
2>.字符变量的输入
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo2.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { char input; //scanf("%c",&input); //接收用户输入的一个字符 input = getchar(); //除了使用上面的scanf方法获取用户输入,我们还可以用getchar来获取用户输入的字符 putchar(input); //将用户输入的字符打印出来 putchar(\'\n\'); //上面打印出来并没有换行,我们可以人为的给它加一个换行符 return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo2 char_demo2.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo2 Y Y [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
3>.ASCII对照表
ASCII码大致有以下两部组成: ASCII非打印控制字符: ASCII表上的数字0-31分配了控制字符,用于控制像打印机等一些外围设备。 ASCII打印字符 数字32-126分配了能在键盘上找到的字符,当查看或打印文档时就会出现。数字127代表Del命令。
ASCII值 | 控制字符 | ASCII值 | 控制字符 | ASCII值 | 控制字符 | ASCII值 | 控制字符 |
---|---|---|---|---|---|---|---|
0 | NUT | 32 | (space) | 64 | @ | 96 | 、 |
1 | SOH | 33 | ! | 65 | A | 97 | a |
2 | STX | 34 | " | 66 | B | 98 | b |
3 | ETX | 35 | # | 67 | C | 99 | c |
4 | EOT | 36 | $ | 68 | D | 100 | d |
5 | ENQ | 37 | % | 69 | E | 101 | e |
6 | ACK | 38 | & | 70 | F | 102 | f |
7 | BEL | 39 | , | 71 | G | 103 | g |
8 | BS | 40 | ( | 72 | H | 104 | h |
9 | HT | 41 | ) | 73 | I | 105 | i |
10 | LF | 42 | * | 74 | J | 106 | j |
11 | VT | 43 | + | 75 | K | 107 | k |
12 | FF | 44 | , | 76 | L | 108 | l |
13 | CR | 45 | - | 77 | M | 109 | m |
14 | SO | 46 | . | 78 | N | 110 | n |
15 | SI | 47 | / | 79 | O | 111 | o |
16 | DLE | 48 | 0 | 80 | P | 112 | p |
17 | DCI | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 | 50 | 2 | 82 | R | 114 | r |
19 | DC3 | 51 | 3 | 83 | S | 115 | s |
20 | DC4 | 52 | 4 | 84 | T | 116 | t |
21 | NAK | 53 | 5 | 85 | U | 117 | u |
22 | SYN | 54 | 6 | 86 | V | 118 | v |
23 | TB | 55 | 7 | 87 | W | 119 | w |
24 | CAN | 56 | 8 | 88 | X | 120 | x |
25 | EM | 57 | 9 | 89 | Y | 121 | y |
26 | SUB | 58 | : | 90 | Z | 122 | z |
27 | ESC | 59 | ; | 91 | [ | 123 | { |
28 | FS | 60 | < | 92 | / | 124 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ` |
31 | US | 63 | ? | 95 | _ | 127 | DEL |
NUL空 | VT 垂直制表 | SYN 空转同步 |
---|---|---|
STX 正文开始 | CR 回车 | CAN 作废 |
ETX 正文结束 | SO 移位输出 | EM 纸尽 |
EOY 传输结束 | SI 移位输入 | SUB 换置 |
ENQ 询问字符 | DLE 空格 | ESC 换码 |
ACK 承认 | DC1 设备控制1 | FS 文字分隔符 |
BEL 报警 | DC2 设备控制2 | GS 组分隔符 |
BS 退一格 | DC3 设备控制3 | RS 记录分隔符 |
HT 横向列表 | DC4 设备控制4 | US 单元分隔符 |
LF 换行 | NAK 否定 | DEL 删除 |
4>.转义字符
所有的转义字符和所对应的意义:
转义字符
|
意义
|
ASCII码值(十进制)
|
\a
|
响铃(BEL)
|
007
|
\b
|
退格(BS) ,将当前位置移到前一列
|
008
|
\f
|
换页(FF),将当前位置移到下页开头
|
012
|
\n
|
换行(LF) ,将当前位置移到下一行开头
|
010
|
\r
|
回车(CR) ,将当前位置移到本行开头
|
013
|
\t
|
水平制表(HT) (跳到下一个TAB位置)
|
009
|
\v
|
垂直制表(VT)
|
011
|
\\
|
代表一个反斜线字符\'\'\\'
|
092
|
\\'
|
代表一个单引号(撇号)字符
|
039
|
\"
|
代表一个双引号字符
|
034
|
\? | 代表一个问号 | 063 |
\0
|
空字符(NUL)
|
000
|
\ddd
|
1到3位八进制数所代表的任意字符
|
三位八进制
|
\xhh
|
1到2位十六进制所代表的任意字符
|
十六进制
|
5>.数值溢出
当超过了一个数据类型能够存放最大的范围时,数值会溢出。 有符号最高位溢出的区别:符号位溢出会导致数的正负发生改变,但最高位的溢出会导致最高位丢失。 char 占用1字节 取值范围在-128到127(负的2的7次方到2的7次方减1) unsigned char 占用1字节 取值范围0到255(0到2的8次方-1)
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo3.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { char input; //符号位溢出会导致数的正负发生改变,0x7f(十六进制表示法)对应的二进制为:0111 1111,给其加2后为:1000 0001,这是负数的原码,其补码为:1111 1111,十进制为-127. input = 0x7f + 2; //127 + 2 printf("%d\n",input); //最高位的溢出会导致高位丢失,0xff(十六进制表示法)对应的二进制为:1111 1111,给其加1后变为:1 0000 0000,char只有8位最高位的溢出(有网友也喜欢说是高位截短),纠其原因是一个字节存取8个比特位,因此结果为:0000 0000,十进制为0. unsigned char input2; input2 = 0xff +1; //255+1 printf("%u\n",input2); //和上面案例原理相同,0xff(十六进制表示法)对应的二进制为:1111 1111,给其加2后变为:1 0000 0001,高位截断后结果为:0000 0001,十进制为1. input2 = 0xff + 2; printf("%u\n",input2); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo3 char_demo3.c char_demo3.c: In function ‘main’: char_demo3.c:19:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] #我们在编译成可执行文件时,发现有warning的提示信息,说是无符号类型数据溢出(-Woverflow)啦,此消息咱们忽略即可,因为这个溢出是咱们人为造成溢出的~ input2 = 0xff +1; //255+1 ^ char_demo3.c:23:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] input2 = 0xff + 2; ^ [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo3 -127 0 1 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
七.实型(浮点型)
实型变量也可以成为浮点型变量,浮点型变量是用来存储小数数值的。在C语言中,浮点型变量分为两种:单精度浮点数(float),双精度浮点数(double),但是double型变量所表示的浮点数比float型变量更精确。
float:占用4字节,7位有效数字。
double:占用8字节,15~16位有效数字。
由于浮点型变量是由有限的存储单元组成的,因此只能提供有限的有效数字。在有效位以外的数字将被舍去,这样可能会产生一些误差。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat float_demo.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main(void) { float a = 3.14f; //或者3.14F,这是传统赋值 double b = 3.14; printf("a = %f\n",a); printf("b = %f\n",b); a = 3.2e3f; //或者3.2E3f,科学法赋值,表示3.2 * 1000 = 3200 printf("a1 = %f\n",a); a = 100e-3f; //表达式为:100 * 0.001 = 0.1 printf("a2 = %f\n",a); a = 3.1415926f; printf("a3 = %f\n",a); //结果为3.141593,因为我们知道a是float类型,占用4字节,仅仅有7位有效数字,最后一位会进行四舍五入法得结果 float r = 2; float s = r * r * 3.14; printf("%.2f\n",s); //注意,“%.2f"表示保留小数点后2位. return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o float_demo float_demo.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./float_demo a = 3.140000 b = 3.140000 a1 = 3200.000000 a2 = 0.100000 a3 = 3.141593 12.56 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
八.字符串格式化输入和输出
1>.字符串常量
字符串是内存中一段连续的char空间,以\'\0\'(数字0)结尾。 字符串常量是由双引号括起来的字符序列,如"chaina","C parogram","$PATH"等都是合法的字符串常量。 字符串常量与字符常量的不同:
每个字符串的结尾,编译器会自动的添加一个结束标志位“\0”,即"a"包含两个字符\'a\'和\'\0\'
2>.printf函数和putchar函数
printf是输出一个字符串,putchar输出一个char。 printf格式字符: 打印格式 对应数据类型 含义 %d int 接收整数值并将它表示为有符号的十进制整数 %hd short int 端整数 %hu unsigned short 无符号短整数 %o unsigned int 无符号8进制整数 %u unsigned int 无符号10进制整数 %x,%X unsigned int 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF %f float 单精度浮点数 %lf double 双精度浮点型 %e,%E double 科学计数法表示的数,此处"e"的大小写代表输出时用"e"的大小写 %c char 字符型,可以把输入的数字按照ASCII对应转换为对应的字符 %s char * 字符串,输出字符串中的字符直至字符串的空字符(字符串以\'\0\'结尾,这个\'\0\'即空字符) %p void 以16进制形式输出指针 %% % 输出一个百分号,即"%" printf附加格式: 字符 含义 l(这个是小写字母l) 附加在d,u,x,o前面,表示长整数 - 左对齐 m(代表一个整数) 数据最小宽度 0(这个是数字0) 将输出的前面补上0知道满指定列环位置不可用搭配使用- m.n(代表一个整数) m值域宽,即对应的输出项在输出设备上所占的字符数,n指进度,用户说明输出的实型数的小数位数。对数值型的来说,未指定n时,隐含的精度为n=6位。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { int a = 100; printf("a = %d\n",a); //格式化输出一个字符串 printf("%p\n",&a); //输出变量a在内存中的地址编码 printf("%%d\n"); char c = \'a\'; putchar(c); //putchar只有一个参数,就是要输出的char long long a3 = 1000; printf("%lld,%llx,%llo\n",a3,a3,a3); int abc = 10; printf("abc = \'%6d\'\n",abc); printf("abc = \'%-6d\'\n",abc); printf("abc = \'%0d\'\n",abc); printf("abc = \'%-06d\'\n",abc); double d = 12.3; printf("d = \\'%-10.3lf\'\n",d); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o echo echo.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./echo a = 100 0x7fff18387bec %d a1000,3e8,1750 abc = \' 10\' abc = \'10 \' abc = \'10\' abc = \'10 \' d = \'12.300 \' [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#
3>.scanf函数与getchar函数
getchar是从标准输入设备读取一个char
scanf通过%转义的方式可以得到用户通过标准输入设备输入的数据
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo2.c /* @author :yinzhengjie blog:http://www.cnblogs.com/yinzhengjie EMAIL:y1053419035@qq.com */ #include <stdio.h> int main() { char ch1; char ch2; char ch3; int a; int b; printf("请输入ch1的字符:>>> "); ch1 = getchar(); printf("ch1 = %c\n",ch1); getchar(); //测试此处getchar()的作用 printf("请输入ch2的字符:>>> "); ch2 = getchar(); printf("\\'ch2 = %ctest\\'\n",ch2); getchar(); //测试此处getchar()的作用 printf("请输入ch3的字符:>>> "); scanf("%c",&ch3); //这里第二个参数一定是变量的地址,而不是变量名 printf("ch3 = %c\n",ch3); printf("请输入a的值:>>> "); scanf("%d",&a); printf("a = %d\n",a); printf("请输入b的值:>>> "); scanf("%d",&b); printf("b = %d\n",b); return 0; } [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o echo2 echo2.c [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./echo2 请输入ch1的字符:>>> a ch1 = a 请输入ch2的字符:>>> b \'ch2 = btest\' 请输入ch3的字符:>>> c ch3 = c 请输入a的值:>>> 100 a = 100 请输入b的值:>>> 200 b = 200 [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# [root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]#