首先,讓我強調一下,這個問題在本質上是legalistic。我是而不是問實際上,下面的程序是否可以用於實際實現,我問根據對ISO-9899標準的最嚴格的法律解釋是否合法(:=不產生未定義的行爲) 1999年和2011年)。指針爲整數並且再次返回
問題是,是否允許將指針轉換爲整數,對該整數執行一些算術運算,將其返回到相同的值,然後將該整數轉換回指針。
那麼,下面的程序是否合法(就是說它不會產生未定義的行爲)?
#include <stdint.h>
#include <stdio.h>
int
main(void)
{
int answer = 42; void *ptr;
uintptr_t deepthought;
ptr = &answer;
deepthought = (uintptr_t)ptr;
ptr = 0;
deepthought ^= 0xdeadbeef;
printf("I'm thinking about it...\n");
deepthought ^= 0xdeadbeef;
ptr = (void *)deepthought;
printf("The answer is: %d\n", *((int *)ptr));
return 0;
}
同樣,我知道這個代碼在任何真實的系統上都不會造成困難。問題在於它是否符合C標準中的法律術語, ISO-9899:2011中的ISO-9899:1999 /§7.20.1.4中的§7.18.1.4,其中短語「無符號整數類型的屬性指向void
的任何有效指針都可以轉換爲此類型,然後轉換回指向void
,並且結果將與原始指針「相等:」不清楚「然後轉換回」是否允許進行中間算術計算。
爲了使這個問題有點不那麼理論化,這裏有一個原因是爲什麼人們可能希望這種處理被禁止。如果我們稍微改變這個例子,以便指針指向malloc
,而不是指向局部變量,並且如果它碰巧在具有(保守)垃圾收集器的實現上運行,則可以想象在因爲在那一刻,沒有任何東西指向那個區域的內存。因此,如果C標準使上述示例成爲非法的(例如,如果沒有任何東西可以寫入一直沒有合法指針值的指針),則這爲垃圾收集器的假設提供了合法的理由。
但我重複說,問題是關於C標準的解釋學,而不是關於任何實際或現實世界的結果。
在這樣的語義下,垃圾收集變得基本上是不可能的,除非有人願意永久地泄漏其地址可能已經暴露給外部世界的任何對象。 – supercat