C 如何將輸出的地址轉化為十進位制數

MElephant發表於2022-03-23

 

•需求

  這兩天在看記憶體對齊的相關問題,因此產生了一個,如何將地址轉換為十進位制數?

  對於如下程式:

void func()
{
    int a = 10;

    printf("a 的地址為:%p\n", &a);
}

  通過格式控制符  %p 以及取地址符  &a ,可以很方便的輸出變數 a 的地址。

   printf 函式中對於  %p  一般以十六進位制的方式輸出指標的值:

C 如何將輸出的地址轉化為十進位制數

  一般而言,十六進位制對於分析各個變數間的記憶體空間位置沒那麼方便,此時往往需要將其轉化為十進位制。

  如何那麼,該轉換呢?

•十六進位制地址轉十進位制

方法一

  複製輸出控制檯輸出的十六進位制程式碼,通過線上進位制轉換工具將其轉化為十進位制。

  是不是簡單粗暴,但是當要轉化的地址多的時候,這個方法往往比較繁瑣,那麼還有沒有其他方法呢?

方法二

  首先,編寫一個十六進位制轉十進位制的程式碼,下面做一下簡單介紹。

  • 十進位制:逢十進一,數字中含有 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;
}

  顯然不行,編譯都不通過;

C 如何將輸出的地址轉化為十進位制數

  這可如何是好?

  莫慌,我們可以曲線轉換,下面介紹一下 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可通過右擊找到該專案所在資料夾。

C 如何將輸出的地址轉化為十進位制數

  開啟  addressToDecimal.txt 你會發現裡面的內容就是包含兩項:

  1. 通過 printf 輸出的 a 的地址
  2. 通過 cout 輸出的資訊

C 如何將輸出的地址轉化為十進位制數

  完結撒花~~~

•宣告

參考資料

  1.【freopen函式用法|CSDN

相關文章