1.数据的基本内置类型:
char | 字符数据类型 | 1字节 |
---|---|---|
short | 短整型 | 2字节 |
int | 整型 | 4字节 |
long | 长整型 | 4字节 |
long long | 更长的整型 | 8字节 |
float | 单精度浮点数 | 4字节 |
double | 双精度浮点数 | 8字节 |
2.void(空类型)
(1)void不能直接定义变量,但 void* 可以,且在32平台下占4字节。
(2)void* 可以接收任意类型,通常用来接收任意指针类型。
3.整型在内存中的存储
创建变量=开辟空间+赋值,空间的大小是根据其自身类型决定的。
对于整形来说,数据存放内存中其实存放的是补码。补码更利于加法运算,因为CPU只有加法器。
我们需要把数据转换为补码形式,先要给出其原码,除过符号为其他比特位全部取反得到反码,然后再将反码加1得到其补码。
大小端问题:
我们知道数据在存储时,都是以字节存储的,不同的计算机可能有不同的存储方式,我们把它分为大端存储模式和小端存储模式。
大端:数据的低权值位保存在内存的高地址中。
小段:数据的低权值位保存在内存的低地址中。
之后的内容默认计算机为小端存储模式。
根据以上知识我们通过实例看一看数据到底是怎么存储的。
比如: int a = 20; int b = -10;
我们知道int类型需要分配四字节,但是他们在计算机中是怎样存储的呢?
存数据看数值,且存储数据时是按字节存储的。
(1)int a = 20; 20为正数,正数的原码、反码、补码都一样。
0000 0000 0000 0000 0000 0000 0001 0100(原、反、补码)
0 0 0 0 0 0 1 4
因为存储是按照字节存储的,所以20在内存(小端)中这样存放: 14 00 00 00
(2)int b = -10,-10为负数,其符号位为1。
1000 0000 0000 0000 0000 0000 0000 1010 (原码)
1111 1111 1111 1111 1111 1111 1111 0101 (反码)
1111 1111 1111 1111 1111 1111 1111 0110 (补码)
F F F F F F F 6
所以,-10在内存(小端)中这样存放:F6 FF FF FF
为了更好的巩固理论知识,我们来做几个练习:
一、输出什么?
#include
#include
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d,b=%d,c=%d", a, b, c);
system("pause");
return 0;
}
解题思路步骤:
(1)我们知道,在存数据时只看数值,取其补码,那我们先求-1的补码:
1000 0000 0000 0000 0000 0000 0000 0001(原码)
1111 1111 1111 1111 1111 1111 1111 1110(反码)
1111 1111 1111 1111 1111 1111 1111 1111(补码)
(2)我们得到原码,现在要把它存入变量所开辟的空间中,但我们变量的数据类型都为char,在内存中开辟了一字节的空间。那么在存数据时就会发生截断,截取低八位的数据存入变量中。那现在变量a、b、c中存的数据为1111 1111.
(3)最后输出,我们需要读取数据,读取数据要看变量自身的类型,这题中,a和b都是有符号char型,其结果肯定是相同的。我们再看输出格式要求,%d为有符号十进制打印,所以会发生整型提升。
负数整型提升时,高位补充符号位1.
正数整型提升时,高位补充符号为0.
无符号数整型提升时,高位补0.
1)读取a和b,a和b为有符号char型,-1为负数,高位补符号位1,整型提升为
1111 1111 1111 1111 1111 1111 1111 1111(补码)//又因为是%d输出,需要把它转换为原码然后输出,
1111 1111 1111 1111 1111 1111 1111 1110(反码)
1000 0000 0000 0000 0000 0000 0000 0001(原码)
a和b的输出要求为%d,即按照有符号十进制打印,所以a和b的值都为-1.
2)读取c,c为无符号char型,所以整型提升时高位补0.得到
0000 0000 0000 0000 0000 0000 1111 1111(原码、补码、反码)
c的、输出要求为%d,即按照有符号十进制打印,结果为255.
答:a=-1,b=-1,c=255.
二、下面程序输出什么?
#include
#include
int main()
{
char a = -128;
printf("%u\n", a);
system("pause");
return 0;
}
解题思路和步骤
(1)存数据,看数值,取补码。
1000 0000 0000 0000 0000 0000 1000 0000(原码)
1111 1111 1111 1111 1111 1111 0111 1111(反码)
1111 1111 1111 1111 1111 1111 1000 0000(补码)
(2)存数据,变量a类型为char,开辟了一字节空间,截取补码低八位存入a中,即a中为1000 0000.
(3)读数据,看变量自身类型,做整型提升,变量a为有符号char,高位补充符号位-1,即 1111 1111 1111 1111 1111 1111 1000 0000
(4)最后以%u的形式打印,%u是按照无符号十进制打印的,(无符号数原码等于补码),所以这里打印出来的就是1111 1111 1111 1111 1111 1111 1000 0000 的十进制4294967168。
答:4294967168。
三、输出什么?
#include
#include
int main()
{
char a = 128;
printf("%u\n", a);
system("pause");
return 0;
}
解题思路和步骤:
(1)存数据,看数值,取补码
0000 0000 0000 0000 0000 0000 1000 0000(原码、补码、反码)
(2)存数据,char开辟了一个字节空间,发生截断,低八位存入,a中存的是1000 0000
(3)取数据,看a的自身类型,为有符号char,发生整型提升,第八位1被当作符号位,则高位补1,为1111 1111 1111 1111 1111 1111 1000 0000.
(4)%u是按照无符号十进制打印,即1111 1111 1111 1111 1111 1111 1000 0000的十进制,为4294967168。
答 : 4294967168.
四、输出什么?
#include
#include
int main()
{
int i = -20;
unsigned int j = 10;
printf("%d\n", i + j);
system("pause");
return 0;
}
解题思路和步骤:
(1)存数据,看数值,取反码。
i
1000 0000 0000 0000 0000 0000 0001 0100(原码)
1111 1111 1111 1111 1111 1111 1110 1011(反码)
1111 1111 1111 1111 1111 1111 1110 1100(补码)
j
0000 0000 0000 0000 0000 0000 0000 1010(原码、反码、补码)
i+j
1111 1111 1111 1111 1111 1111 1110 1100(补码)
+ 0000 0000 0000 0000 0000 0000 0000 1010(补码)
————————————————————————————————————————————————————————
= 1111 1111 1111 1111 1111 1111 1111 0110
(2)取数据,%d有符号十进制输出,
1111 1111 1111 1111 1111 1111 1111 0110 (原码)
1111 1111 1111 1111 1111 1111 1111 0101 (-1)
1000 0000 0000 0000 0000 0000 0000 1010 (取反)
1000 0000 0000 0000 0000 0000 0000 1010 有符号十进制输出为-10.
答:-10.
五、输出什么?
#include
#include
int main()
{
unsigned int i = 0;
for (i = 0; i >= 0; i--){
printf("%u\n", i);
}
system("pause");
return 0;
}
解题思路:
这题数据肯定有一个存储和读取的过程,读取时我们需要看变量的自身类型,很明显i是无符号char型,也就是说,从i中拿到的值将全部为正数且>=0,始终满足for循环的条件,所以此题为死循环。
答:死循环。
六、输出什么?
#include
#include
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++){
printf("hello\n");
}
system("pause");
return 0;
}
解题思路:
这道题和上一题是一个题型,i的值要读取,看其类型,为无符号char型,i的取值只能是0-255,一直满足for循环的条件,为死循环。
答:死循环。
七、输出什么?
#include
#include
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++){
a[i] = -1 - i;
}
printf("%d", strlen(a));
system("pause");
return 0;
}
解题思路:
(1)它最后要输出的是数组长度,那最开始我们已经定义了数组长度100,所以它肯定不是单纯的求a数组长度,我们知道,char遇到\0表示字符结束,而\0的ASCII码刚好也是0,所以说,再遍历数组的时候,一定会碰到0,这是结束,取出i。
(2)遇到0是在哪个情况呢,因为char的取值为-128~127,从-1开始直到-18,比如说我们现在是1111 1111(-128)-1=1111 1110(127),此时我们继续循环,1111 1110一直减一,127次后变为0000 0000,遍历结束!
答:128+127=255