我想定義一個結構:
struct error
{
int errno;
/* other information */
};
然后我希望我的代碼具有如下所示的錯誤路徑:
struct error my_error;
my_error.errno = errno;
/* set other fields on the error */
但是如果同一個翻譯單元包含#include <errno.h>, thenerrno通常是一個被其他東西替換的宏。
假設您實際上需要訪問errno該翻譯單元,因此您不能只是取消定義它,有沒有辦法仍然擁有該結構欄位名稱?
我不在乎是通過抑制特定令牌的擴展,還是通過某種方式獲得errno令牌由其他不會進一步擴展的宏擴展或任何方法生成。
最終這并不重要,我可以將欄位命名為其他名稱,error或者error_number取而代之。我只是不喜歡無法命名似乎最合適的名稱。
uj5u.com熱心網友回復:
因為你評論:
我想實作這樣的東西可能的源代碼......因為我認為
errno不言而喻是該領域最清晰和最佳的名稱,而且 C 不允許我為某事使用最合適的名稱是令人反感的。
覆寫作為語言一部分的通用識別符號通常是一個壞主意,因為它會使人們感到困惑。而且,當你忘記你做過這件事時,它會讓你自己感到困惑;所以在私人自己的專案中甚至不建議這樣做。
撰寫有意義的無錯誤代碼對人類來說已經是一項非常艱巨的任務。像這樣的技巧使事情更難理解。意義在編程中最重要!
然后,我不認為這errno是一個要求在其他地方使用的好名字:
- 由兩個縮寫部分組成:
err和no。 - 不使用常見的駝峰式
errNo - 好的選擇很容易/很明顯(例如
errorNumber) - 在我看到的例子中
struct error,不是struct err,所以看起來你不喜歡縮寫。err那么多
最后, iferrno是一個宏,這樣的行:my_error.errno = errno;,這是您想要這個的核心,永遠不可能,因為 CPP 將無法區分這兩個errnos。QED。
uj5u.com熱心網友回復:
如果為了訪問實際物件而禁止宏定義,或者程式定義了名稱為 errno 的識別符號,則行為未定義。
https://port70.net/~nsz/c/c11/n1570.html#7.5
uj5u.com熱心網友回復:
盡管 C 標準沒有明確禁止,但將errno其用作用戶定義物件的識別符號并不是一個好主意:
7.1.3 保留識別符號
每個標頭宣告或定義其相關子條款中列出的所有識別符號,并可選地宣告或定義其相關的未來庫方向子條款中列出的識別符號和始終保留用于任何用途或用作檔案范圍識別符號的識別符號。
— 由實作提供的所有可能保留的識別符號(包括在未來庫方向中列出的識別符號)都保留用于任何用途。沒有其他可能保留的識別符號被保留。
— 如果包含任何關聯的頭檔案,則保留以下任何子條款(包括未來的庫方向)中的每個宏名稱以供指定使用;除非另有明確說明(見 7.1.4)。
— 以下任何子條款(包括未來的庫方向)和 errno 中的所有具有外部鏈接的識別符號始終保留用作具有外部鏈接的識別符號。
— 在以下任何子條款(包括未來的庫方向)中列出的每個具有檔案范圍的識別符號都保留用作宏名稱和在同一名稱空間中作為具有檔案范圍的識別符號,如果包括其任何關聯的頭檔案。
此外,errno在7.5 錯誤<errno.h>中指定為定義為宏。
因此,如果您不包含<errno.h>或取消定義errno,您可以命名一個結構成員errno,但由于其他答案中解釋的原因,這可能是一個壞主意。
您不能用于my_error.errno = errno;設定結構成員,因為您必須errno未定義宏才能訪問成員。
這是一種可能但不推薦的方法:
#include <errno.h>
static inline int get_errno(void) { return errno; }
#undef errno
struct error {
int errno;
/* other information */
};
int myfunction(const char *filename, struct error *errorp) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
errorp->errno = get_errno();
return -1;
}
fclose(fp);
return 0;
}
編輯: C 標準實際上確實使上述未定義:
7.5 錯誤
<errno.h>[...]
如果為了訪問實際物件而禁止宏定義,或者程式定義了名稱為 的識別符號
errno,則行為未定義。
uj5u.com熱心網友回復:
您可以使用#undef取消定義前處理器宏,例如:
https ://ideone.com/le9aTz
所以#undef errno應該作業。
請注意,您當然不能使用errnoafter 的原始定義#undef。如果您的結構error是在您的一個頭檔案中定義的,則包括該頭檔案的任何檔案都將無法使用errno任何一個的原始定義。
總而言之,將成員變數重命名為不同的名稱可能會更好。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/473151.html
上一篇:C語言中的“物件”是什么?
下一篇:C中的外部/全域變數
