1. C语言的数据类型 1Byte == 8bit
计算机存储数据的基本单位:字节(Byte)
计算机表示数据的基本单位:位(bit)
表示数据方式:二进制
typeof(x):求对象(变量、数组名、函数名)的类型 关键字
typeof(3): int
typeof(3.0):double
基本类型:系统分配给基本类型的变量的内存大小固定
整型
(unsigned) short(%hd) 2字节
(unsigned) int 4字节
(unsigned) long(%ld) / long long(%lld) 64位系统:8字节 / 32位系统:4字节
实型(浮点型)
单精度实型 float 4字节
双精度实型 double 8字节长双精度浮点型 long double 64位系统:16字节 / 32位系统:8字节
字符型
(unsigned) char 1字节
♥构造类型:系统分配给构造类型变量的内存大小,取决于该类型具体是如何定义的
数组类型
结构体类型
联合体型(共用体)
枚举类型♥指针类型
*空类型(无类型)
void
2. 常量和变量
常量:在程序运行期间,其值不能被改变的量称为常量
如:1 2 3.1415926
3 = 4; // error 3是一个常量,其值不能被改变,3要是能变成4,岂不是不三不四!
变量:一个可以被改变的量(必须先定义,后使用)
变量实质上是内存中具有特定属性的存储单元,它是用来存放数据的。这个存储单元中的数据,就是变量的值,而这个值在程序运行期间可以被改变(赋值)。变量名:变量的名字
⭐系统把内存以一个字节为单位划分成很多份进行编号,这个编号就是地址(无符号整数),即每增加一个字节地址加1。操作系统访问哪个内存单元时,就必须要知道它的地址。
在定义变量时,会在内存分配空间(大小根据变量的类型决定),这时变量名就与该空间的首地址关联, 即操作系统由变量名去找到该内存空间的地址。变量的定义:
数据类型 变量名;eg: int a; // 定义了一个 int 型的变量a,其空间大小是4字节
"数据类型":所有的C语言合法的类型都可以
"变量名":给存储数据的哪个对象(变量)取个名字,来代表它
⭐在C语言中,不管你是给什么东西起名字,都必须要符合C语言标识符命名规则:
C语言标识符必须由字母、数字、下划线组成,且第一个字符必须是字母或者下划线。int 3coutrt; // error 数字开头
int score+; // error 包含了 +
int count3; // 正确
int _score; // 正确
编程规范:
(1)变量名取名时避免以下划线开头,因为下划线开头的符号一般用于编译器编译的符号。
(2)给对象(变量)取名时,尽量做到“见其名知其意”
int HouseSize;
int house_size;
(3)标识符不能是C语言保留的关键字
int short; //error short是关键字
int Short; //正确
(4)C语言是区分大小写
eg: count 和 Count 是两个不同的意思
(5)在ANSI标准中,"nin-lengh && max-information"
最短的长度表达最多的信息
变量的访问(读/写)
(1)从变量中取值(读)。实际上是通过变量名找到相应的内存地址,从该地址对应的存储单元中读取数据。这时变量一般在赋值符号(=)的右边,表示变量的值,我们称为右值。
(2)给变量赋值(写)。实际上是通过变量名找到对应的内存地址,把数值写到地址对应的存储单元中去,覆盖掉原来的值,这时变量一般在赋值符号(=)的左边,表示变量的内存单元,我们称为左值。
int a;
int b;
a = b; //a是表示变量的内存单元,b是变量的值我们把给变量第一次赋值叫做初始化,若变量没有初始化,该值???(a、b两种可能)
(a)随机值
(b)0
常变量:有类型,占存储单元,不允许改变其值,定义时用 const 修饰的变量。初始化后不能再赋值的变量,即只读变量。
eg: const int c=3;
c = 250; //error
3. 常量表达式:由常量和运算符组成的表达式
整型常量(整数)
十进制常数 1,2,3,99,250 %d(格式控制符)
八进制常数 (以0开头的数字序列) 0666 %o
十六进制常数 (以0x开头的数据字序列) 0x12,0x99,0xff %x
(0,1,。。。8,9,a,b,c,d,e,f)长整型常数 (在数字后加字符L或l) 123l,1234L
实型常量
1)十进制小数形式,由数字和小数点组成。如 123.456,0.345,-56.79……
2)指数形式(e或E前有数,e或E后为整)
如 12.34e3(代表12.34*10^3) -346.87e-25(代表-346.87*10^-25)
符号常量 :用 #define指令,指定用一个符号名称代表一个常量,不占内存,只是一个临时符号,代表一个值,在预编译后这个符号就不存在了,故不能对符号常量重新赋新值,为与变量名相区别,习惯上符号常量用大写表示。
#define 符号常量标识符(大写字母) 常量数据
例: #define PI 3.14159 //注意行末没有分号
整型变量
⭐整型数据在内存中是以二进制的补码形式存放的,且最高位为符号位补码: 0000:0 -1=0-1:1111 -2: 1110 ... -8: 1000
1) 1表示负数,0表示正数,其他位为数值位
2)"补码"
正数:原码,即直接转化成二进制
负数:该值的绝对值的原码取反加1
(1)可以推出 short 的表示范围为 -2^15 ~ 2^15-1 2^15 = 32768
(2)short a = 32767; // 32767 = 2^15-1
a = a + 1; // 数据溢出
printf("%d\n", a); // -32768
(3)当编译器以无符号整数输出(%u),就没有符号位的概念了,全部当作数值位
转化为十进制数输出。%hu 无符号短整形 %u无符号整形 %lu无符号长整形
⭐无符号和有符号的本质区别:
当CPU把数据进行计算时,需要把变量的数据拷贝到CPU内部的寄存器(32bit),
当变量的数据 小于32bit位时,有符号的数据拷贝到寄存器高位补符号位,
无符号的数据拷贝到寄存器高位补0。⭐C语言各整数之间赋值问题:
长->短:int->short int->char short->char
只保留低字节
例如:
short a = 0xc1d1; //1100 0001 1101 0001
char b = a; //1101 0001
短->长:char->int char->short short->int
unsigned(无符号):低字节直接拷贝,高位补0
signed(有符号):低字节直接拷贝,高位补符号位⭐%u 和 %d 都是以 32bit 十进制整数的形式打印
4.浮点型数据 (默认输出小数点后6位)
单精度 float(有效数字7位) 4字节 32bits %f
双精度 double(有效数字15位) 8字节 64bits %lf(1)注意:小数保存在内存中,有可能保存的是近似值
❤️(2)浮点型和零的判断
float b;
#define ESP 0.00000001
if(b <= ESP && b >= -ESP) // 浮点型数据和零的比较 (只能无限接近于0,不能直接等于0)(3)浮点型默认是double类型
typeof(3.0):double
typeof(3.0f):float
5.字符型数据
(unsigned ) char 8bits %c
在内存中,字符型的变量存储的实际是一个小于等于255的整数数据,这个数据就是字符的 ASCII值(以二进制形式存放)'A' = 65, 'a' = 97, '48' = 0;1)字符常量:用 '' 括起来的一个字符,如 '1'、'A'、'='... 字符常量存储在计算机存储单元中时,并不是存储字符(如 a , z ,#等)本身,而是以其代码(一般采用 ASCII 代码)存储的,例如字符' a '的 ASCII 代码是97,因此,在存储单元中存放的是97(以二进制形式存放)。
char c;
c = 'B';
printf("%c\n", c); // B
6. 字符串数据 %s
字符串常量是用 " " 括起来的若干个字符,如:"abcd"、"123456"...
字符串保存在内存中时,其末尾一定有一个结束标识符'\0'(它的ASCII就是0)
字符串没有对应的基本类型,字符串是用字符数组或指针来保存的。1)'A'与"A”的区别:'A'是一个字符,只占一个字节;“A”是一个字符串,包括字符‘A’和‘\0’, 所以占2个字节空间。
2)一个字符串常量不能赋给一个字符型变量。
eg:
printf("i like %s\n", "zhoujielun");
练习:
(1)
int b = -1;
printf("%u %d\n", b, b); // 2^32-1 -1-1补码:
1111 1111 1111 1111 1111 1111 1111 1111%u打印:
无符号转换成原码:正数的原码、补码、反码是一样
1111 1111 1111 1111 1111 1111 1111 1111 // 2^32-1%d打印:
有符号转换成原码:-1的原码转成补码的逆操作
1111 1111 1111 1111 1111 1111 1111 1111 // -1的补码
-1:
1111 1111 1111 1111 1111 1111 1111 1110
取反:
1000 0000 0000 0000 0000 0000 0000 0001(2)
short a = 32767; // 32767 ==> 2^15-1
a = a + 1; // 数据溢出
printf("%d\n", a); // -32768
(3)
unsigned char c = 255;
char d = 255;
printf("%d %u\n", c, c); // 255 255
printf("%d %u\n", d, d); // -1 2^32-1
255的补码:
0000 0000 0000 0000 0000 0000 1111 1111 // 255
d的补码:(以%d打印)
1111 1111 1111 1111 1111 1111 1111 1111
-1:
1111 1111 1111 1111 1111 1111 1111 1110
取反:
1000 0000 0000 0000 0000 0000 0000 0001 // -1
d的补码:(以%u打印)
1111 1111 1111 1111 1111 1111 1111 1111 // 正数的原码、补码一样(4)
unsigned short e = -1;
int f = e;
printf("%d\n", f); // 65535
(5)
unsigned char g = -1;
unsigned int h = -1;
printf("%d %d\n", g, h); // 255 -1
6) 在C语言中,如下程序输出结果为
char c=250;// 取250补码 0000 0000 0000 0000 0000 0000 1111 1010 低8位保存到内存char c中,整型数据在内存中是以二进制的补码形式存放的,且最高位为符号位,此时已保存到内存中了,后面不能再转换成补码形式去运算
unsigned char d;
char f ;
d = c + 249;
f = c + 249;
printf("d=%d\n",d); // 243
printf("d=%u\n",d); // 243
printf("f=%d\n",f); // -13
printf("f=%u\n",f); // 2^23-13