[英]Copy “pointer to const” to “pointer to non const” via memcpy
const void *a = something;
void *b = a;
返回警告:
警告:初始化從指針目標類型中丟棄“const”限定符 [-Wdiscarded-qualifiers]
通過memcpy
將指向const
的指針復制到指向非const
的指針以避免警告是否安全(定義明確的行為)?
/* Linear search */
void *vector_lsearch(const void *key, const void *base, int (*comp)(const void *, const void *))
{
const struct vector *vector = CONST_VECTOR(base);
void *cast[1];
void *data;
/* Skip const to non const warning */
data = *(void **)memcpy(cast, &base, sizeof base);
for (size_t item = 0; item < vector->size; item++)
{
if (comp(data, key) == 0)
{
return data;
}
data = (unsigned char *)data + vector->szof;
}
return NULL;
}
該警告來自於將 const 限定符作為初始化的一部分。 只需添加顯式演員表也可以避免警告。
const void *a = something;
void *b = (void *)a;
該標准的第 6.5.4 節描述了對指針隱式轉換的約束:
涉及指針的轉換,除了 6.5.16.1 的約束允許的情況外,應通過顯式轉換來指定。
顯式轉換指針的唯一限制是:
指針類型不應轉換為任何浮點類型。 浮動類型不應轉換為任何指針類型。
第一條規則 6.5.16.1 的相關部分具有以下簡單分配規則:
左操作數具有原子、限定或非限定指針類型,並且(考慮左操作數在左值轉換后將具有的類型)兩個操作數都是指向兼容類型的限定或非限定版本的指針,並且左側指向的類型具有所有右邊指向的類型的限定符;
最后,關於限定符的第 6.7.3 節有:
如果嘗試通過使用具有非 const 限定類型的左值來修改使用 const 限定類型定義的 object,則行為未定義。
如果具有非 const 限定類型的左值可以訪問使用 const 限定類型定義的對象,那么這句話不會提供太多價值。 這表明您可以將 const void * 顯式轉換為 void * 並避免警告而不會引入未定義的行為,因為警告特別涉及通過簡單賦值對隱式轉換的無效使用,而不是一般反對丟棄 const 限定符。
復制指針是安全的。 潛在的安全問題是當您使用b
時。 由於它被聲明為指向非常量數據的指針,因此您可以通過指針進行賦值,例如*(int *b) = 1;
如果something
是常量數據,這將導致未定義的行為。
如果您使用void *
指針作為最終將指針傳遞給 function 的管道,該指針會將指針轉換回其原始類型(就像qsort()
使用其指針參數的方式一樣),您應該能夠忽略這個警告。 您會期望 function 將其轉換回指向const
的指針,而不是嘗試通過它進行分配。
我不認為有一種方法可以聲明一個可以用作 const 或非常量數據的管道的通用指針。 如果您將其聲明為非 const,則在為它分配 const 指針時會收到警告; 如果您將其聲明為 const,您將無法將其用於需要非常量指針的函數。
初始化void *b = a;
是無效的 C,它違反了簡單賦值規則 C17 6.5.16.1(初始化遵循賦值規則),其中規定為了使表達式有效:
...左側指向的類型具有右側指向的類型的所有限定符。
您可能希望使用-pedantic-errors
進行編譯以獲取錯誤而不是針對 C 語言違規的警告。
至於定義明確的行為——只要你使用正確類型的實際數據取消引用指針,它就是明確定義的行為,指針本身的類型並不重要。
我什至不明白你為什么需要轉換為void*
,因為你的回調格式是這樣的:
int (*comp)(const void *, const void *)
所以唯一的問題是外部 function 的返回類型,可以簡化為這樣的:
void* vector_lsearch (const void* key, const void* base, int (*comp)(const void*, const void*))
{
const struct vector* vector = CONST_VECTOR(base);
void* result = NULL;
unsigned char* data = (unsigned char*)base;
for (size_t i=0; i < vector->size; i++)
{
if (comp(&data[i*vector->szof], key) == 0)
{
result = data;
break;
}
}
return result;
}
CONST_VECTOR
是可疑的,聞起來像你在宏或什么后面隱藏一個演員?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.