Create a 64-bit result using different values












-1















I have to create a 64byte value using val1, val2, val3 and val4.
Output should look like: 0xabcdabcd01000000, but I am getting 0x81000000



uint32_t val1 = 0xabcdabcd;
uint8_t val2 = 1;
uint8_t val3 = 0;
uint16_t val4 = 0;
uint8_t final_val[8];
#define ADDR (&final_val[0])
//The output format is as follows: NNNNNNNNxyz
// NNNNNNNN: value1 in hex
// x - val2,
// y - val3,
// z - val4
int main() {

uint64_t *ptr = (uint64_t *)ADDR ;
*ptr = val1<<31|val2<<24|val3<<16|val4;
printf("%p 0x%x n", ptr, *ptr);
return 0;

}









share|improve this question

























  • Where is final_val declared? please provide the minimum code to reproduce

    – PC Luddite
    Nov 13 '18 at 22:06






  • 3





    I think you refer to 64 bit value instead of 64 bytes.

    – Patrik Valkovič
    Nov 13 '18 at 22:06








  • 1





    Does casting val1/2/3/4 to uint64_t before shifting do the trick?

    – Ctx
    Nov 13 '18 at 22:07






  • 3





    You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

    – Christian Gibbons
    Nov 13 '18 at 22:09








  • 1





    uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

    – chux
    Nov 13 '18 at 22:15
















-1















I have to create a 64byte value using val1, val2, val3 and val4.
Output should look like: 0xabcdabcd01000000, but I am getting 0x81000000



uint32_t val1 = 0xabcdabcd;
uint8_t val2 = 1;
uint8_t val3 = 0;
uint16_t val4 = 0;
uint8_t final_val[8];
#define ADDR (&final_val[0])
//The output format is as follows: NNNNNNNNxyz
// NNNNNNNN: value1 in hex
// x - val2,
// y - val3,
// z - val4
int main() {

uint64_t *ptr = (uint64_t *)ADDR ;
*ptr = val1<<31|val2<<24|val3<<16|val4;
printf("%p 0x%x n", ptr, *ptr);
return 0;

}









share|improve this question

























  • Where is final_val declared? please provide the minimum code to reproduce

    – PC Luddite
    Nov 13 '18 at 22:06






  • 3





    I think you refer to 64 bit value instead of 64 bytes.

    – Patrik Valkovič
    Nov 13 '18 at 22:06








  • 1





    Does casting val1/2/3/4 to uint64_t before shifting do the trick?

    – Ctx
    Nov 13 '18 at 22:07






  • 3





    You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

    – Christian Gibbons
    Nov 13 '18 at 22:09








  • 1





    uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

    – chux
    Nov 13 '18 at 22:15














-1












-1








-1








I have to create a 64byte value using val1, val2, val3 and val4.
Output should look like: 0xabcdabcd01000000, but I am getting 0x81000000



uint32_t val1 = 0xabcdabcd;
uint8_t val2 = 1;
uint8_t val3 = 0;
uint16_t val4 = 0;
uint8_t final_val[8];
#define ADDR (&final_val[0])
//The output format is as follows: NNNNNNNNxyz
// NNNNNNNN: value1 in hex
// x - val2,
// y - val3,
// z - val4
int main() {

uint64_t *ptr = (uint64_t *)ADDR ;
*ptr = val1<<31|val2<<24|val3<<16|val4;
printf("%p 0x%x n", ptr, *ptr);
return 0;

}









share|improve this question
















I have to create a 64byte value using val1, val2, val3 and val4.
Output should look like: 0xabcdabcd01000000, but I am getting 0x81000000



uint32_t val1 = 0xabcdabcd;
uint8_t val2 = 1;
uint8_t val3 = 0;
uint16_t val4 = 0;
uint8_t final_val[8];
#define ADDR (&final_val[0])
//The output format is as follows: NNNNNNNNxyz
// NNNNNNNN: value1 in hex
// x - val2,
// y - val3,
// z - val4
int main() {

uint64_t *ptr = (uint64_t *)ADDR ;
*ptr = val1<<31|val2<<24|val3<<16|val4;
printf("%p 0x%x n", ptr, *ptr);
return 0;

}






c






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 22:20









Jonathan Leffler

565k916771026




565k916771026










asked Nov 13 '18 at 22:04









user968000user968000

88111224




88111224













  • Where is final_val declared? please provide the minimum code to reproduce

    – PC Luddite
    Nov 13 '18 at 22:06






  • 3





    I think you refer to 64 bit value instead of 64 bytes.

    – Patrik Valkovič
    Nov 13 '18 at 22:06








  • 1





    Does casting val1/2/3/4 to uint64_t before shifting do the trick?

    – Ctx
    Nov 13 '18 at 22:07






  • 3





    You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

    – Christian Gibbons
    Nov 13 '18 at 22:09








  • 1





    uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

    – chux
    Nov 13 '18 at 22:15



















  • Where is final_val declared? please provide the minimum code to reproduce

    – PC Luddite
    Nov 13 '18 at 22:06






  • 3





    I think you refer to 64 bit value instead of 64 bytes.

    – Patrik Valkovič
    Nov 13 '18 at 22:06








  • 1





    Does casting val1/2/3/4 to uint64_t before shifting do the trick?

    – Ctx
    Nov 13 '18 at 22:07






  • 3





    You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

    – Christian Gibbons
    Nov 13 '18 at 22:09








  • 1





    uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

    – chux
    Nov 13 '18 at 22:15

















