2010-10-15 73 views
2

我想打印一個地址指向的值,但問題是我需要根據傳遞給我的大小取消引用此指針。所以這樣的東西:如何根據尺寸取消引用?

void print(Address addr, Int size) { 
... 
} 

我有點困惑如何實現這一點。有人能指引我朝着正確的方向嗎?

編輯: 好了,所以我在想:

char p[80]; 
memset(p, '\0', 80); 
memcpy(p, addr, size); 

然後解引用爲* P。如果有更好的方法或正確的方式,請讓我知道

+0

你能否詳述一下 - 你的意思是說有時候你想要將指針解引用爲32位int(比如size == 4),有時候是64位int(如果size == 8)?或者你在追求別的東西? – 2010-10-15 04:49:42

+0

@邁克爾:沒錯。我正在嘗試打印這些數字的十六進制表示。 – Legend 2010-10-15 04:55:28

回答

3

您的問題是非常不清楚。如果你的意思是你要轉儲從通過地址任意的二進制數據,你想要的東西,如:

void print(const unsigned char *addr, size_t size) 
{ 
    while (size--) printf("%.2x", *addr++); 
} 

或者,如果你的意思是你要打印的字符數據,這不是空終止,嘗試:

void print(const char *addr, int size) 
{ 
    printf("%.*s", size, addr); 
} 
+1

我將const限定符添加到'char *'參數中。由於函數不會(也不應該)修改指針參數的目標,我們可以讓編譯器的優化器和錯誤檢查知道更多關於裏面發生的事情。 – 2010-10-15 05:26:55

+0

感謝您的修復。 – 2010-10-15 05:44:06

0

如果它是一個數字,我認爲這是,你需要這樣的事情:

int n=0; 
if (size>sizeof(int)) { return; //int is too small }; 
for (int i=0;i<size;i++) { 
    ((char*)(&n))[sizeof(int)-(i+1)] = ((char*)addr)[size-(i+1)]; 
} 
printf("%d",n); 
+0

這段代碼至多有實現定義的行爲,更可能是未定義的行爲... – 2010-10-15 05:08:45

+0

真的,爲什麼? – 2010-10-15 05:12:51

+1

如果'size'小於'sizeof(int)','n'的部分表示仍未初始化。此外,您是否應該複製到開頭或結尾是實現定義的(依賴於endian)。 – 2010-10-15 05:46:35

0

您可以在日常使用switch語句:

switch (size) { 
    case 1: print(*(char*)pointer); break; 
    case 2: print(*(short*)pointer); break; 
    case 4: print(*(long *)pointer); break; 
    case 8: print(*(__int64*)pointer); break; 
    default: puts("unsupported); 
} 

(「打印」是打印各種尺寸,可能使用C++多態性整數的例程)

一個複雜的解決方案是使用一個C++模板例如使用參數類型Integer,該參數在調用時由實際變量類型提供。然後這個例程可以作用於這個Integer變量的大小(如果你自己實現更長的整數,它可能會從1到8變化,或更多)。這種方法的缺點是編譯器會爲每種類型的參數生成一個例程實例,而依賴於尺寸的邏輯將導致某些測試的「始終爲真」條件。一個簡單的方法是始終使用您期望的最長整數類型。

+0

OP已經將此標記爲C而不是C++,所以我想這會排除多態性或重載打印 - 但您的答案背後的原則是確定的。 – Andrew 2012-10-26 09:02:25