深度剖析数据在内存中的存储

//以下程序 输出什么?
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 ;
}
先在VS2019运行,得出结果:

 char a和signed char b都是相同定义,都代表有符号数,打印结果为-1,但c定义为unsigned char类型,表示无符号数,其在内存中表示为0000 0000 0000 0000 0000 0000 1111 1111(32位),低八位1111 1111表示 char类型的-1,占1个字节,由于其为无符号数据,系统将1111 1111中的最高位1看为数据,在其前面补0,最后输出0000 0000 0000 0000 0000 0000 1111 1111为255

2.
#include <stdio.h>
int main ()
{
    char a = - 128 ;
    printf ( "%u\n" , a );
    return 0 ;
}
VS运行结果:

char类型数据范围为-128~127,-128在内存中存储为1000 0000,打印格式为%u是十进制无符号整数,将-128在内存中扩展为32位为1111 1111 1111 1111 1111 1111 1000 0000(补码形式),将其输出为十进制,结果为 4,294,967,168

3.
#include <stdio.h>
int main ()
{
    char a = 128 ;
    printf ( "%u\n" , a );
    return 0 ;
}
VS2019运行结果:

 

128在内存中为1000 0000,打印其无符号十进制整数,与2相同,为4,294,967,168

4.
int  i =- 20 ;
unsigned   int   j = 10 ;
printf ( "%d\n" , i + j );
VS2019运行结果:

-20补码为1111 1111 1111 1111 1111 1111 1110 1100,10的补码为0000 0000 0000 0000 0000 0000 0000 1010,两数相加为1111 1111 1111 1111 1111 1111 1111 0110,因为其打印为%d是有符号整数,所以最高位1表示符号位为负数,将其转换为原码为1000 0000 0000 0000 0000 0000 0000 1010,结果为-10

5.
unsigned int  i ;
for ( i = 9 ; i >= 0 ; i -- )
{
   printf ( "%u\n" , i );
}
VS2019运行结果:

出现死循环, 定义无符号整形i,其值一直大于等于0,所以陷入死循环

6.
int  main ()
{
    char  a [ 1000 ];
    int  i ;
    for ( i = 0 ; i < 1000 ; i ++ )
  {
        a [ i ] =- 1 - i ;
  }
    printf ( "%d" , strlen ( a ));
    return 0 ;
}
VS2019运行结果:

 

char类型数据范围为-128~127,当i从0到127,a[i]的值从-1到-128,i从128开始时,a[i]的值从127开始递减,知道a[i]=0时,循环结束,此时0为字符'\0',为字符串结束标志,结束循环,所以循环一共进行255次,所以字符串长度为255
7.
#include <stdio.h>
unsigned char i = 0 ;
int main ()
{
    for ( i = 0 ; i <= 255 ; i ++ )
  {
        printf ( "hello world\n" );
  }
    return 0 ;
}
VS2019运行结果:

 

i为无符号数据,其范围为0-255,所以会陷入死循环

大端小端模式介绍

什么是大端小端:

大端模式,是指数据的低位保存在内存中的高地址,而数据的高位保存在内存的低地址中

小端模式,是指数据的高位保存在内存中的低地址,而数据的低位保存在内存的高地址中

此系统用小端存储,变量a 值为10,十六进制表示为00 00 00 0a,在小端模式下,其在内存中存储为0a 00 00 00

百度 2015 年系统工程师笔试题:

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序

 本题是为判断程序运行的电脑是大端存储模式还是小端存储模式,解法如下:

解法1:

定义i变量赋值为1,将其强转为char类型,只有一个字节,1的二进制形式为0000 0000 0000 0000 0000 0000 0000 0001,将其转为char 类型值只有俩种可能,0和1,当输出为1 的时候说明0000 0001 在内存的低地址中,为小端模式,否则为大端模式

#include <stdio.h>
int check_sys()
{
    int i = 1;//0000 0000 0000 0000 0000 0000 0000 0001
    return *(char*)&i;
}
int main()
{
    int ret = check_sys();
    if (ret == 1)
    {
        printf("小端\n");
    }
    else {
        printf("大端\n");
    }
    return 0;
}

解法2:

使用联合体union,就是一个多个变量的结构体同时使用一块内存区域,区域的取值大小为该结构体中长度最大的变量的值

在内存中1的存储为00 00 00 01(16进制,大端)或者01 00 00 00(16进制,小端),un.ch表示内存中低地址的数据,即00或者01,如果结果是1,即为小端,否则为大端

#include<stdio.h>
int check_sys()
{
    union {
        int i;
        char ch;
    }un;
    un.i = 1;
    return un.ch;
}
int main()
{
    int ret = check_sys();
    if (ret == 1)
    {
        printf("小端\n");
    }
    else {
        printf("大端\n");
    }
    return 0;
}

最后,在平时做题是一定要仔细,对整形数据在内存中的存储要注意分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值