C语言数据的存储

目录

常见数据类型

1.整型家族:

1.1 char

1.2 short

1.3 int

1.4 long

1.5 long long

浮点型家族

构造类型(自定义类型)

关于数组类型

指针类型

空类型

练习2:

关于变量的存储

大小端字节序

大端字节序存储:

 小端字节序存储:

为什么会存在大小端字节序问题呢?

练习--设计一个函数来求出该机器是大端还是小端字节序 


常见数据类型

char

int

short

long

long long

float

double

1.整型家族:

有符号的:最高位是符号位  0是整数 1是负数

无符号: 最高位是数值位

1.1 char

unsigned char

signed char

对于char 类型 默认为 signed和unsigned 是取决于编译器的

一般情况下都是 signed 很少被认为 unsigned

1.2 short

unsigned short[int]    //int可省略

signed short [int] 

1.3 int

 unsigned int

signed int

1.4 long

unsigned long[int]

signed long[int]

1.5 long long

unsigned long long[int]

signed long long[int] 

/short int long long long 都默认位 signed(有符号的)

关于short int long long long 的区别

可以看到在不同的系统下 不同类型所占字节数可能会不同
 long long是标准的八字节
short 是标准的 二字节

浮点型家族

float

double

long double

构造类型(自定义类型)

>数组类型

>结构体类型 struct

>枚举类型 enum

>联合类型 union

关于数组类型

int arr[3]; //类型是 int [3] 
int arr1[]={0,0,0};// 类型也是 int [3] 
char arr2[4]; //类型是 char [4];

指针类型

int* pi; 
char* pc; 
float* pf; 
double* pd; 
void* pv;

空类型

通常用于函数的返回类型,函数的参数,指针类型等

void Add(void)//无返回值 无参数 { }


整型在计算机中以补码形式存在!

int main()
 {
     unsigned int ch=-10;
     printf("%d\n",ch);//打印结果是-10 
     printf("%u\n",ch);//打印结果是4294967286 
     
     return 0;.
 }

原因:

-10 的

原码:10000000000000000000000000001010

反码:11111111111111111111111111110101

补码:11111111111111111111111111110110

ch中存放的是-10的补码 也就是 1111111111111111111111111111110110

而%u是打印 无符号数 意思是你要我打印的一定是无符号数,不是无符号数我也认为是无符号数

所以1111111111111111111111111111110110 被认为是无符号数 因此 符号位被认为是数值为 打印出来的就是 4294967286

而 %d 打印的就是 有符号数 意思是你要我打印的一定是有符号数 不是有符号数我也认为是有符号数

所以1111111111111111111111111111110110 被认为是有符号数 所以符号位是就是符号位 结果是-10


练习2:

#include<stdio.h>
 int main() 
{ 
    char a=-1; 
    signed char b=-1;
    unsigned char c=-1; 
    printf("%d %d %d\n",a,b,c); //结果是 -1, -1, 255 
    return 0;
}

原因:

char a = -1;

-1 是整数

-1的

原码:10000000000000000000000000000001

补码:11111111111111111111111111111111

整形以补码形式存储在内存中

char类型只有八位 所以a的值是 11111111

而把 a以 %d 的形式打印出来 %d 是整形 所以需要发生整型提升

打印的是有符号数 --->数据现在是补码 需要转换成原码

整形提升 前面补的是原来的变量的符号位

对于a 前面补1 -->1111111111111111111111111111111111

而打印出的是 数据的原码! 原码是 10000000000000000000000000000001 也就是 -1

对于 b 和a 是一样的

对于 c: unsigned char c=-1

c 同样也只能存放11111111

打印c的时候 c是无符号数 所以前面直接补0 ---> 00000000000000000000000011111111

打印数据的原码 正数的原码 就是他本身 所以打印出 255

关于变量的存储

首先要了解一下内存的三个区  如图所示

我们可以验证一下:

可以观察到:

                全局变量c为0 

                局部变量a为随机值      

那么 变量在内存中是怎么存储的呢?

我们知道 int 类型 10 的16进制为 00 00 00 0a

                -            -10 的16进制为  ff ff ff f6

为什么 在内存中是 倒着的呢? --- ------这就是大小端字节序的问题了

大小端字节序

对于多字节数据

                        0x 0 0 1 1 2 2 3 3

                        高字节 <----低字节

大端字节序存储:

        把一个数据低位字节处的数据存放在高地址 处,把高位字节处的数据存放在低地址处

 小端字节序存储:

        把一个数据低位字节处的数据存放在低地址处,把高位字节处的数据存放在高地址处

 

 而不同机器使用大端字节序还是小端字节序 不一定相同 

上面的例子  就是使用了 小端字节序存储

为什么会存在大小端字节序问题呢?

因为在计算机系统中,是以字节为单位的 每个地址单元都对应着一个字节,一个字节为8bit

而C语言中 除了char类型是8bit short int long 等大于8bit的数据类型

另外对于 大于8位的处理器 如16位处理器和32位处理器,由于寄存器宽度大于一个字节,那

么必然存在着一个如何将多个字节安排的问题 所以产生了大小端存储模式!!

练习--设计一个函数来求出该机器是大端还是小端字节序 

思路:

        以 int a = 1 为例子我们只需要知道 第一个字节的内容就可以判断出来 是大端还是小端

        但是 int类型的首地址我们怎么得到呢?

        我们知道 &a得到的是a的起始地址 也就是首字节的地址

        我们如果把&a 强制类型转换后 放到一个char* 类型里面 那么该地址后面的东西就没了

        所以只剩下了首字节的地址 便可以实现了

如图 :

代码实现:

int main()
{
    int a=1;
    char* pa=(char*)&a;//必须要强制类型转换!!!!!
    if(*pa==1)
    {
        printf("小端\n");    
    }
    else 
    {
        printf("大端\n"); 
    }
    return 0;
}

 判断大小端的函数代码

#include<stdio.h>

 int sys()
{
	int a = 1;
	return *(char*)&a;//更简化了
}

int main()
{
	int ret = is_sys();
	if (ret == 1)
	{
		printf("小端\n");

	}
	else {
		printf("大端\n");
	}
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021狮子歌歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值