首页 > 其他分享 >第一章 C语言:数据存储

第一章 C语言:数据存储

时间:2023-03-06 11:33:41浏览次数:42  
标签:10 存储 int 补码 第一章 char printf 对齐 C语言

一、大小端存储

  • 大端存储:数据的低位字节存储在高地址
  • 小端存储:数据的低位字节存储在低地址

  不同编译器有不同的存储方式

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 * 2E

      S为数符,M为尾码,E为阶码,E = E + 127

      float 是单精度浮点数,数码 1 bit,尾码 23 bit,阶码 8 bit,共32位

      double是双精度浮点数,数码 1 bit,尾码 52 bit,阶码 11 bit,共64位

//打印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;
}

 

四、结构体内存对齐

  对齐规则

  1. 第一个成员在与结构体偏移量为0的地址处
  2. 其他成员要对齐到对齐数的整数倍的地址处
  3. 对齐数:编译器默认的某个数字与该成员大小的较小值(VS默认值是8)
  4. 结构体总大小为最大对齐数的(每个成员变量都有一个对齐数)整数倍
  5. 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小就是最大对齐数(含嵌套结构体对齐数)的整数倍
#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
}

 

标签:10,存储,int,补码,第一章,char,printf,对齐,C语言
From: https://www.cnblogs.com/phoenixflyzzz/p/17183141.html

相关文章

  • MySql(7)—— 约束、存储引擎
    约束(非常重要)什么是约束?constraint在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性、有效性!!!约束的作用:保证表中的数据有效约束的种类非空约......
  • Winfrom/CSharp中获取当前时间戳字符串、存储Sqlite数据库、时间戳转换与比较大小
    场景Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/129322345在上面Winform中操作Sql......
  • c语言中有符号和无符号数字
    https://nju-projectn.github.io/ics-pa-gitbook/ics2022/why.html#数组求和数组求和intsum(inta[],unsignedlen){inti,sum=0;for(i=0;i<=len-1;i++)......
  • Linux & 标准C语言学习 <DAY1>
    Linux系统简单介绍:  BCPL->NewB->C->UNIX->Minix->Linux->gcc  美国贝尔实验室1968  Linux管理硬盘的能力非常强,所以只有一个磁盘分区  cd路径名......
  • Linux & 标准C语言学习 <DAY3>
    C语言简介:  BCPL->NewB->C->UNIX->Minix->Linux->gcc  C语言诞生于1971~1973年,美国贝尔实验室,肯.汤普逊和丹尼斯.里奇  C语言是专门为了编写操作系统而诞......
  • Linux & 标准C语言学习 <DAY2>
    vim文本编辑器:  可以直接在终端下采用纯键盘操作的一款文本编辑器,号称编辑器之神,可以二次升级、可以扩展  基础用法:    1、进入vim:      ......
  • Linux & 标准C语言学习 <DAY5>
    一、if分支语句  if(表达式) //单分支语句  {     //表达式的值为真,则执行此处代码  }  if(表达式) //双分支语句  {   ......
  • Linux & 标准C语言学习 <DAY4>
    一、数据类型  为什么要对数据进行分类    1、现实中的数据就是自带类别属性的    2、对数据进行分类可以节约内存存储空间、提高运行速度  ......
  • Linux & 标准C语言学习 <DAY6>
    一、数组  什么是数组:变量的组合,是一种批量定义相同类型变量的方式  定义: 类型名数组名[数量];      intarr[5];      注意:数组......
  • C语言数据类型笔记
    Unsigned如果一个字面量常数想要表达自己是unsigned,可以在后面加u或U255U用l或L表示long(long)*unsigned的初衷并非扩展数能表达的范围,而是为了做纯二进制运算,主要是......