constness cast undefined behaviour

后端 未结 2 1284
醉话见心
醉话见心 2021-01-25 19:43

Could the return cast (==>) give place to an undefined behavior? the idea of the code is very simple, iterate through an intrusive list (plist) and return the element if found.

相关标签:
2条回答
  • 2021-01-25 20:04

    Could the return cast (==>) give place to an undefined behavior?

    No. casting a (my_custom_type_t*) to (const my_custom_type_t*) does not cause UB.

    Neither does either of the below cause 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;
    

    Yet the following does invoke UB ...

    const my_custom_type_t* plist3;
    my_custom_type_t* obj3 = get_object_by_id(plist3, "x");
    
    // UB
    obj3->some_field = 3;
    

    To avoid this potential, write 2 functions, one being a wrapper of the other.

    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;
    }
    
    0 讨论(0)
  • 2021-01-25 20:18

    C specifies conversions from pointers to qualified-pointers, but not the other way around, C11 6.3.2.3/2:

    For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.

    However, C allows the following, C11 6.3.2.3/7:

    A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer.

    In plain English, any pointer type may be converted to any other pointer type and back. If there are no alignment issues with the pointer itself, such code is fine unless the pointer is converted to a non-compatible type and then de-referenced. A qualified-pointer-to-type is always a compatible type of pointer-to-type.

    (Note that this refers to pointers to object type - function pointers is a special case.)

    So whether this is UB or not really depends on where that pointer originally pointed. You invoke UB in the following case, C11 6.7.3/6:

    If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

    If the pointer originally pointed at a read-only location, you would invoke undefined behavior. But if it pointed at a non-const, allocated variable, it would be fine. For example, this code is fine and does not invoke undefined behavior:

    type t;
    type* p = (type*)(const type*)&t1;
    

    Otherwise, as someone pointed out in comments, several of the C standard library functions would be fundamentally broken, for example strstr.

    0 讨论(0)
提交回复
热议问题