Where is final_val declared? please provide the minimum code to reproduce

– PC Luddite
Nov 13 '18 at 22:06





Where is final_val declared? please provide the minimum code to reproduce

– PC Luddite
Nov 13 '18 at 22:06




3




3





I think you refer to 64 bit value instead of 64 bytes.

– Patrik Valkovič
Nov 13 '18 at 22:06







I think you refer to 64 bit value instead of 64 bytes.

– Patrik Valkovič
Nov 13 '18 at 22:06






1




1





Does casting val1/2/3/4 to uint64_t before shifting do the trick?

– Ctx
Nov 13 '18 at 22:07





Does casting val1/2/3/4 to uint64_t before shifting do the trick?

– Ctx
Nov 13 '18 at 22:07




3




3





You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

– Christian Gibbons
Nov 13 '18 at 22:09







You've got a strict-aliasing violation when you dereference a pointer to final_val[0] as a uint64_t.

– Christian Gibbons
Nov 13 '18 at 22:09






1




1





uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

– chux
Nov 13 '18 at 22:15





uint64_t *ptr =... printf("%p 0x%x n",ptr,*ptr); implies your compiler is not helping you with good warnings. Enable all warnings or get a new compiler.

– chux
Nov 13 '18 at 22:15












2 Answers
2






active

oldest

votes


















2














Each of the shift terms except the first is evaluated as an int; the first is evaluated as a uint32_t which is probably an unsigned int. These results are then or'd together in a uint32_t, and then assigned to your 64-bit result.



You need at least the first shift performed as a 64-bit calculation:



*ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;


This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand (uint64_t). Previously, you couldn't use 32 because you'd be told the shift is too big.



You might prefer the symmetry of:



*ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;


Your printing is also faulty. You should be using the macros from <inttypes.h> to specify the format for the uint64_t value:



printf("%p  0x%" PRIx64 "n", ptr, *ptr);


Note that if you used unsigned long long *ptr etc, you'd use 0x%llx.



The use of final_val is also dubious at best; it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. You'd get different results on little-endian vs big-endian machines, too.






share|improve this answer


























  • For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

    – Lundin
    Nov 14 '18 at 10:26





















4














To create a 64-bit value:



1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits.



val1<<31    
(uint64_t) val1 << 31


2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz



3) Avoid pointers tricks.



uint8_t final_val[8];
// uint64_t *ptr = (uint64_t *)ADDR ;
uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
memcpy(final_val, &u64, sizeof final_val);


4) Use matching printf specifiers.



#include <inttypes.h>
// v---- Not x, x is for unsigned
// printf("0x%xn", u64);
printf("0x%" PRIx64 "n", u64);
// ^----^ from inttypes.h





