Debug和release版本的区别
release版本会自动优化程序,比如上图中将变量i放到低地址存储防止数组溢栈造成死循环。
1. 数据类型介绍
类型的意义:
1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
2. 如何看待内存空间的视角。
1.1 类型的基本归类:
整形家族:
![](https://i-blog.csdnimg.cn/blog_migrate/ddf6e1d20b898c751d7d8adc7d0347e0.png)
注意:如果只写char,到底是signed char还是unsingned char是未定义的,取决于编译器的实现。其他的如果只写基本类型则是属于signed类型。
浮点数家族:
构造类型:
//第一个void 表示函数不会返回值
//第二个void 表示函数不需要传任何参数
void test(void)
{
printf("hehe\n");
}
int main()
{
test();
return 0;
}
2. 整形在内存中的存储
数值有不同表示形式 eg
(1)2进制 0b10101
(2)8进制 025
(3)10进制 21
(4)16进制 0x15
2.1 原码、反码、补码
整数的2进制表示也有三种表示形式:
1. 正的整数,原码、反码、补码相同
2. 负的整数,原码、反码、补码是需要计算的
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位
正数的原、反、补码都相同。
原码:直接通过正负的形式写出的二进制序列就是原码
反码:原码的符号位不变,其他位按位取反得到的就是反码
补码:反码+1就是补码
故得出结论整数内存中存放是补码的二进制序列
2.2 大小端介绍
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中。
3.练习
1.请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。
判断字节序是小端或者大端只需检测首元素地址是00还是01,如上图。
而要去出十六进制首元素地址,需要步骤:
(1)&a---->int*
(2)*&a---->整形字符中的四个字节
(3)*(char*)&a------>强制转换类型为char*则取出一个字节的内容
#include <stdio.h>
int check_sys()
{
int i = 1;
return (*(char *)&i);
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
2.输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
首先
signed char
因第一个比特位的二进制数字表示符号,则只有7比特位的数字
从00000000到01111111都是正数计算出来的十进制数就是0到127.
而从10000000到11111111都是负数 注意:10000000直接计算成-128
故从10000000到11111111计算出来的十进制数就是-128到-1.
unsigned char
00000000到11111111计算出来的十进制数就是0-255
注意:(1)signed发生整型提升补的是符号位数字,而unsigned发生整型提升补的是0.
(2)由四个字节转换为一个字节时发生截断,直接从右端截取8个比特位并使用。
4.例题分析
(1)
#include <stdio.h>
//
//int main()
//{
// //char -128~127
// char a = -128;
//
// //10000000000000000000000010000000
// //11111111111111111111111101111111
// //11111111111111111111111110000000 - 截断
// //10000000 - a
// //11111111111111111111111110000000 - 提升
// //
// printf("%u\n", a);
// printf("%d\n", a);
// //11111111111111111111111110000000
// //10000000000000000000000001111111
// //10000000000000000000000010000000
// //-128
//
// //
// //
// //%u - 打印无符号整数
// //
// return 0;
//}
//
//#include <stdio.h>
//int main()
//{
// //-128~127
// char a = 128;
// //00000000000000000000000010000000
// //10000000 - a
// printf("%u\n", a);
// printf("%d\n", a);//-128
//
// //10000000
// //11111111111111111111111110000000
// //10000000000000000000000001111111
// //10000000000000000000000010000000
//
// return 0;
//}
(2)
5.
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
(3)
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
//arr[i] --> char -128~127
//-1 -2 -3 -4 ... -1000
//-1 -2 ... -128 127 126 125 .. 3 2 1 0 -1 ...
//128+127 = 255
printf("%d", strlen(a));//255
//strlen 是求字符串的长度,关注的是字符串中'\0'(数字0)之前出现多少字符
return 0;
}
注意:char类型变量存储范围是从-128~127.
(4)
#include <stdio.h>
unsigned char i = 0;
unsigned char 类型的取值范围是0~255
int main()
{
for (i = 0; i <= 255; i++)//因为char类型取值范围是0~255而i<=255恒成立,所以就死循环了。
{
printf("hello world\n");
}
return 0;
}
(6)
int main()
{
//int len = strlen("abcdef");
//printf("%d\n", len);
//size_t -> unsigned int
//
if ((int)strlen("abc") - (int)strlen("abcdef")>0)
printf(">\n");
else
printf("<\n");
return 0;
}
输出结果为(int)strlen("abc")-(int)strlen("abcdef")>0 因为strlen是size_t类型属于无符号数,无符号数-无符号数也是一个无符号数,而无符号数>0。
5.计算
//int main()
//{
// int i = -20;
// //10000000000000000000000000010100
// //11111111111111111111111111101011
// //11111111111111111111111111101100 - -20的补码
// //
// unsigned int j = 10;
// //00000000000000000000000000001010
// printf("%d\n", i + j);
// //11111111111111111111111111101100
// //00000000000000000000000000001010
// //11111111111111111111111111110110 - 补码
// //10000000000000000000000000001001
// //10000000000000000000000000001010 -> -10
// //
// return 0;
//}