想象我有這個C函數(在頭文件中的相應的原型)它是未定義行爲來拋棄函數參數的常量嗎?
void clearstring(const char *data) {
char *dst = (char *)data;
*dst = 0;
}
有沒有在上面的代碼中未定義行爲,鑄造const
走,或者是它只是一個非常不好的編程習慣?
假設有沒有const限定對象使用
char name[] = "pmg";
clearstring(name);
想象我有這個C函數(在頭文件中的相應的原型)它是未定義行爲來拋棄函數參數的常量嗎?
void clearstring(const char *data) {
char *dst = (char *)data;
*dst = 0;
}
有沒有在上面的代碼中未定義行爲,鑄造const
走,或者是它只是一個非常不好的編程習慣?
假設有沒有const限定對象使用
char name[] = "pmg";
clearstring(name);
的嘗試寫入*dst
是UB 如果調用者傳遞你指向一個const對象,或指向一個字符串。
但是,如果調用者向您傳遞指向實際上可變的數據的指針,則會定義行爲。創建指向可修改的const char*
char
不會使該不可變的char
。
所以:
char c;
clearstring(&c); // OK, sets c to 0
char *p = malloc(100);
if (p) {
clearstring(p); // OK, p now points to an empty string
free(p);
}
const char d = 0;
clearstring(&d); // UB
clearstring("foo"); // UB
也就是說,你的功能是非常不明智的,因爲它是那麼容易讓呼叫者引起UB。但實際上可以將其與定義的行爲一起使用。
考慮一個函數,如strstr
,如果給定一個指向包含字符串的對象的一部分的指針,並返回一個指向同一對象的可能不同部分的指針。如果該方法傳遞一個指向內存只讀區域的指針,它將返回一個指向內存只讀區域的指針;同樣,如果給它一個指向可寫區域的指針,它將返回一個指向可寫區域的指針。
當給定const char *
時,C無法讓函數返回const char *
,並且在給定普通char *
時返回普通char *
。爲了兼容strstr
在將const char *
的想法添加到語言之前工作,必須將const限定指針轉換爲非const限定指針。儘管確實如此,即使用戶代碼不能,庫函數strstr
也許有權做這樣的投射,但在用戶代碼中經常出現相同的模式,以至於禁止它是實際的。
如果演員陣容不是UB,我認爲它應該是:) – pmg 2012-01-31 11:55:28
你當然有你的腳在霰彈槍的景點! – 2012-01-31 11:57:56
@pmg:如果轉換本身是UB,那麼語言允許的話就沒有什麼意義了 - 編譯器很容易檢測到const已經被添加到了轉換中,就像它檢測到'char * dst = data;'是非法的。顯然有一些沒有意義的事情是由於歷史原因標準允許的,但我聲稱這不是其中之一:-) – 2012-01-31 12:08:30