•需求
這兩天在看內存對齊的相關問題,因此產生了一個,如何將地址轉換為十進制數?
對於如下程序:
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 );
具體內容,請參考:🔗。
接下來,通過 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 輸出的信息
完結撒花~~~