[英]Comparison and assignment between pointer and integer C
我對這兩個陳述有一個理論上的問題:
假設p
的指針整數和a
整數:
a) if(p==a){.....}
或if(p>a)
..
b) p=a
;
所有這些都是非法的, b
特別危險,但標准C如何考慮它們?
閱讀標准,我沒有發現它們是錯誤,未定義的行為,未指定的行為,違反約束,如果其中一個是合法的或其他的。
看着無數類似的問題,我還沒有找到解決方案。
一切都是非法的。 為了進行比較,雙方大多數可以轉換為普通類型,對於賦值,右側必須可以轉換為左側的類型,並且:
除了6.5.16.1的約束允許之外,涉及指針的轉換應通過顯式轉換來指定。
(6.5.4,3; 6.5.16.1描述了空指針常量,一些例外void
指針和_Bool
在分配的情況下)。
當您添加顯式轉換以將指針轉換為整數時,程序再次變為有效,您將從比較中獲得布爾值。 結果取決於實現。 在以整數存儲指針時,請務必使用uintptr_t
。
C11(n1570)§6.5.8[關系運算符] / 2:
約束
以下其中一項應持有:
- 兩個操作數都有實物類型 ; 要么
- 兩個操作數都是指向兼容對象類型的限定或非限定版本的指針 。
(實數類型表示整數類型,枚舉,實數浮點類型和char
(§6.2.5/ 17))
§6.5.9[平等運營商]
約束
以下其中一項應持有:
- 兩個操作數都有算術類型 ;
- 兩個操作數都是指向兼容類型的限定或非限定版本的指針 ;
- 一個操作數是指向對象類型的指針 ,另一個是指向合格或非限定版本的
void
的指針 ; 要么- 一個操作數是一個指針 ,另一個是空指針常量。
§6.5.16.1[簡單分配] / 1:
約束
以下其中一項應持有:
- 左操作數具有原子,限定或非限定算術類型 ,並且righ具有算術類型 ;
- 左操作數具有與右側類型兼容的結構或聯合類型的原子,限定或非限定版本;
- 左操作數具有原子,限定或非限定指針類型 ,並且(考慮左值操作數在左值轉換后將具有的類型)兩個操作數都是指向兼容類型的限定或非限定版本的指針 ,左側指向的類型具有全部右邊指出的那種限定詞;
- 左操作數具有原子,限定或非限定指針類型 ,並且(考慮左值操作數在左值轉換后將具有的類型)一個操作數是指向對象類型的指針 ,另一個是指向合格或非限定版本的指針
void
,左邊指向的類型具有右邊指向的所有類型的限定符;- 左操作數是一個原子,限定或非限定指針 ,右邊是一個空指針常量; 或左操作數具有類型為atomic,qualified或
_Bool
,右邊是指針 。
基本上,所有3個表達式都違反了表達式中設置的約束 。
違反約束意味着什么? 錯誤? 但是沒有地方說違反約束會導致翻譯失敗。 C標准似乎不是很清楚,但最接近的解釋是:
§4[符合性] / 2:
如果違反了出現在約束或運行時約束之外的“應該”或“不應該”的要求,則行為是不確定的。
但這談到了限制之外 ; 和§5.1.1.3[診斷] / 1:
如果預處理轉換單元或轉換單元包含違反任何語法規則或約束的情況 ,則符合要求的實現應生成至少一條診斷消息(以實現定義的方式標識),即使該行為也明確指定為未定義或實現 -定義。 在其他情況下不需要產生診斷消息。
因此編譯器至少需要生成一條消息(正如我們在gcc中看到的那樣),但沒有說明之后他們應該做什么。
本段后面的例子提到了這一點
例
實施應為翻譯單位發布診斷:
char i; int i;
因為在本國際標准中的措辭將構造的行為描述為約束錯誤並導致未定義的行為的情況下 ,應診斷約束錯誤。
和§6.7[聲明] / 3沒有明確提到違反約束將導致未定義的行為。
因此,我推斷出您的3個表達式都是未定義的行為,並伴有診斷消息 。
a)和b)都是約束違規。 C99 ,§6.5.8,§6.5.9和§6.5.16.1。
我不知道我是否真的在回答你的問題,但現在就去了。 關於a),你有一個比較,所以你基本上說的是“指針是否有內存地址a?”。 在b)你將指針指定給值a,這意味着你說它將指向內存地址“a”。 這里有一些提示:
p=&a
你的指針現在指向整數a的內存地址。
*p=a
指針指向的值采用a的值。
p=a
你的指針現在指向內存值a。
希望它有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.