C++ 查看变量对应的内存区域的bit形式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq295456059/article/details/85880602

最近遇到一个关于C++ float类型表示和显示的问题: link,过程中需要查看变量对应的内存区域的bit形式。

主要有下面的两种方法:

  1. 直接使用C++中的bitset容器:这种方法比较简单,我们使用的是已经封装好的容器,直截了当;
  2. 使用unsigned char类型变量:这一种我们需要自己清晰地知道变量在内存中的存储形式(小端存储/大端存储);

下面分别介绍两种方法。


1 bitset

先看代码:

#include <iostream>
#include <bitset>

using namespace std;

namespace util {
	template<typename VType>
	std::string to_binary(VType value) {
		std::bitset<sizeof(VType) * 8> bs(value);
		return bs.to_string();
	}
}


int main()
{
	string s = util::to_binary<int>(2);
	printf("%s", s.c_str());
}

对应的输出:

00000000000000000000000000000010请按任意键继续. . .

这种形式比较简单,直接使用bitset容器的相关方法就可以了。

2 unsigned char

同样直接上代码:

#include <iostream>

using namespace std;

void char2bin(unsigned char);
void show_bytes(unsigned char*, int);

void show_bytes(unsigned char* start, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%x ", start[i]);	// 小端存储,所以最先输出的是最低位的,以十六进制输出
		unsigned char tmp = start[i];
		printf("%x ", tmp);
		char tmp_1 = start[i];	// printf函数在解析unsigned char和char的时候,会进行高位符号拓展,如果是char,且符号位为1的时候,printf输出高位会出现ffffff
		printf("%x ", tmp_1);
		char2bin(tmp);
	}
	printf("\n");
}

void char2bin(unsigned char tmp)
{
	string data;
	unsigned char mask = 0x80;	// 这里不能用char,因为本编译器将char视为signed char,带有符号位 0x80 >>1 得到0xc0,0x80 >>2 得到0xe0
	for (int i = 0; i < 8; i++)
	{
		if (tmp & (mask >> i))
		{
			data += '1';
		}
		else
		{
			data += '0';
		}

	}
	cout << data.c_str() << endl;
}

int main()
{
	bool a = true;
	bool b = false;
	int c = 2;
	float d = 1.1;
	double e = 1.1;

	show_bytes((unsigned char *)&a, sizeof(a));
	show_bytes((unsigned char *)&b, sizeof(b));
	show_bytes((unsigned char *)&c, sizeof(c));
	show_bytes((unsigned char *)&d, sizeof(d));
	show_bytes((unsigned char *)&e, sizeof(e));

}

对应的输出结果是:

1 1 1 00000001

0 0 0 00000000

2 2 2 00000010
0 0 0 00000000
0 0 0 00000000
0 0 0 00000000

cd cd ffffffcd 11001101
cc cc ffffffcc 11001100
8c 8c ffffff8c 10001100
3f 3f 3f 00111111

9a 9a ffffff9a 10011010
99 99 ffffff99 10011001
99 99 ffffff99 10011001
99 99 ffffff99 10011001
99 99 ffffff99 10011001
99 99 ffffff99 10011001
f1 f1 fffffff1 11110001
3f 3f 3f 00111111

请按任意键继续. . .

代码上不难理解,但是有一些细节需要注意:

  1. 注意区分小端存储 (低字节存储在低地址)和大端存储 (低字节存储在高地址),我当时的编译环境是小端存储,所以最先显示的数据(低地址),对应的是低字节,应该放在后面 (第一种方法bitset其实已经帮我们做好了这件事情);
  2. 在获取二进制表示的时候,用于右移的mask需要是无符号的unsigned char,如果是char(signed char)右移的时候会产生多个1;
  3. printf函数在解析unsigned char和char的时候,会进行高位拓展,如果是char,且符号位为1的时候,printf输出高位会出现ffffff,详细可以参考: link,关于符号拓展和零拓展可以参考: link

大概就是这么多了,如果各位朋友还知道更多的方法,欢迎留言交流。

展开阅读全文

没有更多推荐了,返回首页