C++ 查看變量對應的內存區域的bit形式

最近遇到一個關於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

大概就是這麼多了,如果各位朋友還知道更多的方法,歡迎留言交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章