返回强制转换(==>)是否会出现未定义的行为?代码的概念非常简单,遍历一个侵入式列表(plist)并返回元素(如果找到)。由于代码只迭代它不会更改列表所以我想将它作为const指针传递。
static my_custom_type_t* get_object_by_id(const my_custom_type_t* plist, const char *my_id)
{
const my_custom_type_t* obj = NULL;
for (obj = plist; obj && strncmp(obj->id, my_id, MAX_SIZE); obj = obj->next)
{
; //empty body
}
==> return ((my_custom_type_t*) obj);
}
当函数用于获取对象并将其用作const时:
const my_custom_type_t* obj = get_object_by_id(intrusive_list, some_id);
当函数用于获取对象并将其用作非const对象时:
my_custom_type_t* obj = get_object_by_id(intrusive_list, some_id);
答案 0 :(得分:2)
C指定从指针到限定指针的转换,但不是相反,C11 6.3.2.3/2:
对于任何限定符q,指向非q限定类型的指针可能是 转换为指向该类型的q限定版本的指针;该 存储在原始和转换指针中的值应进行比较 相等。
但是,C允许以下内容,C11 6.3.2.3/7:
指向对象类型的指针可以转换为指向a的指针 不同的对象类型。如果结果指针不正确 对于引用的类型,行为是未定义的。 否则,当再次转换回来时,结果应该相等 到原始指针。
简单来说,任何指针类型都可以转换为任何其他指针类型并返回。如果指针本身没有对齐问题,除非将指针转换为不兼容类型然后取消引用,否则这样的代码就可以了。限定指向类型的指针始终是指向类型指针的兼容类型。
(注意,这指的是指向对象类型的指针 - 函数指针是一种特殊情况。)
那么这是否是UB实际上取决于指针最初指向的位置。在以下情况下调用UB,C11 6.7.3 / 6:
如果尝试修改用a定义的对象 通过使用具有非const限定的左值的const限定类型 类型,行为未定义。
如果指针最初指向只读位置,则会调用未定义的行为。但如果它指向一个非const,已分配的变量,那就没问题了。例如,此代码很好,不会调用未定义的行为:
type t;
type* p = (type*)(const type*)&t1;
否则,正如有人在评论中指出的那样,几个C标准库函数将从根本上被打破,例如strstr
。
答案 1 :(得分:0)
返回强制转换(==>)是否会导致未定义的行为?
没有。将(my_custom_type_t*)
转换为(const my_custom_type_t*)
不会导致UB。
下列任何一项都不会导致UB
const my_custom_type_t* plist1;
const my_custom_type_t* obj1 = get_object_by_id(plist1, "x");
printf("%d\n", obj1->some_field);
my_custom_type_t* plist2;
my_custom_type_t* obj2 = get_object_by_id(plist2, "x");
obj2->some_field = 2;
然而以下 调用UB ...
const my_custom_type_t* plist3;
my_custom_type_t* obj3 = get_object_by_id(plist3, "x");
// UB
obj3->some_field = 3;
为避免这种可能性,编写2个函数,一个是另一个函数的包装器。
static const my_custom_type_t* get_object_by_id_const(
const my_custom_type_t* plist, const char *my_id) {
// as above in OP's post
return obj;
}
static my_custom_type_t* get_object_by_id_noconst(
my_custom_type_t* plist, const char *my_id) {
const my_custom_type_t* obj = get_object_by_id_const(plist, my_id);
return (my_custom_type_t*) obj;
}