数据在内存中的存储必刷题

本文详细剖析了不同类型数据如整形和浮点型在内存中的存储方式,包括原码、反码、补码的概念及位操作符的使用,如左移、右移。还探讨了大小端字节序的问题,以及如何通过位运算高效地计算二进制中1的个数。此外,文章还涉及了隐式类型转换和死循环的情况,并举例说明了浮点型数据的内存表示。
摘要由CSDN通过智能技术生成

前言

该部分是有关数据在内存中的存储的一些经典例题,也包含了相关知识点的补充,前后题目有紧密联系,可以作为学习的例题或课后作业,帮助你查漏补缺提升进步。 

剖析整形在内存中的存储

剖析整形在内存中的存储_WHabcwu的博客-CSDN博客内置类型名称字节大小char字符1short短整型2int整形4long长整型4/8long long更长的整形81.1关于数据大小的范围(1)int 为例其他以此类推,long long除外方法:图1-1查看:图1-2(2)long long的范围是多少?-2^64“ 到”2^64 -1-9223372036854775808到92233720368547758071.2详细介绍要点(问答形式)1.何为内置类型?该语言本身自带的类型。https://blog.csdn.net/WHabc2002/article/details/131515659

浮点型在内存中的存储 

浮点型在内存中的存储_WHabcwu的博客-CSDN博客1.浮点数是什么?就是数学中的小数。常见的浮点数:3.14159浮点数家族包括: float、double、long double 类型。浮点数表示的范围:float.h中定义(图1-1,图1-2)图1-1图1-2。https://blog.csdn.net/WHabc2002/article/details/131886153


目录

前言

一、原码、反码、补码(操作符)

1.移位操作符

2. 位操作符

二、数据在内存中的存储

1.大小端字节序

         2.signed与unsigned

 3.隐式类型转换

4.按照补码的形式进行运算,最后格式化成为有符号整数

 5.死循环

6.浮点型在内存中的存储


一、原码、反码、补码(操作符)

1.移位操作符

1.<< 左移操作符
移位规则:
左边抛弃、右边补0
2.>> 右移操作符
   
移位规则:
首先右移运算分两种:
1. 逻辑 移位
左边用0填充,右边丢弃
2. 算术 移位(一般编译器是算术移位)
左边用原该值的符号位填充,右边丢弃
注:移位操作符的操作数只能是整数。
注意 
对于移位运算符,不要移动负数位,这个是标准未定义的。

2. 位操作符

位操作符有:
1. & //按位与
对应的二进制位,有0则为0,同时为1才为1。
2. |  //按位或
对应的二进制位,有1则为1,同时为0才为0。
3. ^  //按位异或
对应的二进制位,相同为0,相异为1。
重要:
(1)a^a=0;
  (2) a^0=a;
 (3)支持交换律
注:他们的操作数必须是整数。

 例1:不能创建临时变量(第三个变量),实现两个数的交换。

#include <stdio.h>
int main()
{
 int a = 10;
 int b = 20;
 a = a^b;
 b = a^b;
 a = a^b;
 printf("a = %d b = %d\n", a, b);
 return 0;
}

解析:图1-1 

                                                               图1-1  

例2.编写代码实现:求一个整数存储在内存中的二进制中1的个数。

 方法1:

#include <stdio.h>
int main()
{
	int count = 0;
	int n = 0;
	scanf("%d", &n);
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n /= 2;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}
总结:
对于整数:
(1)n*2- >n=n<<1;
  (2)   n/2- >n =n>>1;
 (3)n为奇数,最低为一定是1。
  (4)n为偶数,最低为一定是0。
这样的实现方式有没有问题?
(1)不能处理负数。
(2)进行了大量的取模以及除法运算,效率比较低。
 方法2:
#include <stdio.h>
int main()
{
	int count = 0;
	int n = 0, i = 0;
	scanf("%d", &n);
	for (i = 0; i < 32; i++)
	{
		if (n & (1 << i))
		{
			count++;
		}
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}
思路:将 一个整数存储在内存中的二进制进行一一判断是不是1。
这里必须循环 32次的,还能不能更加优化?
 方法3:
#include <stdio.h>
int main()
{
	int count = 0;
	int n = 0;
	scanf("%d", &n);
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}

解析:

在n不为0的情况下,我们对n进行位运算n&(n-1)。这个运算会把n的二进制表示中最右边的1变成0。比如,对于十进制数10,它的二进制表示是1010,那么 10&(10-1) = 8,等价于把10的二进制表示最后一个1变成0。

二、数据在内存中的存储

1.大小端字节序

例1. 设计一个小程序来判断当前机器的字节序
画图解释辅助理解

                                                            图2-1

​
#include<stdio.h>
int check_sys()
{
	int i = 1;
	return (*(char*)&i);
}

int main() 
{
	int a = check_sys();
	if (a == 1)
	{
		printf("小端字节序");
	}
	else 
	{
		printf("大端字节序");
	}
	return 0;

}

​

2.signed与unsigned

char为例画图解释辅助理解

                                                    图2-2

 

                                                图2-3 

例2.输出什么?

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

答案:

 3.隐式类型转换

题目基础

1.%d十进制的形式打印有符号整型

2.%u十进制的形式打印无符号整型

例3.输出什么?

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

分析

char a = -128;
    //10000000000000000000000010000000-原码
    //11111111111111111111111101111111-反码
    //11111111111111111111111110000000-补码
    //截断->10000000

    //11111111111111111111111110000000-整型提升

答案:

变式:例4.输出什么?

#include <stdio.h>
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

分析

char a = 128;
    //00000000000000000000000010000000-原码
    //01111111111111111111111101111111-反码
    //00000000000000000000000010000000-补码
    //截断->10000000
    //11111111111111111111111110000000-整型提升

 答案:

4.按照补码的形式进行运算,最后格式化成为有符号整数

例5.输出什么?

#include <stdio.h>
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}

分析

unsigned int j=10<=>signed int j=10<=>int j=10

任意正整数同理!

 答案:

 5.死循环

以下两题答案都是死循环,请通过图2-2和图2-3进行理解

例6.输出什么?

#include <stdio.h>
//#include<windows.h>
int main()
{
	unsigned char i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
		//sleep(1000);//单位是毫秒
	}
	return 0;
}

(变式)例7.输出什么?

#include <stdio.h>
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0;
}

6.浮点型在内存中的存储

例8.输出什么?

你觉得答案是多少呢?

#include<stdio.h>
int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 printf("n的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 *pFloat = 9.0;
 printf("num的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 return 0;
}

答案:

 解析:

 int n = 9; 

00000000000000000000000000001001

 float* pFloat = (float*)&n;

 0     00000000 00000000000000000001001
    S     E为全0              M
    0       -126    0.00000000000000000001001

故:

  printf("n的值为:%d\n", n);  //  9
    printf("*pFloat的值为:%f\n", *pFloat);
  // (-1)^0*0.00000000000000000001001*s^-126 , 接近0 。
 

 *pFloat = 9.0;

 (-1)^0*1.001*10^3
   S=0     M=001    E=3+127=130 
    0 10000010  0010000000000000000000000

故:
    printf("num的值为:%d\n", n);
    //按照整形的读法是一个很大的数
    printf("*pFloat的值为:%f\n", *pFloat);
    //9.000000
  

以上为我个人的小分享,如有问题,欢迎讨论!!!  

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值