在 5/4/21 2:48 AM, Martin Storsjö 写道:

Sure. However in practice, with e.g. code like this:

typedef void (*fp)(void);
_Atomic fp ptr1 = ((void(*)(void))0);
_Atomic fp ptr2 = ((void*)0);

Clang accepts ptr1 but errors out on ptr2: https://gcc.godbolt.org/z/3YW6EsGP4


It looks like a bug. As per C standard (N2176, ISO/IEC 9899:2017):

    ```
    6.3.2.3 Pointers
3 An integer constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. 67) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
    ```

So `(void*)0` is also a /null pointer constant/ and should be implicitly convertible to any pointer, including a function pointer.

1. This is not true in C++. C++ does not allow the latter.
2. `(void*)1` is not implicitly convertible to function pointers; however due to the nature of `void*`, it is implicitly convertible to other object pointers such as `int*`.



In practice it shouldn't really matter, because as Jacek points out, we should be able to do without the atomics just fine in practice here.


I think I have to disagree on this. Just because something works 'in practice' doesn't mean it is correct in principle. The atomic load-store pair is essential to prevent races in case of multiple threads calling this function concurrently. One may argue that such races are harmless, but they are still undefined behavior, and could cause faults if thread sanitizer is involved.


--
Best regards,
Liu Hao

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to