指針算術,是整數自動轉換爲其簽名的變體?如果是,爲什麼?指針運算&簽名/未簽名轉換!
假設我
int *pointer;
int *pointerdiff;
unsigned int uiVal = -1;
pointerdiff = pointer + uiVal // Pointer will contain valid address here.
其中指針是指向int和uiVal被初始化爲-1,然後我發現,在指針的地址得到遞減4爲什麼是無符號值-1這裏不考慮?
指針算術,是整數自動轉換爲其簽名的變體?如果是,爲什麼?指針運算&簽名/未簽名轉換!
假設我
int *pointer;
int *pointerdiff;
unsigned int uiVal = -1;
pointerdiff = pointer + uiVal // Pointer will contain valid address here.
其中指針是指向int和uiVal被初始化爲-1,然後我發現,在指針的地址得到遞減4爲什麼是無符號值-1這裏不考慮?
它看起來像你的指針溢出。
讓我們來做一些數學。假設你在一臺32位機器上,並且你的指針初始化爲0x 12 34 56 78
。然後,我們初始化一個無符號整型變量-1
,這是0x FF FF FF FF
。因爲它是一個無符號整數,所以-1
溢出,實際上代表4 294 967 295
。
您的指針指向一個整數(int*
),因此每個增量實際上會將地址增加sizeof int
,這是標準x86機器上的4。所以我們實際上添加了0x 03 FF FF FF FC
(這是0x FF FF FF FF * 4
)。
現在讓我們將這兩者加在一起。
0x 00 12 34 56 78
+ 0x 03 FF FF FF FC
-------------------
0x 04 12 34 56 74
當然,這個溢出,因爲我們現在有一個40位的值,而指針是32位,只能容納這麼多的信息。因此我們在開始時失去了04
。這導致0x 12 34 56 74
,這是0x 12 34 56 78 - 4
。
是的,整數操作數被提升。但這並不重要。如果它是無符號類型,則它不能爲-1
。也許你沒有
unsigned int uiVal = -1;
pointer + uiVal ...
但會做一樣
pointer + UINT_MAX ...
而這很可能會導致不確定的行爲,如果指針可以容納地址範圍不能帶有附加應對。標準說在5.7/4
對於這些操作符的目的,一個指向非數組對象的行爲相同的指針長度的一個陣列的具有作爲其元素類型的對象的類型的第一元件。
如果將具有整型的表達式添加到指針或從指針中減去,則結果爲指針操作數的類型。 如果指針操作數指向一個數組對象的一個元素,並且該數組足夠大,[...]。 如果指針操作數和結果都指向同一個數組對象的元素,或者一個超過數組對象的最後一個元素,則評估不應產生溢出; ,否則,行爲是未定義的。
即,如果結果指針不會在同一陣列中位於或一個過去的結束,或者如果它確實而是由溢出這樣做了,行爲是未定義的。
但是,重點是,它不給我不確定的行爲。它的行爲完全像-1一樣。這讓我感到驚訝。 – Jay 2010-04-05 13:12:07
@Jay,說行爲不明確意味着任何事情都可能發生,包括你總是會得到同樣的行爲。這並不一定意味着你會遇到段錯誤。在具有32位無符號整數的64位平臺上,您可能會得到不同的行爲。 – 2010-04-05 13:16:13
我認爲右操作數被轉換爲ptrdiff_t類型,這似乎是簽名。
所以,uiVal是一個無符號整型?也許你可以發佈更多的代碼,而不是讓我假設。如果uiVal未經簽名,它如何爲-1? – WhirlWind 2010-04-05 12:58:31
對不起。編輯我的帖子。希望現在好了。如果你覺得它可以進一步編輯,請隨時這樣做。謝謝! – Jay 2010-04-05 13:05:24