数据的存储(上)

简介: 数据的存储(上)

一.数据类型


类型归类

类型介绍

char         //字符数据类型

short       //短整型

int         //整形

long         //长整型

long long   //更长的整形

float       //单精度浮点数

double       //双精度浮点数


1.整型家族

char

 unsigned char

 signed char

short

 unsigned short[int]     short int num==short num

 signed short[int]

int

 unsigned int             int num==signed int num

 signed int

long

 unsigned long[int]   long num==signed long num

 signed long[int]

long long

 unsigned long long [int]

 signed long long[int]

[]表示可省略的意思,还有一点要注意的是 字符在存储的时候是ASCII码值,ASCII是整数,所以在归类的时候,字符属于整型家族。

char 到底是signed char还是unsigned char 是取决于编译器的,常见编译器char==signed char  


2.浮点型家族

float

double


3.自定义类型(构造类型)

数组类型            

 结构体类型 struct

 枚举类型 enum

 联合类型 union


数组类型也是自定义类型,例如

int arr[10]     类型为 int [10]

int arr[20]     类型为 int [20]

char arr[10]  类型为 char [10]

当数组的元素个数和元素类型发生变化时,数组类型也跟着发生变化


4.指针类型

int *pi;

char *pc;

float* pf;

void* pv;


5.空类型

void 表示空类型(无类型)

通常应用于函数的返回类型、函数的参数、指针类型


void test(){}; 表示函数没有返回类型

void test(void){};   表示含函数不需要参数,不需要传参

void *p; 表示没有具体类型的指针


二. 整形在内存中的存储


一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。

计算机中的整数有三种2进制表示方法,即原码、反码和补码。由符号位数值位两部分组成,符号位都是用0表示,用1表示” ,正数的原反补相同,负数的原码根据短除法算出,反码为原码取反,补码在反码基础上加1

int a = 20;

int b = -10;

以下为代码,涉及到小端存储问题

int main()
{
  int a = 20;
  int b = -10;
  //-10
  //1000 0000 0000 0000 0000 0000 0000 1010
  //1111 1111 1111 1111 1111 1111 1111 0101
  //11111111 11111111 11111111 11110110
  //0xff ff ff f6
  //20
  //0000 0000 0000 0000 0000 0000 0001 0100
  //0000 0000 0000 0000 0000 0000 0001 0100
  //0000 0000 0000 0000 0000 0000 0001 0100
  //0x00 00 00 14
  return 0;
}

1.补码的计算

而关于补码的计算, CPU只有加法器,无法进行减法运算,注意不能用原码计算

int main()
{
  //用原码去计算会出问题 
  int a = 1, b = 1;
  int c = a - b;
  //1-1 <==> 1+(-1)
  //0000 0000 0000 0000 0000 0000 0000 0001 1的原码
  //1000 0000 0000 0000 0000 0000 0000 0001 -1的原码
  //1000 0000 0000 0000 0000 0000 0000 0010 1+(-1)=2
}


int main()
{
  int a = 1, b = 1;
  int c = a - b;
  //1-1 <==> 1+(-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
  //return 0;
  // 0000 0000 0000 0000 0000 0000 0000 0001 1的原码(补码)
  // 1111 1111 1111 1111 1111 1111 1111 1111 -1的补码
  //10000 0000 0000 0000 0000 0000 0000 0000 最高位保存不了,丢弃
}

2.大小端

这里提一下数据的高位和地位,一般左边为高位,右边为低位(这个高低来自于人类的阅读习惯,数字从左向右,表示由大到小)

例如:0x11223344,11是高位,44是低位。

#include<stdio.h>
int main()
{
  int a = 0x11223344;//小端存储
  return 0;
}


41820b428c824bdf8f8ebb6e489794ac.png

这里的0x代表是16进制,可以看到a变量的值在内存中是倒着放的.

6dcd2726df5c46f38b2844eb1ffd3330.png

大端存储(大端字节序存储):把一个数据的低位字节的内容存放在高地址处,高位字节的内容存放在低地址

49feecdea67247f0af8c8a9a9446b229.png

小端存储(小端字节序存储):把一个数据的低位字节的内容存放在低地址处,高位字节的内容存放在高地址

根据大小端概念,写一个小程序来判断机器的字节序

理解:把1存到a里,a在内存的4个字节,拿出a的第一个字节的数据,用char *的指针解引用,访问一个字节,&a是取出的4个字节的地址,但是取出来是int *,需要用到强制转换操作符()

int a=1

0x00 00 00 01


928bb25d90934b8f817a3e8ba9d0c2ca.png

代码:

abb5c3d59034408399d695843ce293c5.png

//设计一个程序来判断当前机器的字节序
#include<stdio.h>
int check_sys()
{
  int a = 1;
  char* p = (char*)&a;
  if (*p == 1)
    return 1;
  else
    return 0;
  //return *(char*)&a;
}
int main()
{
  int ret = check_sys();
  if (ret == 1)
  {
    printf("小端\n");
  }
  else
  {
    printf("大端\n");
  }
  return 0;
}
//小端:返回1
//大端:返回0

3.练习题

有符号数整型提升,提升高位补原来的符号数,无符号数整型提升,提升高位补0,%d打印的是有符号的整数,%u打印的是无符号的整数

直白的来说,就是一个变量的数值截断后,提升高位,看它原来创建的时候是有符号还是无符号,打印的时候是按照%d还是%u,若是%u则所有数值位都是有效位,不存在符号位


1.

#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;
}


95d25f5e7cca4d91bbc929f68b4f73b1.png

char a = -1;

   //-1是整数 32bit

   // 1000 0000 0000 0000 0000 0000 0000 0001

   // 1111 1111 1111 1111 1111 1111 1111 1110

   // 1111 1111 1111 1111 1111 1111 1111 1111

   //截断

   //1111 1111-a

   //1111 1111 1111 1111 1111 1111 1111 1111-提升

  //1000 0000 0000 0000 0000 0000 0000 0000-反码

 // 1000 0000 0000 0000 0000 0000 0000 0001-原码为 -1


c-> 1000 0000 0000 0000 0000 0000 0000 0001

       1111 1111 1111 1111 1111 1111 1111 1110

       1111 1111 1111 1111 1111 1111 1111 1111

   截断 1111 1111

   无符号数提升,高位补0

   0000 0000 0000 0000 0000 0000 1111 1111 所有数值位都是有效位,无符号位,正数的原反补相同,补码是给计算机看的,原码是人看的,想验证答案,转变成原码


其中,a和b的原理一样,signed可省略,而c无符号位,所有位都是有效位,可算出对应的10进制值.

33368f069b0c4a569a324365da742763.png

相关文章
|
11天前
|
存储 小程序
数据的存储
数据的存储
|
6月前
|
存储
【数据的存储】
【数据的存储】
47 0
|
6月前
|
存储
数据的存储(下)
数据的存储(下)
|
8月前
|
存储 缓存 固态存储
一文看懂存储
一文看懂存储
196 1
|
8月前
|
存储 应用服务中间件 nginx
k8s--数据存储、EmptyDir存储
k8s--数据存储、EmptyDir存储
|
8月前
|
存储 监控 安全
使用阿里云存储
使用阿里云存储
75 1
|
9月前
|
存储 小程序 编译器
数据在内存中的存储形式
数据在内存中的存储形式
|
9月前
|
存储 SQL NoSQL
存储的未来
存储的未来
85 1
|
10月前
|
存储 C语言
数据的存储 详解(下)
数据的存储 详解(下)
73 0
|
10月前
|
存储 编译器 C语言
数据的存储 详解(上)
数据的存储 详解
74 0