2017-08-15 83 views
2

我想知道我們是否可以通過使用C語言中該位置的裸地址在特定位置打印數據。我們可以通過在C中使用裸地址來打印數據嗎?

用於例如,下面是我使用的代碼:

#include<stdio.h> 

int main(int argc, char** argv) { 

    int num = 10; 
    int *ptr; 
    ptr = &num; 

    //To output the address of the "num" variable 
    printf("Address: %p\n", ptr); 

    //Address is 0x7fff47808f50... 

    //Using that address to print the data at variable "num" 
    printf("Data: %d\n", *(0x7fff47808f50)); 

    return 0; 
} 

但它顯示錯誤。也許我使用了錯誤的語法,或者這不是做這件事的方法。總之,請告訴我正確的方法來做到這一點。

+1

是什麼讓你覺得總是會有在您的地址'0x7fff47808f50'的東西嗎? – litelite

+2

地址發生了變化,它並不總是這樣......你必須將它設置爲一個整數指針,否則如何解碼類型? –

+0

請注意,這是變量「num」的地址,我將它賦值爲10. –

回答

1

可以使用char *別名另一種類型的指針讀取單個字節:

int i; 
char *p = (char *)ptr; 
for (i=0; i<sizeof(*ptr); i++) { 
    printf("p[%d]=%02hhx", i, p[i]); 
} 
2

可以(想法不應該)投的整數指針像這樣:(void *) 0x7fff47808f50

該轉換具有實現定義和未定義的方面,但是,這意味着您的里程會有所不同。這個值顯然會從編譯器變成編譯器,甚至可能是因爲編譯不同,字節順序可能與我們通常編寫數字的方式不一樣,這意味着您可能必須修補很多才能使其工作。

這是在實踐中仍然顯而易見的,當實現定義的行爲使我們能夠重現行爲,下面將遵循:

unsigned long long ptr_as_integer = (unsigned long long) "hello world"; 
printf("%s", (void *) ptr_as_integer); 

int value = 42; 
unsigned long long value_ptr_as_integer = (unsigned long long) &value; 
printf("%d", * (int *) value_ptr_as_integer); 

另外還有uintptr_t類型,這是本設計的,但這是可選所以不能保證存在...

很好奇,好奇;這就是我們學習最好的方式......但請不要在實踐中使用這個!你被教過多少次不使用幻數?

+1

問題的含義詳細內容:儘管當然合理,'(無符號long long)「hello world」;'沒有被指定爲「工作」或者是'unsigned long long'缺乏足夠的寬度 - 甚至是「uintmax_t」。這種情況可能發生在不存在'(u)intptr_t'的平臺上。國際海事組織,當使用指針/從整數,使用'uintptr_t'更好。如果缺少'uintptr_t',代碼的替代方法可能也是可疑的,最好不要編譯。 – chux

+0

@chux感謝批評,但我認爲我的回答已經表達了您的擔憂。你有什麼有用的補充,但尚未被覆蓋? – Sebivor

+0

字節順序對文字無關緊要。這可能是因爲在一個小端機器上,該值存儲爲{0x50,0x8F,0x80,...}。事實上,這是一個發生這種情況的平臺。 http://ideone.com/7OU7GY。儘管我已經使用'uintptr_t'來最大程度的保證我使用了一個兼容指針的類型(如果這樣的東西是可用的......)。 – Persixty

1

修改代碼

#include<stdio.h> 

int main(int argc, char** argv) { 
    int num = 10; 
    int *ptr; 
    ptr = &num; 

    //To output the address of the "num" variable 
    printf("Address: %p\n", ptr); 

    //Address is 0x7fff47808f50... 

    //Using that address to print the data at variable "num" 
    printf("Data: %d\n", *ptr); 

    return 0; 
} 

想問你的是YES的答案。

但是:

  1. 你必須100%確定使用什麼地址。例如,在任何類型的固件中,您都將手冊中定義的寄存器地址定義爲常規數字。我們使用它們像這樣

    #define MY_REG_ADDR 0x12345ABC 
    int a = *((int*)(MY_REG_ADDR)) 
    
  2. 現代的操作系統做地址隨機這樣可執行文件的虛擬地址sapce改變每次運行你的應用程序,所以你不能只使用硬編碼地址的時間。

這裏是後我跑的應用的輸出的4倍(修改後的代碼)

地址:0x7ffc279af5ac
數據:10
地址:0x7ffc2d78021c
數據:10
地址:0x7fffb36ae32c
Data:10
Address:0x7ffca2c2a9ec
Data:10

  • 你改變你的代碼的內存佈局可能會改變每齒所以variabl的地址也可能改變
  • +0

    的確,這就是我幾分鐘前得到的結果。每次編譯後,地址都在不斷變化。 –

    +2

    @YatendraRathore不僅在每次編譯之後,而且在現代操作系統中使用[ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization),每次運行後地址都會改變 –

    相關問題