const void *a = something;
void *b = a;
返回警告:
警告:初始化会从指针目标中丢弃“ const”限定词 输入[-Wdiscarded-qualifiers]
通过const
将指向const
的指针复制到指向非memcpy
的指针是否安全(明确定义),以避免警告?
/* 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;
}
答案 0 :(得分:2)
该警告来自于在初始化过程中删除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限定类型的左值,行为未定义。
如果具有非const限定类型的,可以访问用const限定类型定义的对象的左值本身未定义,则该语句没有太大价值。这表明您可以将const void *显式地转换为void *并避免警告而不会引入未定义的行为,因为该警告专门涉及通过简单赋值而不是对const限定符的普遍反对而对隐式强制转换的无效使用。
答案 1 :(得分:2)
复制指针是安全的。潜在的安全问题是您使用b
时。由于已将其声明为指向非恒定数据的指针,因此您可以通过该指针进行赋值,例如*(int *b) = 1;
如果something
是常量数据,这将导致未定义的行为。
如果您将void *
指针用作管道,则最终会将指针传递给一个函数,该函数会将指针转换回其原始类型(例如qsort()
使用其指针参数的方式),您应该可以忽略此警告。您可能希望该函数将其转换回指向const
的指针,而不尝试通过它进行分配。
我不认为有一种方法可以声明可用于const或非const数据的通用指针的通用指针。如果将其声明为非const,则在为其指定const指针时会收到警告。如果将其声明为const,则无法将其用于需要非const指针的函数。
答案 2 :(得分:1)
初始化void *b = a;
不是有效的C,它违反了简单赋值规则C17 6.5.16.1(初始化遵循赋值规则),该表达式指出要使表达式有效:>
...左侧指向的类型具有右侧指向的所有类型的限定符。
您可能希望使用-pedantic-errors
进行编译,以获取错误而不是针对C语言违规的警告。
对于明确定义的行为-只要您使用正确的实际数据类型取消引用指针,它就是明确定义的行为,并且指针本身的类型无关紧要。
我什至都不明白为什么您需要转换为void*
,因为回调的格式是这样:
int (*comp)(const void *, const void *)
所以唯一的问题是外部函数的返回类型,可以将其简化为如下形式:
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
是可疑的,闻起来像是您在宏或其他内容后面隐藏了演员表吗?