2016-01-05 59 views
1
#include<stdio.h> 
main() 
{ 
     unsigned char c; 
     typedef struct name { 
       long a; 
       int b; 
       long c; 
     }r; 
     r re = {3,4,5}; 
     r *na = &re; 
     printf("%d", *(int*) ((char*)na + (unsigned int) & ((struct name *)0)->b)); 
} 

OUTPUT:結構的偏移量是如何計算的?在這裏解釋printf語句?

我會感激如果有人詳細解釋printf語句是該類別中的程序在做什麼?據我說,int是鑄造的。然後char指針被鑄造成na。但我無法理解整個聲明在做什麼?在這裏做什麼? b不是指針,但它似乎被用作指針。我發現這個問題是C編程書籍之一。它似乎是計算結構抵消,但我仍然不知道如何。請幫助我詳細瞭解程序。

回答

3

代碼&((struct name *)0)->b確實被稱爲「offsetof」操作,實際上是well-known C macro

的想法是,如果aA類型的結構,那麼&a.b等於a地址加的ba的偏移量。由於這裏使用的是NULL而不是a的地址,因此結果只是bA類型的結構中的偏移量。

根據維基百科,

這是通過鑄造一個空指針到一個指向結構ST, 然後內獲得的m的地址,所述結構。 儘管這種實現正常工作在許多編譯器,它根據C標準 未定義行爲,2因爲它涉及到一個 提領一空指針(儘管可能有人會說沒有 非關聯化發生,因爲整個表達式在編譯時計算爲 )

那麼我們一步一步看看printf中的表達式。

表達式(unsigned int) & ((struct name *)0)->b))如上所述計算在struct name中的偏移量b,並將結果轉換爲整數。在大多數平臺上,結果應該等於sizeof(long)

代碼中的(char*)na強制轉換爲na,這是一個指向struct name的字符指針。這是必需的,因爲sizeof(char)可以假定爲1而sizeof(*na)大於1.我們想要做的是使用地址*na作爲原始數字地址而不是做pointer arithmetic,因此如果例如na==0x1234,那麼結果((char*)na + 4)等於0x1234 + 4 = 0x1238

總和產生一個存儲器地址。該地址等於對象na中的成員變量b的地址,並且類型爲char *。知道這一點,最後一步是將地址轉換回int *(因爲b的類型爲int),然後解除引用結果(再一次,我們知道它指向b)。最終結果是b的值,然後打印。

+0

我的實際問題是瞭解printf聲明親愛的。仍然我在你嘗試使用你的答案 –

+0

@PunitVara:你還缺少哪些部分?我可以擴大答案。一旦你理解了東西的抵消,其餘的都是普通指針算術。 – kfx

+0

如果您逐步擴展該聲明,我非常感謝您。 –