2010-12-16 80 views
1

有人可能會向我解釋,在以下兩行代碼中發生了什麼?假設我們在32位計算機上工作指針算術問題

p - 爲指針

(*(long *)((char **)(p) - 1)) 
(*(int *)((int)(p) - 4)) 

我瞭解的唯一的事情,就是*(long *)「東西」轉換爲long類型的指針,然後DEREF。獲得價值。

謝謝!

+3

評估到20我就希望* *,這是一個32位的機器上。該代碼是64位不安全的。 – 2010-12-16 05:48:24

+0

'p'是什麼?[MoreCharactersToAppeaseJeffAtwood] – 2010-12-16 05:48:31

+0

根據'p'的類型可能是ub也可能不是ub。 – wilhelmtell 2010-12-16 05:48:52

回答

1
(*(long *)((char **)(p) - 1)) 

開始與指針p。將其轉換爲類型(char **)。從中減去一個。將結果轉換爲類型(long *),然後取消引用結果。換句話說,將指針移動一個字節,並獲取存儲在該地址的長整型值。這個操作在某些平臺上可能會被打破,特別是取決於p的類型。

(*(int *)((int)(p) - 4)) 

從指針p開始。將其轉換爲int。減去4.將它轉換爲(int *),並取消引用結果。現在,不是做正常的指針算術,而是直接將指針值作爲整數進行擺動,將其移位四位,然後讀取結果指向的int。該操作在某些系統上也會被打破。

我覺得我設法解析,而不會迷失在parens。無論如何,不​​要這樣做。這是病態的。可能有一些奇怪的嵌入式開發任務,你認爲這樣的事情是一個好主意。如果是這樣,永遠不要承認已經做到了。如果發現它,就責怪別人。

例如,與第二實施例,其中p爲一個int *,並用8個字符和32位整數的系統上,你基本上完成*(P-1)

OTOH,在一個一臺16位int的機器,你正在執行*(p-2),並且在一臺64位int的機器上,你正在執行*(p-0.5),這是不明智的,並且可能會崩潰而只是抱怨關於未對齊的內存訪問。 (它應該會崩潰。)使用實際指向正確類型的指針,並且你永遠不應該有理由去做這種無稽之談。

+0

我剛剛注意到我的第一個描述是錯誤的。從char **減1會調整指針的sizeof(char *)而不是sizeof(char)。所以,如我所說,偏移量可能大於一個字符的大小。 (雖然從技術上來說,一個char可以和char *一樣......) – wrosecrans 2010-12-16 07:48:39

1
(*(long *)((char **)(p) - 1)) 

    Looks like getting the length of some kind of length byte character array 
that was passed by reference. But that is just first glance.. 

    (p) = some object 

    (char **) casts some object to the address of the address of a character, which is a 32bit value sizeof(char**) 

    -1 gets the 32bits in memory prior to (char **)(p) 
    *(long*) does what you thought, takes that 32bits, casts it as a long *, and dereferences it. 
    So there is a record in memory like: 

    struct {long * n; char ** s; } 
    similiar to what happens in parameter passing. 

(*爲(int *)((int)的(P) - 4))

這一個是難看。一些對象p被轉換爲一個int,讓我們希望sizeof(int)是32,所以它可能是一個地址,從它減去4(地址仍然是計數字節,4字節是32位),將其作爲指向int ,並將其解除引用。

對於額外的信用比較它: *((INT *)((INT)(P)) - 1)

1

1: ((字符**)(P) - 1):投p來指向字符的數組的數組和減去(所以它現在就像& P [-1])

(長*):將它轉換爲指向long的指針,並且從該地址開始持續很長時間。

2: ((int)的(P) - 4):投p存放和減去4

(INT *):投它指向INT的陣列,並從該地址

INT取
1

首先得到p之前很久。
對於X32的sizeof(字符*)==的sizeof(長),所以(長*)(字符* )爲(長
所以它只是*((long*)p - 1 )((long*)p)[-1]

第二行則是相同的,但它產生int而不是long(long*)p - 1是相同的地址作爲(int)p - 4,因爲的sizeof(長)== 4.

1

考慮p是一個指針,指向二維陣列 爲.eg

int a[][5] = {10,20,30,40,50,11,21,31,41,51,12,22,32,42,52,13,23,33,43,53,14,24,34,44,54}; 
int (*p)[5] = a; 

現在爲了簡單起見,我們假設地址的[0] [0]作爲1000

現在讓我們評估(*(long *)((char **)(p) + 1));

  1. (char **)(p)會給你解決[0] [0] >>>>即1000
  2. (char **)(p) + 1會的sizeof INT添加到您的地址>>>>即1004
  3. (*(長*))將獲得價值在我們的例子中的地址1004是20

(*(long *)((char **)(p) + 1));將在我們的例子