Assigning pointers to atomic type to pointers to non atomic type The 2019 Stack Overflow Developer Survey Results Are InWhere is the lock for a std::atomic?Casting pointers to _Atomic pointers and _Atomic sizesHow do function pointers in C work?Are these compatible function types in C?Pointer to qualified and non-qualified type representationtechnical legality of incompatible pointer assignmentsDangerous pointer cast results in loss of const qualificationIs this behavior of clang standard compliant?How to understand the conversion rule when a “pointer to an object type” compares for eqality with a “pointer to a void”?Why are structs not allowed in equality expressions in C?What made i = i++ + 1; legal in C++17?Function without prototype called with non-compatible type

If the Wish spell is used to duplicate the effect of Simulacrum, are existing duplicates destroyed?

Does duplicating a spell with Wish count as casting that spell?

Spanish for "widget"

The difference between dialogue marks

Is it possible for the two major parties in the UK to form a coalition with each other instead of a much smaller party?

How are circuits which use complex ICs normally simulated?

Inline version of a function returns different value than non-inline version

Where to refill my bottle in India?

Does a dangling wire really electrocute me if I'm standing in water?

Are USB sockets on wall outlets live all the time, even when the switch is off?

Why Did Howard Stark Use All The Vibranium They Had On A Prototype Shield?

Springs with some finite mass

Extreme, unacceptable situation and I can't attend work tomorrow morning

What does Linus Torvalds mean when he says that Git "never ever" tracks a file?

Access elements in std::string where positon of string is greater than its size

A poker game description that does not feel gimmicky

If a poisoned arrow's piercing damage is reduced to 0, do you still get poisoned?

How can I create a character who can assume the widest possible range of creature sizes?

How to create dashed lines/arrows in Illustrator

Is bread bad for ducks?

How to make payment on the internet without leaving a money trail?

How to answer pointed "are you quitting" questioning when I don't want them to suspect

What do the Banks children have against barley water?

I looked up a future colleague on LinkedIn before I started a job. I told my colleague about it and he seemed surprised. Should I apologize?



Assigning pointers to atomic type to pointers to non atomic type



The 2019 Stack Overflow Developer Survey Results Are InWhere is the lock for a std::atomic?Casting pointers to _Atomic pointers and _Atomic sizesHow do function pointers in C work?Are these compatible function types in C?Pointer to qualified and non-qualified type representationtechnical legality of incompatible pointer assignmentsDangerous pointer cast results in loss of const qualificationIs this behavior of clang standard compliant?How to understand the conversion rule when a “pointer to an object type” compares for eqality with a “pointer to a void”?Why are structs not allowed in equality expressions in C?What made i = i++ + 1; legal in C++17?Function without prototype called with non-compatible type



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








10















Is the behavior of this code well-defined?



#include <stdatomic.h>

const int test = 42;
const int * _Atomic atomic_int_ptr;
atomic_init(&atomic_int_ptr, &test);
const int ** int_ptr_ptr = &atomic_int_ptr;
printf("int = %dn", **int_ptr_ptr); //prints int = 42



I assigned a pointer to atomic type to a pointer to non-atomic type (the types are the same). Here are my thoughts of this example:



The Standard explicitly specify distinction of const, volatile and restrict qualifiers from the _Atomic qualifier 6.2.5(p27):




this Standard explicitly uses the phrase ‘‘atomic, qualified or
unqualified type’’ whenever the atomic version of a type is permitted
along with the other qualified versions of a type. The phrase
‘‘qualified or unqualified type’’, without specific mention of atomic,
does not include the atomic types.




Also the compatibility of qualified types is defined as 6.7.3(p10):




For two qualified types to be compatible, both shall have the
identically qualified versionof a compatible type; the order of
type qualifiers within a list of specifiers or qualifiers does
not affect the specified type.




Combining the quotes cited above I concluded that atomic and non-atomic types are compatible types. So, applying the rule of simple assigning 6.5.16.1(p1) (emp. mine):




the left operand has atomic, qualified, or unqualified pointer
type, and (considering the type the left operand would have
after lvalue conversion) both operands are pointers to qualified
or unqualified versions of compatible types, and the type pointed to by
the left has all the qualifiers of the type pointed to by the right;




So I concluded that the behavior is well defined (even in spite of assigning atomic type to a non-atomic type).



The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.










share|improve this question






























    10















    Is the behavior of this code well-defined?



    #include <stdatomic.h>

    const int test = 42;
    const int * _Atomic atomic_int_ptr;
    atomic_init(&atomic_int_ptr, &test);
    const int ** int_ptr_ptr = &atomic_int_ptr;
    printf("int = %dn", **int_ptr_ptr); //prints int = 42



    I assigned a pointer to atomic type to a pointer to non-atomic type (the types are the same). Here are my thoughts of this example:



    The Standard explicitly specify distinction of const, volatile and restrict qualifiers from the _Atomic qualifier 6.2.5(p27):




    this Standard explicitly uses the phrase ‘‘atomic, qualified or
    unqualified type’’ whenever the atomic version of a type is permitted
    along with the other qualified versions of a type. The phrase
    ‘‘qualified or unqualified type’’, without specific mention of atomic,
    does not include the atomic types.




    Also the compatibility of qualified types is defined as 6.7.3(p10):




    For two qualified types to be compatible, both shall have the
    identically qualified versionof a compatible type; the order of
    type qualifiers within a list of specifiers or qualifiers does
    not affect the specified type.




    Combining the quotes cited above I concluded that atomic and non-atomic types are compatible types. So, applying the rule of simple assigning 6.5.16.1(p1) (emp. mine):




    the left operand has atomic, qualified, or unqualified pointer
    type, and (considering the type the left operand would have
    after lvalue conversion) both operands are pointers to qualified
    or unqualified versions of compatible types, and the type pointed to by
    the left has all the qualifiers of the type pointed to by the right;




    So I concluded that the behavior is well defined (even in spite of assigning atomic type to a non-atomic type).



    The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.










    share|improve this question


























      10












      10








      10


      1






      Is the behavior of this code well-defined?



      #include <stdatomic.h>

      const int test = 42;
      const int * _Atomic atomic_int_ptr;
      atomic_init(&atomic_int_ptr, &test);
      const int ** int_ptr_ptr = &atomic_int_ptr;
      printf("int = %dn", **int_ptr_ptr); //prints int = 42



      I assigned a pointer to atomic type to a pointer to non-atomic type (the types are the same). Here are my thoughts of this example:



      The Standard explicitly specify distinction of const, volatile and restrict qualifiers from the _Atomic qualifier 6.2.5(p27):




      this Standard explicitly uses the phrase ‘‘atomic, qualified or
      unqualified type’’ whenever the atomic version of a type is permitted
      along with the other qualified versions of a type. The phrase
      ‘‘qualified or unqualified type’’, without specific mention of atomic,
      does not include the atomic types.




      Also the compatibility of qualified types is defined as 6.7.3(p10):




      For two qualified types to be compatible, both shall have the
      identically qualified versionof a compatible type; the order of
      type qualifiers within a list of specifiers or qualifiers does
      not affect the specified type.




      Combining the quotes cited above I concluded that atomic and non-atomic types are compatible types. So, applying the rule of simple assigning 6.5.16.1(p1) (emp. mine):




      the left operand has atomic, qualified, or unqualified pointer
      type, and (considering the type the left operand would have
      after lvalue conversion) both operands are pointers to qualified
      or unqualified versions of compatible types, and the type pointed to by
      the left has all the qualifiers of the type pointed to by the right;




      So I concluded that the behavior is well defined (even in spite of assigning atomic type to a non-atomic type).



      The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.










      share|improve this question
















      Is the behavior of this code well-defined?



      #include <stdatomic.h>

      const int test = 42;
      const int * _Atomic atomic_int_ptr;
      atomic_init(&atomic_int_ptr, &test);
      const int ** int_ptr_ptr = &atomic_int_ptr;
      printf("int = %dn", **int_ptr_ptr); //prints int = 42



      I assigned a pointer to atomic type to a pointer to non-atomic type (the types are the same). Here are my thoughts of this example:



      The Standard explicitly specify distinction of const, volatile and restrict qualifiers from the _Atomic qualifier 6.2.5(p27):




      this Standard explicitly uses the phrase ‘‘atomic, qualified or
      unqualified type’’ whenever the atomic version of a type is permitted
      along with the other qualified versions of a type. The phrase
      ‘‘qualified or unqualified type’’, without specific mention of atomic,
      does not include the atomic types.




      Also the compatibility of qualified types is defined as 6.7.3(p10):




      For two qualified types to be compatible, both shall have the
      identically qualified versionof a compatible type; the order of
      type qualifiers within a list of specifiers or qualifiers does
      not affect the specified type.




      Combining the quotes cited above I concluded that atomic and non-atomic types are compatible types. So, applying the rule of simple assigning 6.5.16.1(p1) (emp. mine):




      the left operand has atomic, qualified, or unqualified pointer
      type, and (considering the type the left operand would have
      after lvalue conversion) both operands are pointers to qualified
      or unqualified versions of compatible types, and the type pointed to by
      the left has all the qualifiers of the type pointed to by the right;




      So I concluded that the behavior is well defined (even in spite of assigning atomic type to a non-atomic type).



      The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.







      c concurrency language-lawyer c11 stdatomic






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 6 at 8:07









      Peter Cordes

      134k18203342




      134k18203342










      asked Apr 6 at 8:03









      Some NameSome Name

      1,782418




      1,782418






















          2 Answers
          2






          active

          oldest

          votes


















          8














          6.2.5p27:




          Further, there is the _Atomic qualifier. The presence of the _Atomic
          qualifier designates an atomic type. The size, representation, and
          alignment of an atomic type need not be the same as those of the
          corresponding unqualified type. Therefore, this Standard explicitly
          uses the phrase ''atomic, qualified or unqualified type'' whenever the
          atomic version of a type is permitted along with the other qualified
          versions of a type. The phrase ''qualified or unqualified type'',
          without specific mention of atomic, does not include the atomic types.




          I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.






          share|improve this answer






























            6














            C11 allows _Atomic T to have a different size and layout than T, e.g. if it's not lock-free. (See @PSkocik's answer).



            For example, the implementation could choose to put a mutex inside each atomic object, and put it first. (Most implementations instead use the address as an index into a table of locks: Where is the lock for a std::atomic? instead of bloating each instance of an _Atomic or std::atomic<T> object that isn't guaranteed lock-free at compile time).



            Therefore _Atomic T* is not compatible with T* even in a single-threaded program.



            Merely assigning a pointer might not be UB (sorry I didn't put on my language lawyer hat), but dereferencing certainly can be.



            I'm not sure if it's strictly UB on implementations where _Atomic T and T do share the same layout and alignment. Probably it violates strict aliasing, if _Atomic T and T are considered different types regardless of whether or not they share the same layout.




            alignof(T) might be different from alignof(_Atomic T), but other than an intentionally perverse implementation (Deathstation 9000), _Atomic T will be at least as aligned as plain T, so that's not an issue for casting pointers to objects that already exist. An object that's more aligned than it needs to be is not a problem, just a possible missed-optimization if it stops a compiler from using a single wider load.



            Fun fact: creating an under-aligned pointer is UB in ISO C, even without dereference. (Most implementations don't complain, and Intel's _mm_loadu_si128 intrinsic even requires compilers to support doing so.)




            In practice on real implementations, _Atomic T* and T* use the same layout / object representation and alignof(_Atomic T) >= alignof(T). A single-threaded or mutex-guarded part of a program could do non-atomic access to an _Atomic object, if you can work around the strict-aliasing UB. Maybe with memcpy.



            On real implementations, _Atomic may increase the alignment requirement, e.g. a struct int a,b; on most ABIs for most 64-bit ISAs would typically only have 4-byte alignment (max of the members), but _Atomic would give it natural alignment = 8 to allow loading/storing it with a single aligned 64-bit load/store. This of course doesn't change the layout or alignment of the members relative to the start of the object, just the alignment of the object as a whole.





            The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.




            No, that reasoning is flawed.



            atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. In the C abstract machine, they both do an atomic store with memory_order_seq_cst.



            You can also see this from looking at the code-gen for real compilers on any ISA; e.g. x86 compilers will use an xchg instruction, or mov+mfence. Similarly, shared_var++ compiles to an atomic RMW (with mo_seq_cst).



            IDK why there's an atomic_store generic function. Maybe just for contrast / consistency with atomic_store_explicit, which lets you do atomic_store_explicit(&shared_var, 1, memory_order_release) or memory_order_relaxed to do a release or relaxed store instead of sequential-release. (On x86, just a plain store. Or on weakly-ordered ISAs, some fencing but not a full barrier.)




            For types that are lock-free, where the object representation of _Atomic T and T are identical, there's no problem in practice accessing an atomic object through a non-atomic pointer in a single-threaded program. I suspect it's still UB, though.



            C++20 is planning to introduce std::atomic_ref<T> which will let you do atomic operations on a non-atomic variable. (With no UB as long as no threads are potentially doing non-atomic access to it during the time window of being written.) This is basically a wrapper around the __atomic_* builtins in GCC for example, that std::atomic<T> is implemented on top of.



            (This presents some problems, like if atomic<T> needs more alignment than T, e.g. for long long or double on i386 System V. Or a struct of 2x int on most 64-bit ISAs. You should use alignas(_Atomic T) T foo when declaring non-atomic objects you want to be able to do atomic operations on.)



            Anyway, I'm not aware of any standards-compliant way to do similar things in portable ISO C11, but it's worth mentioning that real C compilers very much do support doing atomic operations on objects declared without _Atomic. But only using stuff like GNU C atomic builtins.:



            See Casting pointers to _Atomic pointers and _Atomic sizes : apparently casting a T* to _Atomic T* is not recommended even in GNU C. Although we don't have a definitive answer that it's actually UB.






            share|improve this answer

























            • You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

              – Some Name
              Apr 6 at 8:46







            • 1





              @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

              – Peter Cordes
              Apr 6 at 8:50







            • 2





              "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

              – PSkocik
              Apr 6 at 8:52











            • Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

              – Some Name
              Apr 6 at 9:00







            • 1





              @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

              – Peter Cordes
              Apr 6 at 9:16












            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55547081%2fassigning-pointers-to-atomic-type-to-pointers-to-non-atomic-type%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            8














            6.2.5p27:




            Further, there is the _Atomic qualifier. The presence of the _Atomic
            qualifier designates an atomic type. The size, representation, and
            alignment of an atomic type need not be the same as those of the
            corresponding unqualified type. Therefore, this Standard explicitly
            uses the phrase ''atomic, qualified or unqualified type'' whenever the
            atomic version of a type is permitted along with the other qualified
            versions of a type. The phrase ''qualified or unqualified type'',
            without specific mention of atomic, does not include the atomic types.




            I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.






            share|improve this answer



























              8














              6.2.5p27:




              Further, there is the _Atomic qualifier. The presence of the _Atomic
              qualifier designates an atomic type. The size, representation, and
              alignment of an atomic type need not be the same as those of the
              corresponding unqualified type. Therefore, this Standard explicitly
              uses the phrase ''atomic, qualified or unqualified type'' whenever the
              atomic version of a type is permitted along with the other qualified
              versions of a type. The phrase ''qualified or unqualified type'',
              without specific mention of atomic, does not include the atomic types.




              I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.






              share|improve this answer

























                8












                8








                8







                6.2.5p27:




                Further, there is the _Atomic qualifier. The presence of the _Atomic
                qualifier designates an atomic type. The size, representation, and
                alignment of an atomic type need not be the same as those of the
                corresponding unqualified type. Therefore, this Standard explicitly
                uses the phrase ''atomic, qualified or unqualified type'' whenever the
                atomic version of a type is permitted along with the other qualified
                versions of a type. The phrase ''qualified or unqualified type'',
                without specific mention of atomic, does not include the atomic types.




                I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.






                share|improve this answer













                6.2.5p27:




                Further, there is the _Atomic qualifier. The presence of the _Atomic
                qualifier designates an atomic type. The size, representation, and
                alignment of an atomic type need not be the same as those of the
                corresponding unqualified type. Therefore, this Standard explicitly
                uses the phrase ''atomic, qualified or unqualified type'' whenever the
                atomic version of a type is permitted along with the other qualified
                versions of a type. The phrase ''qualified or unqualified type'',
                without specific mention of atomic, does not include the atomic types.




                I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Apr 6 at 8:37









                PSkocikPSkocik

                35.1k65579




                35.1k65579























                    6














                    C11 allows _Atomic T to have a different size and layout than T, e.g. if it's not lock-free. (See @PSkocik's answer).



                    For example, the implementation could choose to put a mutex inside each atomic object, and put it first. (Most implementations instead use the address as an index into a table of locks: Where is the lock for a std::atomic? instead of bloating each instance of an _Atomic or std::atomic<T> object that isn't guaranteed lock-free at compile time).



                    Therefore _Atomic T* is not compatible with T* even in a single-threaded program.



                    Merely assigning a pointer might not be UB (sorry I didn't put on my language lawyer hat), but dereferencing certainly can be.



                    I'm not sure if it's strictly UB on implementations where _Atomic T and T do share the same layout and alignment. Probably it violates strict aliasing, if _Atomic T and T are considered different types regardless of whether or not they share the same layout.




                    alignof(T) might be different from alignof(_Atomic T), but other than an intentionally perverse implementation (Deathstation 9000), _Atomic T will be at least as aligned as plain T, so that's not an issue for casting pointers to objects that already exist. An object that's more aligned than it needs to be is not a problem, just a possible missed-optimization if it stops a compiler from using a single wider load.



                    Fun fact: creating an under-aligned pointer is UB in ISO C, even without dereference. (Most implementations don't complain, and Intel's _mm_loadu_si128 intrinsic even requires compilers to support doing so.)




                    In practice on real implementations, _Atomic T* and T* use the same layout / object representation and alignof(_Atomic T) >= alignof(T). A single-threaded or mutex-guarded part of a program could do non-atomic access to an _Atomic object, if you can work around the strict-aliasing UB. Maybe with memcpy.



                    On real implementations, _Atomic may increase the alignment requirement, e.g. a struct int a,b; on most ABIs for most 64-bit ISAs would typically only have 4-byte alignment (max of the members), but _Atomic would give it natural alignment = 8 to allow loading/storing it with a single aligned 64-bit load/store. This of course doesn't change the layout or alignment of the members relative to the start of the object, just the alignment of the object as a whole.





                    The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.




                    No, that reasoning is flawed.



                    atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. In the C abstract machine, they both do an atomic store with memory_order_seq_cst.



                    You can also see this from looking at the code-gen for real compilers on any ISA; e.g. x86 compilers will use an xchg instruction, or mov+mfence. Similarly, shared_var++ compiles to an atomic RMW (with mo_seq_cst).



                    IDK why there's an atomic_store generic function. Maybe just for contrast / consistency with atomic_store_explicit, which lets you do atomic_store_explicit(&shared_var, 1, memory_order_release) or memory_order_relaxed to do a release or relaxed store instead of sequential-release. (On x86, just a plain store. Or on weakly-ordered ISAs, some fencing but not a full barrier.)




                    For types that are lock-free, where the object representation of _Atomic T and T are identical, there's no problem in practice accessing an atomic object through a non-atomic pointer in a single-threaded program. I suspect it's still UB, though.



                    C++20 is planning to introduce std::atomic_ref<T> which will let you do atomic operations on a non-atomic variable. (With no UB as long as no threads are potentially doing non-atomic access to it during the time window of being written.) This is basically a wrapper around the __atomic_* builtins in GCC for example, that std::atomic<T> is implemented on top of.



                    (This presents some problems, like if atomic<T> needs more alignment than T, e.g. for long long or double on i386 System V. Or a struct of 2x int on most 64-bit ISAs. You should use alignas(_Atomic T) T foo when declaring non-atomic objects you want to be able to do atomic operations on.)



                    Anyway, I'm not aware of any standards-compliant way to do similar things in portable ISO C11, but it's worth mentioning that real C compilers very much do support doing atomic operations on objects declared without _Atomic. But only using stuff like GNU C atomic builtins.:



                    See Casting pointers to _Atomic pointers and _Atomic sizes : apparently casting a T* to _Atomic T* is not recommended even in GNU C. Although we don't have a definitive answer that it's actually UB.






                    share|improve this answer

























                    • You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                      – Some Name
                      Apr 6 at 8:46







                    • 1





                      @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                      – Peter Cordes
                      Apr 6 at 8:50







                    • 2





                      "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                      – PSkocik
                      Apr 6 at 8:52











                    • Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                      – Some Name
                      Apr 6 at 9:00







                    • 1





                      @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                      – Peter Cordes
                      Apr 6 at 9:16
















                    6














                    C11 allows _Atomic T to have a different size and layout than T, e.g. if it's not lock-free. (See @PSkocik's answer).



                    For example, the implementation could choose to put a mutex inside each atomic object, and put it first. (Most implementations instead use the address as an index into a table of locks: Where is the lock for a std::atomic? instead of bloating each instance of an _Atomic or std::atomic<T> object that isn't guaranteed lock-free at compile time).



                    Therefore _Atomic T* is not compatible with T* even in a single-threaded program.



                    Merely assigning a pointer might not be UB (sorry I didn't put on my language lawyer hat), but dereferencing certainly can be.



                    I'm not sure if it's strictly UB on implementations where _Atomic T and T do share the same layout and alignment. Probably it violates strict aliasing, if _Atomic T and T are considered different types regardless of whether or not they share the same layout.




                    alignof(T) might be different from alignof(_Atomic T), but other than an intentionally perverse implementation (Deathstation 9000), _Atomic T will be at least as aligned as plain T, so that's not an issue for casting pointers to objects that already exist. An object that's more aligned than it needs to be is not a problem, just a possible missed-optimization if it stops a compiler from using a single wider load.



                    Fun fact: creating an under-aligned pointer is UB in ISO C, even without dereference. (Most implementations don't complain, and Intel's _mm_loadu_si128 intrinsic even requires compilers to support doing so.)




                    In practice on real implementations, _Atomic T* and T* use the same layout / object representation and alignof(_Atomic T) >= alignof(T). A single-threaded or mutex-guarded part of a program could do non-atomic access to an _Atomic object, if you can work around the strict-aliasing UB. Maybe with memcpy.



                    On real implementations, _Atomic may increase the alignment requirement, e.g. a struct int a,b; on most ABIs for most 64-bit ISAs would typically only have 4-byte alignment (max of the members), but _Atomic would give it natural alignment = 8 to allow loading/storing it with a single aligned 64-bit load/store. This of course doesn't change the layout or alignment of the members relative to the start of the object, just the alignment of the object as a whole.





                    The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.




                    No, that reasoning is flawed.



                    atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. In the C abstract machine, they both do an atomic store with memory_order_seq_cst.



                    You can also see this from looking at the code-gen for real compilers on any ISA; e.g. x86 compilers will use an xchg instruction, or mov+mfence. Similarly, shared_var++ compiles to an atomic RMW (with mo_seq_cst).



                    IDK why there's an atomic_store generic function. Maybe just for contrast / consistency with atomic_store_explicit, which lets you do atomic_store_explicit(&shared_var, 1, memory_order_release) or memory_order_relaxed to do a release or relaxed store instead of sequential-release. (On x86, just a plain store. Or on weakly-ordered ISAs, some fencing but not a full barrier.)




                    For types that are lock-free, where the object representation of _Atomic T and T are identical, there's no problem in practice accessing an atomic object through a non-atomic pointer in a single-threaded program. I suspect it's still UB, though.



                    C++20 is planning to introduce std::atomic_ref<T> which will let you do atomic operations on a non-atomic variable. (With no UB as long as no threads are potentially doing non-atomic access to it during the time window of being written.) This is basically a wrapper around the __atomic_* builtins in GCC for example, that std::atomic<T> is implemented on top of.



                    (This presents some problems, like if atomic<T> needs more alignment than T, e.g. for long long or double on i386 System V. Or a struct of 2x int on most 64-bit ISAs. You should use alignas(_Atomic T) T foo when declaring non-atomic objects you want to be able to do atomic operations on.)



                    Anyway, I'm not aware of any standards-compliant way to do similar things in portable ISO C11, but it's worth mentioning that real C compilers very much do support doing atomic operations on objects declared without _Atomic. But only using stuff like GNU C atomic builtins.:



                    See Casting pointers to _Atomic pointers and _Atomic sizes : apparently casting a T* to _Atomic T* is not recommended even in GNU C. Although we don't have a definitive answer that it's actually UB.






                    share|improve this answer

























                    • You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                      – Some Name
                      Apr 6 at 8:46







                    • 1





                      @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                      – Peter Cordes
                      Apr 6 at 8:50







                    • 2





                      "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                      – PSkocik
                      Apr 6 at 8:52











                    • Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                      – Some Name
                      Apr 6 at 9:00







                    • 1





                      @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                      – Peter Cordes
                      Apr 6 at 9:16














                    6












                    6








                    6







                    C11 allows _Atomic T to have a different size and layout than T, e.g. if it's not lock-free. (See @PSkocik's answer).



                    For example, the implementation could choose to put a mutex inside each atomic object, and put it first. (Most implementations instead use the address as an index into a table of locks: Where is the lock for a std::atomic? instead of bloating each instance of an _Atomic or std::atomic<T> object that isn't guaranteed lock-free at compile time).



                    Therefore _Atomic T* is not compatible with T* even in a single-threaded program.



                    Merely assigning a pointer might not be UB (sorry I didn't put on my language lawyer hat), but dereferencing certainly can be.



                    I'm not sure if it's strictly UB on implementations where _Atomic T and T do share the same layout and alignment. Probably it violates strict aliasing, if _Atomic T and T are considered different types regardless of whether or not they share the same layout.




                    alignof(T) might be different from alignof(_Atomic T), but other than an intentionally perverse implementation (Deathstation 9000), _Atomic T will be at least as aligned as plain T, so that's not an issue for casting pointers to objects that already exist. An object that's more aligned than it needs to be is not a problem, just a possible missed-optimization if it stops a compiler from using a single wider load.



                    Fun fact: creating an under-aligned pointer is UB in ISO C, even without dereference. (Most implementations don't complain, and Intel's _mm_loadu_si128 intrinsic even requires compilers to support doing so.)




                    In practice on real implementations, _Atomic T* and T* use the same layout / object representation and alignof(_Atomic T) >= alignof(T). A single-threaded or mutex-guarded part of a program could do non-atomic access to an _Atomic object, if you can work around the strict-aliasing UB. Maybe with memcpy.



                    On real implementations, _Atomic may increase the alignment requirement, e.g. a struct int a,b; on most ABIs for most 64-bit ISAs would typically only have 4-byte alignment (max of the members), but _Atomic would give it natural alignment = 8 to allow loading/storing it with a single aligned 64-bit load/store. This of course doesn't change the layout or alignment of the members relative to the start of the object, just the alignment of the object as a whole.





                    The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.




                    No, that reasoning is flawed.



                    atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. In the C abstract machine, they both do an atomic store with memory_order_seq_cst.



                    You can also see this from looking at the code-gen for real compilers on any ISA; e.g. x86 compilers will use an xchg instruction, or mov+mfence. Similarly, shared_var++ compiles to an atomic RMW (with mo_seq_cst).



                    IDK why there's an atomic_store generic function. Maybe just for contrast / consistency with atomic_store_explicit, which lets you do atomic_store_explicit(&shared_var, 1, memory_order_release) or memory_order_relaxed to do a release or relaxed store instead of sequential-release. (On x86, just a plain store. Or on weakly-ordered ISAs, some fencing but not a full barrier.)




                    For types that are lock-free, where the object representation of _Atomic T and T are identical, there's no problem in practice accessing an atomic object through a non-atomic pointer in a single-threaded program. I suspect it's still UB, though.



                    C++20 is planning to introduce std::atomic_ref<T> which will let you do atomic operations on a non-atomic variable. (With no UB as long as no threads are potentially doing non-atomic access to it during the time window of being written.) This is basically a wrapper around the __atomic_* builtins in GCC for example, that std::atomic<T> is implemented on top of.



                    (This presents some problems, like if atomic<T> needs more alignment than T, e.g. for long long or double on i386 System V. Or a struct of 2x int on most 64-bit ISAs. You should use alignas(_Atomic T) T foo when declaring non-atomic objects you want to be able to do atomic operations on.)



                    Anyway, I'm not aware of any standards-compliant way to do similar things in portable ISO C11, but it's worth mentioning that real C compilers very much do support doing atomic operations on objects declared without _Atomic. But only using stuff like GNU C atomic builtins.:



                    See Casting pointers to _Atomic pointers and _Atomic sizes : apparently casting a T* to _Atomic T* is not recommended even in GNU C. Although we don't have a definitive answer that it's actually UB.






                    share|improve this answer















                    C11 allows _Atomic T to have a different size and layout than T, e.g. if it's not lock-free. (See @PSkocik's answer).



                    For example, the implementation could choose to put a mutex inside each atomic object, and put it first. (Most implementations instead use the address as an index into a table of locks: Where is the lock for a std::atomic? instead of bloating each instance of an _Atomic or std::atomic<T> object that isn't guaranteed lock-free at compile time).



                    Therefore _Atomic T* is not compatible with T* even in a single-threaded program.



                    Merely assigning a pointer might not be UB (sorry I didn't put on my language lawyer hat), but dereferencing certainly can be.



                    I'm not sure if it's strictly UB on implementations where _Atomic T and T do share the same layout and alignment. Probably it violates strict aliasing, if _Atomic T and T are considered different types regardless of whether or not they share the same layout.




                    alignof(T) might be different from alignof(_Atomic T), but other than an intentionally perverse implementation (Deathstation 9000), _Atomic T will be at least as aligned as plain T, so that's not an issue for casting pointers to objects that already exist. An object that's more aligned than it needs to be is not a problem, just a possible missed-optimization if it stops a compiler from using a single wider load.



                    Fun fact: creating an under-aligned pointer is UB in ISO C, even without dereference. (Most implementations don't complain, and Intel's _mm_loadu_si128 intrinsic even requires compilers to support doing so.)




                    In practice on real implementations, _Atomic T* and T* use the same layout / object representation and alignof(_Atomic T) >= alignof(T). A single-threaded or mutex-guarded part of a program could do non-atomic access to an _Atomic object, if you can work around the strict-aliasing UB. Maybe with memcpy.



                    On real implementations, _Atomic may increase the alignment requirement, e.g. a struct int a,b; on most ABIs for most 64-bit ISAs would typically only have 4-byte alignment (max of the members), but _Atomic would give it natural alignment = 8 to allow loading/storing it with a single aligned 64-bit load/store. This of course doesn't change the layout or alignment of the members relative to the start of the object, just the alignment of the object as a whole.





                    The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.




                    No, that reasoning is flawed.



                    atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. In the C abstract machine, they both do an atomic store with memory_order_seq_cst.



                    You can also see this from looking at the code-gen for real compilers on any ISA; e.g. x86 compilers will use an xchg instruction, or mov+mfence. Similarly, shared_var++ compiles to an atomic RMW (with mo_seq_cst).



                    IDK why there's an atomic_store generic function. Maybe just for contrast / consistency with atomic_store_explicit, which lets you do atomic_store_explicit(&shared_var, 1, memory_order_release) or memory_order_relaxed to do a release or relaxed store instead of sequential-release. (On x86, just a plain store. Or on weakly-ordered ISAs, some fencing but not a full barrier.)




                    For types that are lock-free, where the object representation of _Atomic T and T are identical, there's no problem in practice accessing an atomic object through a non-atomic pointer in a single-threaded program. I suspect it's still UB, though.



                    C++20 is planning to introduce std::atomic_ref<T> which will let you do atomic operations on a non-atomic variable. (With no UB as long as no threads are potentially doing non-atomic access to it during the time window of being written.) This is basically a wrapper around the __atomic_* builtins in GCC for example, that std::atomic<T> is implemented on top of.



                    (This presents some problems, like if atomic<T> needs more alignment than T, e.g. for long long or double on i386 System V. Or a struct of 2x int on most 64-bit ISAs. You should use alignas(_Atomic T) T foo when declaring non-atomic objects you want to be able to do atomic operations on.)



                    Anyway, I'm not aware of any standards-compliant way to do similar things in portable ISO C11, but it's worth mentioning that real C compilers very much do support doing atomic operations on objects declared without _Atomic. But only using stuff like GNU C atomic builtins.:



                    See Casting pointers to _Atomic pointers and _Atomic sizes : apparently casting a T* to _Atomic T* is not recommended even in GNU C. Although we don't have a definitive answer that it's actually UB.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited yesterday

























                    answered Apr 6 at 8:29









                    Peter CordesPeter Cordes

                    134k18203342




                    134k18203342












                    • You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                      – Some Name
                      Apr 6 at 8:46







                    • 1





                      @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                      – Peter Cordes
                      Apr 6 at 8:50







                    • 2





                      "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                      – PSkocik
                      Apr 6 at 8:52











                    • Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                      – Some Name
                      Apr 6 at 9:00







                    • 1





                      @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                      – Peter Cordes
                      Apr 6 at 9:16


















                    • You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                      – Some Name
                      Apr 6 at 8:46







                    • 1





                      @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                      – Peter Cordes
                      Apr 6 at 8:50







                    • 2





                      "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                      – PSkocik
                      Apr 6 at 8:52











                    • Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                      – Some Name
                      Apr 6 at 9:00







                    • 1





                      @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                      – Peter Cordes
                      Apr 6 at 9:16

















                    You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                    – Some Name
                    Apr 6 at 8:46






                    You mentioned that atomic_store(&my_atomic, 1) is equivalent to my_atomic=1;. I tried to test a similar thing and wrote the following function: void do_test_atomic(volatile _Atomic int *ptr, int val) atomic_store(ptr, val); compiled with -O3 gave the mfence at the end of the function. godbolt.org/z/vrFCLT . (I'm not closely familar with intel x86 memory model so please correct me if I'm wrong, but afaik stores go into store buffer first so we need a fence to avoid reordering caused by the store buffer forwarding which I think explaining the mfence).

                    – Some Name
                    Apr 6 at 8:46





                    1




                    1





                    @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                    – Peter Cordes
                    Apr 6 at 8:50






                    @SomeName: yes, I said that in my answer. But you didn't try compiling *ptr=val;, which was the whole point. godbolt.org/z/OdxR_h It compiles to identical assembly, mov+mfence with gcc, or a more efficient xchg [rdi], esi) with clang. On a weakly-ordered ISA, you'd get more fencing. Or AArch64 has a special instruction for a seqeuential-release store...

                    – Peter Cordes
                    Apr 6 at 8:50





                    2




                    2





                    "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                    – PSkocik
                    Apr 6 at 8:52





                    "unless GNU C defines the behaviour of casting a T* to _Atomic T*" I asked about that 2 weeks ago. Was told to use the builtins: stackoverflow.com/questions/55299525/…

                    – PSkocik
                    Apr 6 at 8:52













                    Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                    – Some Name
                    Apr 6 at 9:00






                    Now I see what you meant. Simple assigning like _Atomic int i; i = 42 also emits mfence. I also tried assigning to a non-atomic integer type which emitted a simple move. So (pardon my pedantic) instead of atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; I would say atomic_store(&my_atomic, 1) is equivalent to my_atomic=1; with GCC on x86.

                    – Some Name
                    Apr 6 at 9:00





                    1




                    1





                    @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                    – Peter Cordes
                    Apr 6 at 9:16






                    @SomeName: no, I meant it's equivalent in the C abstract machine. (And separately that you can check it with whatever compiler you want on whatever architecture you want, x86 being one example.) ISO C11 "overloads" assignment and various other operators for _Atomic types.

                    – Peter Cordes
                    Apr 6 at 9:16


















                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55547081%2fassigning-pointers-to-atomic-type-to-pointers-to-non-atomic-type%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Àrd-bhaile Cathair chruinne/Baile mòr cruinne | Artagailean ceangailte | Clàr-taice na seòladaireachd

                    Cannot Extend partition with GParted The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) 2019 Community Moderator Election ResultsCan't increase partition size with GParted?GParted doesn't recognize the unallocated space after my current partitionWhat is the best way to add unallocated space located before to Ubuntu 12.04 partition with GParted live?I can't figure out how to extend my Arch home partition into free spaceGparted Linux Mint 18.1 issueTrying to extend but swap partition is showing as Unknown in Gparted, shows proper from fdiskRearrange partitions in gparted to extend a partitionUnable to extend partition even though unallocated space is next to it using GPartedAllocate free space to root partitiongparted: how to merge unallocated space with a partition

                    대한민국 목차 국명 지리 역사 정치 국방 경제 사회 문화 국제 순위 관련 항목 각주 외부 링크 둘러보기 메뉴북위 37° 34′ 08″ 동경 126° 58′ 36″ / 북위 37.568889° 동경 126.976667°  / 37.568889; 126.976667ehThe Korean Repository문단을 편집문단을 편집추가해Clarkson PLC 사Report for Selected Countries and Subjects-Korea“Human Development Index and its components: P.198”“http://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EA%B5%AD%EA%B8%B0%EB%B2%95”"한국은 국제법상 한반도 유일 합법정부 아니다" - 오마이뉴스 모바일Report for Selected Countries and Subjects: South Korea격동의 역사와 함께한 조선일보 90년 : 조선일보 인수해 혁신시킨 신석우, 임시정부 때는 '대한민국' 국호(國號) 정해《우리가 몰랐던 우리 역사: 나라 이름의 비밀을 찾아가는 역사 여행》“남북 공식호칭 ‘남한’‘북한’으로 쓴다”“Corea 대 Korea, 누가 이긴 거야?”국내기후자료 - 한국[김대중 前 대통령 서거] 과감한 구조개혁 'DJ노믹스'로 최단기간 환란극복 :: 네이버 뉴스“이라크 "韓-쿠르드 유전개발 MOU 승인 안해"(종합)”“해외 우리국민 추방사례 43%가 일본”차기전차 K2'흑표'의 세계 최고 전력 분석, 쿠키뉴스 엄기영, 2007-03-02두산인프라, 헬기잡는 장갑차 'K21'...내년부터 공급, 고뉴스 이대준, 2008-10-30과거 내용 찾기mk 뉴스 - 구매력 기준으로 보면 한국 1인당 소득 3만弗과거 내용 찾기"The N-11: More Than an Acronym"Archived조선일보 최우석, 2008-11-01Global 500 2008: Countries - South Korea“몇년째 '시한폭탄'... 가계부채, 올해는 터질까”가구당 부채 5000만원 처음 넘어서“‘빚’으로 내몰리는 사회.. 위기의 가계대출”“[경제365] 공공부문 부채 급증…800조 육박”“"소득 양극화 다소 완화...불평등은 여전"”“공정사회·공생발전 한참 멀었네”iSuppli,08年2QのDRAMシェア・ランキングを発表(08/8/11)South Korea dominates shipbuilding industry | Stock Market News & Stocks to Watch from StraightStocks한국 자동차 생산, 3년 연속 세계 5위자동차수출 '현대-삼성 웃고 기아-대우-쌍용은 울고' 과거 내용 찾기동반성장위 창립 1주년 맞아Archived"중기적합 3개업종 합의 무시한 채 선정"李대통령, 사업 무분별 확장 소상공인 생계 위협 질타삼성-LG, 서민업종인 빵·분식사업 잇따라 철수상생은 뒷전…SSM ‘몸집 불리기’ 혈안Archived“경부고속도에 '아시안하이웨이' 표지판”'철의 실크로드' 앞서 '말(言)의 실크로드'부터, 프레시안 정창현, 2008-10-01“'서울 지하철은 안전한가?'”“서울시 “올해 안에 모든 지하철역 스크린도어 설치””“부산지하철 1,2호선 승강장 안전펜스 설치 완료”“전교조, 정부 노조 통계서 처음 빠져”“[Weekly BIZ] 도요타 '제로 이사회'가 리콜 사태 불러들였다”“S Korea slams high tuition costs”““정치가 여론 양극화 부채질… 합리주의 절실””“〈"`촛불집회'는 민주주의의 질적 변화 상징"〉”““촛불집회가 민주주의 왜곡 초래””“국민 65%, "한국 노사관계 대립적"”“한국 국가경쟁력 27위‥노사관계 '꼴찌'”“제대로 형성되지 않은 대한민국 이념지형”“[신년기획-갈등의 시대] 갈등지수 OECD 4위…사회적 손실 GDP 27% 무려 300조”“2012 총선-대선의 키워드는 '국민과 소통'”“한국 삶의 질 27위, 2000년과 2008년 연속 하위권 머물러”“[해피 코리아] 행복점수 68점…해외 평가선 '낙제점'”“한국 어린이·청소년 행복지수 3년 연속 OECD ‘꼴찌’”“한국 이혼율 OECD중 8위”“[통계청] 한국 이혼율 OECD 4위”“오피니언 [이렇게 생각한다] `부부의 날` 에 돌아본 이혼율 1위 한국”“Suicide Rates by Country, Global Health Observatory Data Repository.”“1. 또 다른 차별”“오피니언 [편집자에게] '왕따'와 '패거리 정치' 심리는 닮은꼴”“[미래한국리포트] 무한경쟁에 빠진 대한민국”“대학생 98% "외모가 경쟁력이라는 말 동의"”“특급호텔 웨딩·200만원대 유모차… "남보다 더…" 호화病, 고질병 됐다”“[스트레스 공화국] ① 경쟁사회, 스트레스 쌓인다”““매일 30여명 자살 한국, 의사보다 무속인에…””“"자살 부르는 '우울증', 환자 중 85% 치료 안 받아"”“정신병원을 가다”“대한민국도 ‘묻지마 범죄’,안전지대 아니다”“유엔 "학생 '성적 지향'에 따른 차별 금지하라"”“유엔아동권리위원회 보고서 및 번역본 원문”“고졸 성공스토리 담은 '제빵왕 김탁구' 드라마 나온다”“‘빛 좋은 개살구’ 고졸 취업…실습 대신 착취”원본 문서“정신건강, 사회적 편견부터 고쳐드립니다”‘소통’과 ‘행복’에 목 마른 사회가 잠들어 있던 ‘심리학’ 깨웠다“[포토] 사유리-곽금주 교수의 유쾌한 심리상담”“"올해 한국인 평균 영화관람횟수 세계 1위"(종합)”“[게임연중기획] 게임은 문화다-여가활동 1순위 게임”“영화속 ‘영어 지상주의’ …“왠지 씁쓸한데””“2월 `신문 부수 인증기관` 지정..방송법 후속작업”“무료신문 성장동력 ‘차별성’과 ‘갈등해소’”대한민국 국회 법률지식정보시스템"Pew Research Center's Religion & Public Life Project: South Korea"“amp;vwcd=MT_ZTITLE&path=인구·가구%20>%20인구총조사%20>%20인구부문%20>%20 총조사인구(2005)%20>%20전수부문&oper_YN=Y&item=&keyword=종교별%20인구& amp;lang_mode=kor&list_id= 2005년 통계청 인구 총조사”원본 문서“한국인이 좋아하는 취미와 운동 (2004-2009)”“한국인이 좋아하는 취미와 운동 (2004-2014)”Archived“한국, `부분적 언론자유국' 강등〈프리덤하우스〉”“국경없는기자회 "한국, 인터넷감시 대상국"”“한국, 조선산업 1위 유지(S. Korea Stays Top Shipbuilding Nation) RZD-Partner Portal”원본 문서“한국, 4년 만에 ‘선박건조 1위’”“옛 마산시,인터넷속도 세계 1위”“"한국 초고속 인터넷망 세계1위"”“인터넷·휴대폰 요금, 외국보다 훨씬 비싸”“한국 관세행정 6년 연속 세계 '1위'”“한국 교통사고 사망자 수 OECD 회원국 중 2위”“결핵 후진국' 한국, 환자가 급증한 이유는”“수술은 신중해야… 자칫하면 생명 위협”대한민국분류대한민국의 지도대한민국 정부대표 다국어포털대한민국 전자정부대한민국 국회한국방송공사about korea and information korea브리태니커 백과사전(한국편)론리플래닛의 정보(한국편)CIA의 세계 정보(한국편)마리암 부디아 (Mariam Budia),『한국: 하늘이 내린 한 폭의 그림』, 서울: 트랜스라틴 19호 (2012년 3월)대한민국ehehehehehehehehehehehehehehWorldCat132441370n791268020000 0001 2308 81034078029-6026373548cb11863345f(데이터)00573706ge128495