C-整形在内存中的存储(截断、提升、大小端机)

1、判断下面的程序输出什么?
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d\nb=%d\nc=%d\n", a, b, c);
	system("pause");
	return 0;
}

规则
原码→反码:除符号位,按位取反;    反码→补码:反码加一

先看-1在内存中是怎么存的:
-1的原码: 1000 0000 0000 0000 0000 0000 0000 0001
-1的反码: 1111 1111 1111 1111 1111 1111 1111 1110
-1的补码: 1111 1111 1111 1111 1111 1111 1111 1111 (内存)


打印a

补码截断
char类型占一个字节,8位;
-1的补码:1111 1111 1111 1111 1111 1111 1111 1111 截断后8位(第一个字节)赋给字符型a;
由于a要以%d形式打印,所以将char型提升为int型;

整形提升

概念:
无符号类型 提升 补0;
有符号类型 提升 高位为1,补1;高位为0,补0

此时, a是char型,有符号类型
1111 1111 提升给 a:
因为高位(最左边一位)为1,所以给a的前24位(共4个字节32位)补1
1111 1111 1111 1111 1111 1111 1111 1111(内存中存的是二进制补码

运行结果是以原码的形式打印出来的,求出原码:
补码:1111 1111 1111 1111 1111 1111 1111 1111
反码:1111 1111 1111 1111 1111 1111 1111 1110
原码:1000 0000 0000 0000 0000 0000 0000 0001(-1)

所以,a打印结果是:-1


打印b

signed char类型和char类型在这里是一样的截断方式和整形提升,同上:

所以,b打印结果是:-1


打印c

unsigned char 与char都是占用1个字节,阶段后8位;
1111 1111 提升给 c:

整形提升

unsigned char 类型,无符号。c的前24位补0:

0000 0000 0000 0000 0000 0000 1111 1111(内存中存的是二进制补码)

符号位是0,原码和补码相同:

0000 0000 0000 0000 0000 0000 1111 1111(原码:255)

所以,c打印结果是:255


运行结果:
在这里插入图片描述



2、我们用的笔记本一般是大端机还是小端机?

我们先来了解一下什么是大端和小端:
大端:数据的低位保存在内存的高地址中;数据的高位保存在内存的低地址中。
小端:数据的低位保存在内存的低地址中;数据的高位保存在内存的高地址中。
我们常用的x86结构就是小端模式

如何判断大小端机呢?简单说一下这3中方式:

1、取低地址,解引用判断

int main()
{
    int x = 1;
    char* p = (char*) &x; // 截断,取x的低地址
    if (*p == 1)          // 看1是否存在低地址
        printf("小端机\n");
    else
        printf("大端机\n");
}

2、强制类型转换判断:

int main()
{
    int x = 1;
    char flag = (char) x;
    if (flag == 1)
        printf("小端机\n");
    else
        printf("大端机\n");
}

3、联合体/共用体:
union(联合体/共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点:
1.一般而言,共用体类型实际占用存储空间为其最长的成员所占的存储空间;
2.若是该最长的存储空间对其他成员的元类型(如果是数组,取其类型的数据长度,例int a[5]为4)不满足整除关系,该最大空间自动延伸;

int check()
{
	union UN
    {
        int i;
        char c;
    };

    union UN test;
    test.i = 1;
    return test.c;
}
int main()
{
	if(check()==1)
		printf("小端机\n");
	else
	    printf("大端机\n");
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值