[英]Is there a way to initialize a `const` `struct` using `const` variables?
我想在C99中創建一個struct
,該struct
封裝一個以空終止的字符串緩沖區以及實際的字符串長度:
typedef unsigned int uint_t;
typedef unsigned char uchar_t;
typedef struct {
uchar_t * buffer;
uint_t length; // excluding null-terminating character
} string_t;
但是,我在旋轉struct
成員的const
時遇到了一些困難。 具體來說,當我想使用一個接受這樣的const struct string_t
的const struct string_t
,並向其提供帶有const成員的初始化程序時,編譯器const struct string_t
大叫。
void show_string_internal(const string_t str) {
printf("%s", str.buffer);
}
void show_string(const uchar_t * buffer, uint_t length) {
const string_t str = // <== tricky assignment here
(const string_t){ buffer, length };
show_string_internal(str);
}
int main() {
uchar_t message[] = "Hello, world.";
show_string(message, sizeof(message) - 1);
return 0;
}
這會在GCC ...中的突出顯示的行上產生警告:
警告:初始化會從指針目標類型中丟棄“ const”限定符
...並在Visual Studio 2015中:
警告C4090:“正在初始化”:不同的“ const”限定詞
顯然,我在這里做錯了。 我發現解決此問題的唯一方法是聲明:
typedef struct {
const uchar_t * buffer;
const uint_t length;
} const_string_t;
但是現在我有兩種類型,而不是一種,所以我需要創建方便的方法來在兩種類型之間進行轉換,而且我正在創建聲明性糖而不是使用語言功能,因此代碼的可讀性較低。
所以我的問題是,正如標題所示:是否有一種方法可以為成員使用const
變量來初始化const
struct
? 是否有其他方法可以達到我希望達到的結果? 如果不是,為什么不這樣做(請提供對官方文件的引用)?
任何幫助,將不勝感激。
關於指針類型的常量應該從右到左讀取(而"const T * buffer"
”實際上是“指向常量內容的指針”,而不是“指向內容的常量指針”或“指向常量內容的常量指針”)。
因此,您將使用可變指針指向const char緩沖區,並將其用於結構的const版本(詢問具有可變字段的const結構-這是顯示警告的原因)。 如果您打算擺脫警告,則必須移動“ const”這樣的內容:
void show_string(char * const buffer, const int length) { // <== move const to the right of "*"
const string_t str = // <== tricky assignment here
(const string_t) {
buffer, length
};
show_string_internal(str);
}
如果您還打算自己使用const緩沖區,則必須重新定義string_t結構(或作為單獨的類型引入):
typedef struct {
const uchar_t * buffer; // <== add "const" here
uint_t length; // excluding null-terminating character
} string_t;
...
void show_string(const char * const buffer, const int length) { // two "const" clauses there
const string_t str = // <== tricky assignment here
(const string_t) {
buffer, length
};
show_string_internal(str);
}
希望這可以幫助。
問題不在結構級別。 問題在於使用char const*
初始化.buffer
( unsigned char*
)。 如果您使.buffer
char const*
,則即使不進行強制轉換也可以使用,盡管由於簽名不同,您仍然會收到-Wall
警告。
您的結構體具有聲明為uchar_t *buffer
的成員,並且您嘗試使用聲明為const char *buffer
的參數對其進行了初始化。 因此編譯器會抱怨,因為這樣會刪除 buffer
指向的內存的預設常數(這種違反是邏輯錯誤)。 根據您的需求/意願,您可以:
還請注意uchar_t
和char
可能不是同一類型...
正如其他人所寫的那樣,問題與const
類型限定符影響struct
聚合類型的方式有關。 所有的struct
成員值本身都是const
。 對於指針成員,這僅意味着您不能更改指針變量,使其指向其他任何位置,但是指針指向的任何內容仍然可變。 這類似於如果聲明一個int * const
變量將發生的情況。
似乎是在C99沒有辦法賦予const
的是所謂的聚合類型的部分間接(指針)類型的目標-ness。 因此,無法將關鍵字附加到struct
type變量以表示其指針成員應被視為指向const
類型的指針,例如int const *
。 僅在第6.7.3節(類型限定符)末尾的C99和C11標准中均以示例方式提及。
該答案是基於Yuval和PSkocik之間對Jean-BaptisteYunès的回答的對應關系而得出的。
這只是錯誤的常數:
typedef unsigned int uint_t; typedef unsigned char uchar_t;
使用正確的尺寸類型。 在C中是size_t
typedef struct {
const uchar_t * buffer;
size_t length; // excluding null-terminating character
} string_t;
void show_string(const uchar_t * buffer, size_t length) {
const string_t str = // <== tricky assignment here
(string_t){ buffer, length };
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.