share|improve this answer

























    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%2f53290205%2fcreate-a-64-bit-result-using-different-values%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









    2














    Each of the shift terms except the first is evaluated as an int; the first is evaluated as a uint32_t which is probably an unsigned int. These results are then or'd together in a uint32_t, and then assigned to your 64-bit result.



    You need at least the first shift performed as a 64-bit calculation:



    *ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;


    This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand (uint64_t). Previously, you couldn't use 32 because you'd be told the shift is too big.



    You might prefer the symmetry of:



    *ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;


    Your printing is also faulty. You should be using the macros from <inttypes.h> to specify the format for the uint64_t value:



    printf("%p  0x%" PRIx64 "n", ptr, *ptr);


    Note that if you used unsigned long long *ptr etc, you'd use 0x%llx.



    The use of final_val is also dubious at best; it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. You'd get different results on little-endian vs big-endian machines, too.






    share|improve this answer


























    • For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

      – Lundin
      Nov 14 '18 at 10:26


















    2














    Each of the shift terms except the first is evaluated as an int; the first is evaluated as a uint32_t which is probably an unsigned int. These results are then or'd together in a uint32_t, and then assigned to your 64-bit result.



    You need at least the first shift performed as a 64-bit calculation:



    *ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;


    This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand (uint64_t). Previously, you couldn't use 32 because you'd be told the shift is too big.



    You might prefer the symmetry of:



    *ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;


    Your printing is also faulty. You should be using the macros from <inttypes.h> to specify the format for the uint64_t value:



    printf("%p  0x%" PRIx64 "n", ptr, *ptr);


    Note that if you used unsigned long long *ptr etc, you'd use 0x%llx.



    The use of final_val is also dubious at best; it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. You'd get different results on little-endian vs big-endian machines, too.






    share|improve this answer


























    • For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

      – Lundin
      Nov 14 '18 at 10:26
















    2












    2








    2







    Each of the shift terms except the first is evaluated as an int; the first is evaluated as a uint32_t which is probably an unsigned int. These results are then or'd together in a uint32_t, and then assigned to your 64-bit result.



    You need at least the first shift performed as a 64-bit calculation:



    *ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;


    This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand (uint64_t). Previously, you couldn't use 32 because you'd be told the shift is too big.



    You might prefer the symmetry of:



    *ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;


    Your printing is also faulty. You should be using the macros from <inttypes.h> to specify the format for the uint64_t value:



    printf("%p  0x%" PRIx64 "n", ptr, *ptr);


    Note that if you used unsigned long long *ptr etc, you'd use 0x%llx.



    The use of final_val is also dubious at best; it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. You'd get different results on little-endian vs big-endian machines, too.






    share|improve this answer















    Each of the shift terms except the first is evaluated as an int; the first is evaluated as a uint32_t which is probably an unsigned int. These results are then or'd together in a uint32_t, and then assigned to your 64-bit result.



    You need at least the first shift performed as a 64-bit calculation:



    *ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;


    This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand (uint64_t). Previously, you couldn't use 32 because you'd be told the shift is too big.



    You might prefer the symmetry of:



    *ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;


    Your printing is also faulty. You should be using the macros from <inttypes.h> to specify the format for the uint64_t value:



    printf("%p  0x%" PRIx64 "n", ptr, *ptr);


    Note that if you used unsigned long long *ptr etc, you'd use 0x%llx.



    The use of final_val is also dubious at best; it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. You'd get different results on little-endian vs big-endian machines, too.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 13 '18 at 22:31

























    answered Nov 13 '18 at 22:17









    Jonathan LefflerJonathan Leffler

    565k916771026




    565k916771026













    • For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

      – Lundin
      Nov 14 '18 at 10:26





















    • For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

      – Lundin
      Nov 14 '18 at 10:26



















    For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

    – Lundin
    Nov 14 '18 at 10:26







    For a complete answer, please add a note that uint64_t *ptr = (uint64_t *)ADDR ; is a strict aliasing violation and UB, or alternatively just drop ptr in favour for an uint64_t. And we really shouldn't shift on int or other signed types, ever. So the version with explicit casts on all operands is always to prefer.

    – Lundin
    Nov 14 '18 at 10:26















    4














    To create a 64-bit value:



    1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits.



    val1<<31    
    (uint64_t) val1 << 31


    2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz



    3) Avoid pointers tricks.



    uint8_t final_val[8];
    // uint64_t *ptr = (uint64_t *)ADDR ;
    uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
    memcpy(final_val, &u64, sizeof final_val);


    4) Use matching printf specifiers.



    #include <inttypes.h>
    // v---- Not x, x is for unsigned
    // printf("0x%xn", u64);
    printf("0x%" PRIx64 "n", u64);
    // ^----^ from inttypes.h





    share|improve this answer






























      4














      To create a 64-bit value:



      1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits.



      val1<<31    
      (uint64_t) val1 << 31


      2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz



      3) Avoid pointers tricks.



      uint8_t final_val[8];
      // uint64_t *ptr = (uint64_t *)ADDR ;
      uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
      memcpy(final_val, &u64, sizeof final_val);


      4) Use matching printf specifiers.



      #include <inttypes.h>
      // v---- Not x, x is for unsigned
      // printf("0x%xn", u64);
      printf("0x%" PRIx64 "n", u64);
      // ^----^ from inttypes.h





      share|improve this answer




























        4












        4








        4







        To create a 64-bit value:



        1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits.



        val1<<31    
        (uint64_t) val1 << 31


        2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz



        3) Avoid pointers tricks.



        uint8_t final_val[8];
        // uint64_t *ptr = (uint64_t *)ADDR ;
        uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
        memcpy(final_val, &u64, sizeof final_val);


        4) Use matching printf specifiers.



        #include <inttypes.h>
        // v---- Not x, x is for unsigned
        // printf("0x%xn", u64);
        printf("0x%" PRIx64 "n", u64);
        // ^----^ from inttypes.h





        share|improve this answer















        To create a 64-bit value:



        1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits.



        val1<<31    
        (uint64_t) val1 << 31


        2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz



        3) Avoid pointers tricks.



        uint8_t final_val[8];
        // uint64_t *ptr = (uint64_t *)ADDR ;
        uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
        memcpy(final_val, &u64, sizeof final_val);


        4) Use matching printf specifiers.



        #include <inttypes.h>
        // v---- Not x, x is for unsigned
        // printf("0x%xn", u64);
        printf("0x%" PRIx64 "n", u64);
        // ^----^ from inttypes.h






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 13 '18 at 22:28

























        answered Nov 13 '18 at 22:22









        chuxchux

        82.5k872149




        82.5k872149






























            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%2f53290205%2fcreate-a-64-bit-result-using-different-values%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

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma