#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
// Debug的地址 Release的地址
printf("%p\n", &i); // 0018FA50 001CFEF0
printf("%p\n", &arr[9]); // 0018FA44 001CFF18
//for (i = 0;i <= 12;i++)
//{
// arr[i] = 0;
// printf("hehe\n"); //死循环
//}
return 0;
}
解释:
i和arr是局部的变量
因为局部变量是放在栈区上的
并且栈区的使用习惯是:先使用高地址,再使用低地址
数组随着下标的增长,地址是由低到高变化的
i的地址就再arr的地址后面两个,然后i就变成0了。
但是Release没有死循环 所以Release版本是做过优化的
1.数据的分类
整形家族
浮点型家族
构造类型 - 自定义类型
{
struct 结构体类型
数组
枚举
联合体
}
指针类型
空类型
{
void
{
函数返回类型 void test();
函数参数 void test(void);
指针 void* p;
}
}
int main() //数组是自定义的
{
int arr[10]; //int[10]
int arr2[5]; //int [5]
return 0;
}
2.整形在内存中的存储
int main()
{
int a = -10;
//
//10000000000000000000000000001010-原码
//11111111111111111111111111110101-反码
//11111111111111111111111111110110-补码
//FFFFFFF6
return 0;
}
数据在内存中以2进制
对于整数来说:
整数二进制有3种表示形式:原码,反码,补码
正整数:原码,反码,补码相同
负整数:原码,反码,补码要进行计算
按照数据的数值直接写出的二进制序列就是原码
原码的符号位不变,其它位按位取反,得到的就是反码
反码+1,得到的就是补码
当 反码 -> 补码 可以倒回去算 或者 再次取反+1
整数在内存中存储的是补码
为什么不存原码存反码呢?
使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理
1 - 1; //CPU是不能使用减法的,所以用加法来运算
1 + (-1);
用原码来计算:
00000000000000000000000000000001
10000000000000000000000000000001
10000000000000000000000000000010
-2
用补码来计算:
00000000000000000000000000000001 - 1的补码
11111111111111111111111111111111 - (-1)的补码
00000000000000000000000000000000
0
int main()
{
int a = -10;
int b = 10;
//b的数据是:
//二进制: 10000000000000000000000000001010
//16进制: 00 00 00 0a
//VS存储: 0a 00 00 00
return 0;
}
依上面的可以看出,计算机的存储是靠其他方法的
具体方法就是 : 大端字节序和小端字节序
大端字节序:把数据的低位字序的内容存放在 高 地址处,高位字节序的内容存放在 低 地址处
小端字节序:把数据的低位字序的内容存放 在 低 地址处,高位字节序的内容存放在 高 地址处 - VS采用的
int main()
{
int a = 0x11223344; //11 22 33 44 - 大端字节序 ; 44 33 22 11 - 小端字节序
return 0; //把数据的低位字序的内容存放在高位地址处,高位字节序的内容存放放在低位处
}
百度2015年系统工程师笔试题
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序
把数据低位字节序的内容放在高地址处,高位的内容放在低地址处是大端字节序
int main()
{
//写代码判断字节序
int a = 1;
char* p = (char*)&a;
if (*p = 1)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
输出什么?
int main()
{
char a = -1;
100000000000000000000000000000000001
111111111111111111111111111111111110
111111111111111111111111111111111111
11111111
111111111111111111111111111111111111-补码,打印原码
signed char b = -1;
11111111
unsigned char c = -1;
11111111
000000000000000000000000000011111111 - 原码 - 255
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
补充:
1.char 到底是signed char 还是 unsigned char ?
C语言标准并没有规定,取决于编译器
int 是 signed int ; short 是 signed short
输出什么?
int main()
{
char a = -128;//1000 0000
10000000000000000000000010000000
11111111111111111111111101111111
11111111111111111111111110000000-补码
10000000
11111111111111111111111110000000-整形提升
因为用的是%u打印的,高位就不是符号位,补码就是原码
printf("%u\n",a); // 4294967168
return 0;
}
结果?
int main()
{
char a = 128;
printf("%u\n", a);
00000000000000000000000010000000 - 原反补相同
00000000
11111111111111111111111110000000
return 0;
}
补充:
char类型变量的取值范围:
有符号char的取值范围是:[-128,127]
int main()
{
int i = -20;
unsigned int j = 10;
10000000000000000000000000010100
11111111111111111111111111101011
11111111111111111111111111101100
+
00000000000000000000000000001010
=
11111111111111111111111111110110-补码
11111111111111111111111111110101
00000000000000000000000000001010-原码-10
printf("%d\n", i + j); //-10
//i+j是大于0的,因为j是无符号整形,算出的结果也是个无符号数,单看结果是大于0的
//以%d的形式打印,内存是存补码,要转成原码,所以打印出来的才是个负数
return 0;
}
int main()
{
unsigned int i;
for (i = 9;i >= 0;i--)
{
printf("%u\n", i); //死循环
//即使i是unsigned,但是用%d打印的话,它还是按有符号的打印
}
return 0;
}
int main()
{
char a[1000];
int i;
for (i = 0;i < 1000;i++)
{
a[i] = -1 - i;
}
//-1 -2 -3 .. -127 -128 127 126 125 ... 3 2 1 0 -1 -2 -3 ..
printf("%d", strlen(a));//找到\0
return 0;
}
unsigned char i = 0;
int main()
{
for (i = 0;i <= 255;i++);
{
printf("hello world\n"); //死循环
}
return 0;
}