Assigning pointers to atomic type to pointers to non atomic typeWhere 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 a centaur druid Wild Shapes into a Giant Elk, do their Charge features stack?

Why did the Germans forbid the possession of pet pigeons in Rostov-on-Don in 1941?

Manga about a female worker who got dragged into another world together with this high school girl and she was just told she's not needed anymore

What does 'script /dev/null' do?

Landlord wants to switch my lease to a "Land contract" to "get back at the city"

How to deal with fear of taking dependencies

Why is my log file so massive? 22gb. I am running log backups

Where else does the Shulchan Aruch quote an authority by name?

Could a US political party gain complete control over the government by removing checks & balances?

I’m planning on buying a laser printer but concerned about the life cycle of toner in the machine

Why do UK politicians seemingly ignore opinion polls on Brexit?

COUNT(*) or MAX(id) - which is faster?

Ideas for 3rd eye abilities

I see my dog run

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

How is it possible for user's password to be changed after storage was encrypted? (on OS X, Android)

Unbreakable Formation vs. Cry of the Carnarium

Is there a way to make member function NOT callable from constructor?

Prime joint compound before latex paint?

Re-submission of rejected manuscript without informing co-authors

What is it called when one voice type sings a 'solo'?

Can I find out the caloric content of bread by dehydrating it?

Shall I use personal or official e-mail account when registering to external websites for work purpose?

Domain expired, GoDaddy holds it and is asking more money



Assigning pointers to atomic type to pointers to non atomic type


Where 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 2 days ago









      Peter Cordes

      134k18203342




      134k18203342










      asked 2 days ago









      Some NameSome Name

      1,782418




      1,782418






















          2 Answers
          2






          active

          oldest

          votes


















          7














          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
              2 days ago







            • 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
              2 days ago







            • 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
              2 days ago











            • 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
              2 days ago







            • 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
              2 days ago












            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









            7














            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



























              7














              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

























                7












                7








                7







                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 2 days ago









                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
                      2 days ago







                    • 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
                      2 days ago







                    • 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
                      2 days ago











                    • 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
                      2 days ago







                    • 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
                      2 days ago
















                    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
                      2 days ago







                    • 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
                      2 days ago







                    • 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
                      2 days ago











                    • 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
                      2 days ago







                    • 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
                      2 days ago














                    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 10 hours ago

























                    answered 2 days ago









                    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
                      2 days ago







                    • 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
                      2 days ago







                    • 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
                      2 days ago











                    • 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
                      2 days ago







                    • 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
                      2 days ago


















                    • 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
                      2 days ago







                    • 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
                      2 days ago







                    • 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
                      2 days ago











                    • 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
                      2 days ago







                    • 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
                      2 days ago

















                    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
                    2 days ago






                    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
                    2 days ago





                    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
                    2 days ago






                    @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
                    2 days ago





                    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
                    2 days ago





                    "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
                    2 days ago













                    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
                    2 days ago






                    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
                    2 days ago





                    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
                    2 days ago






                    @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
                    2 days ago


















                    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

                    Tamil (spriik) Luke uk diar | Nawigatjuun

                    Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                    Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?