目录
一、大小端存储
二、整型提升和截断
三、数据的二进制存储
四、结构体内存对齐
一、大小端存储
- 大端存储:数据的低位字节存储在高地址
- 小端存储:数据的低位字节存储在低地址
不同编译器有不同的存储方式
int a = 10;
char* p = (char*)&a;
printf("%x\n", *p); // a ---> 0000000a
// 0000 0000 0000 0000 0000 0000 0000 1010
// 0 0 0 0 0 0 0 a 16进制数据:0x0000000a
// a在VS2019中的存储:0a 00 00 00 低地址 --> 高地址
// 整型在内存中以补码存储
二、整型提升和截断
提升:短字节数据类型 ---> 长字节数据类型
截断:长字节数据类型 ---> 短字节数据类型
char ch = -10;
unsigned char c = -10;
// 10000000000000000000000000001010 -10原码
// 11111111111111111111111111110101 -10反码
// 11111111111111111111111111110110 -10补码
// char类型的截断:11110110
// 整型提升:
// 11111111111111111111111111110110 ch补码 char是有符号类型数据,根据符号位数据补0或1
// 00000000000000000000000011110110 c 补码 c 是无符号类型数据,前面直接补0
printf("%d\n", ch); // 将整型提升后的ch补码转换为原码输出为:-10
printf("%u\n", ch); // 将整型提升后的ch补码直接转为10进制数据输出: 4,294,967,286
printf("%d\n", c); // 将整型提升后的c 补码转换为原码输出为: 246
printf("%u\n", c); // 将整型提升后的ch补码直接转为10进制数据输出: 246
三、数据的二进制存储
正数:原码 = 反码 = 补码
负数:符号位不变,原码剩余位取反得反码,再加一得补码,补码取反加一得原码
浮点数:遵循IEEE754标准,二进制浮点数表示为(-1)^s * M * 2^E真
S为数符,M为尾码,E为阶码,E = E真 + 127
float 是单精度浮点数,数码 1 bit,尾码 23 bit,阶码 8 bit,共32位
double是双精度浮点数,数码 1 bit,尾码 52 bit,阶码 11 bit,共64位文章来源:https://www.toymoban.com/news/detail-492244.html
//打印int、float、double类型在内存的二进制编码
#include <iostream>
using namespace std;
int count = 0;
template<class t>
void printbinary(t e, int length)
{
if (length > 1)
printbinary(e >> 1, length - 1);
putchar((e & 1) + '0');
::count++;
if (::count % 8 == 0)
cout << ' ';
if (::count % (sizeof(e) * 8) == 0)
cout << endl;
}
int main()
{
int i1 = 0, i2 = -1, i3 = 17, i4 = -17;
printbinary(i1, 32);// 00000000 00000000 00000000 00000000
printbinary(i2, 32);// 11111111 11111111 11111111 11111111
printbinary(i3, 32);// 00000000 00000000 00000000 00010001
printbinary(i4, 32);// 11111111 11111111 11111111 11101111
cout << endl;
int tmp = 0;
float* f1 = (float*)&tmp;
*f1 = 0;
printbinary(*(unsigned*)f1, 32); // 00000000 00000000 00000000 00000000
float* f2 = f1;
*f2 = -1;
printbinary(*(unsigned*)f2, 32); // 10111111 10000000 00000000 00000000
// 1 01111111 00000000000000000000000 , E = 01111111B - 127D = 0, (-1)1 * 1.0 * 20 = -1
float* f3 = f1;
*f3 = 17;
printbinary(*(unsigned*)f3, 32);//01000001 10001000 00000000 00000000
// 0 10000011 00010000000000000000000 , E = 10000011B - 127D = 4, (-1)0 * 1.0001 * 24 = 10001B = 17
float* f4 = f1;
*f4 = -17;
printbinary(*(unsigned*)f4, 32); // 11000001 10001000 00000000 00000000
cout << endl;
long long temp = 0;
double* d1 = (double*)&temp;
*d1 = 0;
printbinary(*(unsigned long long*)d1, 64); //00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
double* d2 = (double*)&temp;
*d2 = -1;
printbinary(*(unsigned long long*)d2, 64); //10111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
double* d3 = (double*)&temp;
*d3 = 17;
printbinary(*(unsigned long long*)d3, 64); //01000000 00110001 00000000 00000000 00000000 00000000 00000000 00000000
double* d4 = (double*)&temp;
*d4 = -17;
printbinary(*(unsigned long long*)d4, 64); //11000000 00110001 00000000 00000000 00000000 00000000 00000000 00000000
return 0;
}
四、结构体内存对齐
对齐规则:文章来源地址https://www.toymoban.com/news/detail-492244.html
- 第一个成员在与结构体偏移量为0的地址处
- 其他成员要对齐到对齐数的整数倍的地址处
- 对齐数:编译器默认的某个数字与该成员大小的较小值(VS默认值是8)
- 结构体总大小为最大对齐数的(每个成员变量都有一个对齐数)整数倍
- 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小就是最大对齐数(含嵌套结构体对齐数)的整数倍
#include <stdio.h>
struct S1
{
char c1;
int i;
char c2;
};
struct S2
{
char c1;
char c2;
int i;
};
struct S3
{
char c1;
char c2[20];
char c3[20];
};
struct S4
{
char c1;
char c2[20];
char c3[20];
int i;
};
int main()
{
printf("%d\n", sizeof(S1)); // 12 = 1 + 3(对齐) + 4 + 1 + 3(对齐)
printf("%d\n", sizeof(S2)); // 8 = 1 + 1 + 2(对齐) + 4
printf("%d\n", sizeof(S3)); // 41 = 1 + 20 + 20
printf("%d\n", sizeof(S4)); // 48 = 1 + 20 + 20 + 3(对齐) + 4
}
到了这里,关于【C/C++数据结构与算法】C语言数据存储的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!