•需求
這兩天在看記憶體對齊的相關問題,因此產生了一個,如何將地址轉換為十進位制數?
對於如下程式:
void func() { int a = 10; printf("a 的地址為:%p\n", &a); }通過格式控制符 %p 以及取地址符 &a ,可以很方便的輸出變數 a 的地址。
printf 函式中對於 %p 一般以十六進位制的方式輸出指標的值:
一般而言,十六進位制對於分析各個變數間的記憶體空間位置沒那麼方便,此時往往需要將其轉化為十進位制。
如何那麼,該轉換呢?
•十六進位制地址轉十進位制
方法一
複製輸出控制檯輸出的十六進位制程式碼,通過線上進位制轉換工具將其轉化為十進位制。
是不是簡單粗暴,但是當要轉化的地址多的時候,這個方法往往比較繁瑣,那麼還有沒有其他方法呢?
方法二
首先,編寫一個十六進位制轉十進位制的程式碼,下面做一下簡單介紹。
- 十進位制:逢十進一,數字中含有 0,1,2,3,4,5,6,7,8,9
- 十六進位制:逢十六進一,表示形式比較特殊,0~9 正常用數字表示,10~15 用英文字母 A~F(或 a~f) 來表示
- 10 用 A 表示
- 11 用 B 表示
- 12 用 C 表示
- 13 用 D 表示
- 14 用 E 表示
- 15 用 F 表示
在十六進位制的表示中,大寫字母小寫字母都可以,一般有個 0x 字首表示當前的數用十六進位制表示。
有了相關的知識儲備,我們來看看十六進位制如何轉化為十進位制,假設需要轉換的十六進位制數為 0XFA7B :
$\begin{aligned} 0XFA07B &= F\times 16^{4}+ A\times 16^{3} + 0\times 16^{2} + 7\times 16^{1} + B\times 16^{0} \\ &= 15\times 16^{4}+ 10\times 16^{3} + 0\times 16^{2} + 7\times 16^{1} + 11\times 16^{0} \\ &= 1024123\end{aligned} $
是不是超級簡單,那我們通過程式語言來實現一下:
int change(char c)//分解出每一位對應的數字 { if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; if (c >= '0' && c <= '9') return c - '0'; return 0;//如果是字首的X,輸出0,不影響最終答案 } int hexToDecimal(const string& str)//十六進位制轉十進位制,十六進位制儲存在字串中 { int len = str.length(); int x = 1; int ans = 0; for (int i = len - 1; i >= 0; i--)//從右往左依次處理每一位 { int num = change(str[i]); ans += num * x; x *= 16; } return ans; }這兒有一道進位制轉換的題目,有興趣的小夥伴可以用來測試一下程式的正確性:華為機試|HJ5 進位制轉換。
有了十六進位制轉十進位制的方法,那麼,如何將地址輸出的十六進位制程式碼轉化為字串呢?
這樣操作?
void func() { int a = 10; string str = & a; }顯然不行,編譯都不通過;
這可如何是好?
莫慌,我們可以曲線轉換,下面介紹一下 freopen函式用法。
freopen
函式簡介
freopen 是被包含於 C標準庫標頭檔案 stdio.h 中的一個函式,用於重定向輸入輸出流。
該函式可以在不改變程式碼原貌的情況下改變輸入輸出環境,但使用時應當保證流是可靠的。
函式原型
*FILE freopen( const char filename, const char mode, FILE stream );
引數介紹
- filename:需要重定向到的檔名或檔案路徑
- mode:代表檔案訪問許可權的字串
- "r":表示 只讀訪問
- "w":表示 只寫訪問
- "a":表示 追加寫入
- stream:需要被重定向的檔案流
- stdin 表示從檔案中讀取
- stdout 表示輸出到檔案中
接下來,通過 freopen 實現來完美的實現地址轉十進位制。
CODE
#pragma warning(disable:4996)//取消返回值被忽略的報錯 #pragma warning(disable:4786)//取消使用STL中一些容器的報錯 #include<bits/stdc++.h> using namespace std; int change(char c)//分解出每一位對應的數字 { if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; if (c >= '0' && c <= '9') return c - '0'; return 0;//如果是字首的X,輸出0,不影響最終答案 } int hexToDecimal(const string& str)//十六進位制轉十進位制,十六進位制儲存在字串中 { int len = str.length(); int x = 1; int ans = 0; for (int i = len - 1; i >= 0; i--)//從右往左依次處理每一位 { int num = change(str[i]); ans += num * x; x *= 16; } return ans; } void func() { int a = 10; printf("%p\n", &a);//通過輸出重定向,將地址輸出到addressToDecimal.txt中 string str; cin >> str;//從addressToDecimal.txt讀取已儲存的a的地址 cout << "a的地址為:" << str << ",十進位制為:" << hexToDecimal(str) << endl; } int main() { freopen("addressToDecimal.txt", "r", stdin); freopen("addressToDecimal.txt", "w", stdout); func(); return 0; }我們設定的 freopen 的第一個引數就只是一個檔名,那麼該檔案預設放到專案所在地址,VS可通過右擊找到該專案所在資料夾。
開啟 addressToDecimal.txt 你會發現裡面的內容就是包含兩項:
- 通過 printf 輸出的 a 的地址
- 通過 cout 輸出的資訊
完結撒花~~~
•宣告
參考資料
1.【freopen函式用法|CSDN】