Question about converting `void *` to `int` in C











up vote
9
down vote

favorite












I'm trying to pick my C skills again. I want to sum a sequence in different threads, each thread would return a pointer of the sum of a part of the sequence. However, when I tried to convert the void* type value local_sum to int, problem occurred.



I tried to convert with sum += *(int*)local_sum;, a segment error occurred and I got Process finished with exit code 11.



I found that if I use sum += (int)local_sum;, it would be okay. But I couldn't convince myself: shouldn't local_sum be a void *? Why it can be converted to int with (int)local_sum?



I'm so grateful it you could answer the problem.



The part that sum each process's return value is here:



int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}


The function of a thread is here:



void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}









share|improve this question







New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 12




    Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
    – Lundin
    Nov 16 at 15:41












  • refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
    – Sander De Dycker
    Nov 16 at 15:46















up vote
9
down vote

favorite












I'm trying to pick my C skills again. I want to sum a sequence in different threads, each thread would return a pointer of the sum of a part of the sequence. However, when I tried to convert the void* type value local_sum to int, problem occurred.



I tried to convert with sum += *(int*)local_sum;, a segment error occurred and I got Process finished with exit code 11.



I found that if I use sum += (int)local_sum;, it would be okay. But I couldn't convince myself: shouldn't local_sum be a void *? Why it can be converted to int with (int)local_sum?



I'm so grateful it you could answer the problem.



The part that sum each process's return value is here:



int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}


The function of a thread is here:



void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}









share|improve this question







New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 12




    Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
    – Lundin
    Nov 16 at 15:41












  • refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
    – Sander De Dycker
    Nov 16 at 15:46













up vote
9
down vote

favorite









up vote
9
down vote

favorite











I'm trying to pick my C skills again. I want to sum a sequence in different threads, each thread would return a pointer of the sum of a part of the sequence. However, when I tried to convert the void* type value local_sum to int, problem occurred.



I tried to convert with sum += *(int*)local_sum;, a segment error occurred and I got Process finished with exit code 11.



I found that if I use sum += (int)local_sum;, it would be okay. But I couldn't convince myself: shouldn't local_sum be a void *? Why it can be converted to int with (int)local_sum?



I'm so grateful it you could answer the problem.



The part that sum each process's return value is here:



int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}


The function of a thread is here:



void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}









share|improve this question







New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I'm trying to pick my C skills again. I want to sum a sequence in different threads, each thread would return a pointer of the sum of a part of the sequence. However, when I tried to convert the void* type value local_sum to int, problem occurred.



I tried to convert with sum += *(int*)local_sum;, a segment error occurred and I got Process finished with exit code 11.



I found that if I use sum += (int)local_sum;, it would be okay. But I couldn't convince myself: shouldn't local_sum be a void *? Why it can be converted to int with (int)local_sum?



I'm so grateful it you could answer the problem.



The part that sum each process's return value is here:



int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}


The function of a thread is here:



void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}






c pointers type-conversion pthreads






share|improve this question







New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Nov 16 at 15:20









Frost-Lee

514




514




New contributor




Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Frost-Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 12




    Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
    – Lundin
    Nov 16 at 15:41












  • refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
    – Sander De Dycker
    Nov 16 at 15:46














  • 12




    Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
    – Lundin
    Nov 16 at 15:41












  • refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
    – Sander De Dycker
    Nov 16 at 15:46








12




12




Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
– Lundin
Nov 16 at 15:41






Passing an int inside the the void* of pthreads, as opposed to pointing at one, has always been a dirty hack. And as all dirty hacks, they eventually break. Integer-to-pointer conversions have implementation-defined behavior (at the very least use uintptr_t). The solution is not to use dirty hacks, but to pass a pointer to malloc:ed data. The overhead execution time of dynamic allocation is nothing compared to the cost of creating and closing a thread.
– Lundin
Nov 16 at 15:41














refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
– Sander De Dycker
Nov 16 at 15:46




refer to c89: Convert an int to void* and back and the linked question Is it safe to cast an int to void pointer and back to int again?
– Sander De Dycker
Nov 16 at 15:46












3 Answers
3






active

oldest

votes

















up vote
10
down vote



accepted










You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.



void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).



To illustrate this:



int a = 5;
void *p = (void *)a;
int b = (int)p;


a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:



b = *(int *)p; // Undefined Behavior!


Consider the following program:



#include <limits.h>
#include <stdio.h>

int main(void)
{
int a, b;
void *p;

a = 5;
p = (void *)a;
b = (int)p;

printf("%d %p %dn", a, p, b);

a = INT_MAX;
p = (void *)a + 1;
b = (int)p;

printf("%d %p %dn", a, p, b);

return 0;
}


When compiled, I get the following warnings:




$ gcc main.c -o main.exe
main.c: In function ‘main’:
main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
p = (void *)a;
^
main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
b = (int)p;

...


A warning is issued because, as pointed out by @Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.



Output




$ ./main.exe
5 0x5 5
2147483647 0x80000000 -2147483648





share|improve this answer



















  • 1




    " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
    – Gerhardh
    Nov 16 at 15:47






  • 2




    note that the behavior of this is implementation defined
    – Sander De Dycker
    Nov 16 at 15:47










  • @Gerhardh Excellent point.
    – Fiddling Bits
    Nov 16 at 15:59










  • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    Nov 16 at 20:36










  • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    Nov 16 at 20:38




















up vote
8
down vote













You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.






share|improve this answer




























    up vote
    0
    down vote













    A secure and portable solution could be the use of an union:



    union void_cast {
    void* ptr;
    int value;
    };


    Then for example you can safely reinterpret a void* pointer with:



    int VOID_TO_INT(void* ptr) {
    union void_cast u;
    u.ptr = ptr;
    return u.value;
    }

    void* INT_TO_VOID(int value) {
    union void_cast u;
    u.value = value;
    return u.ptr;
    }


    So your code can be changed to:



    sum += VOID_TO_INT(local_sum);





    share|improve this answer

















    • 2




      Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
      – PSkocik
      Nov 16 at 16:21











    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',
    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
    });


    }
    });






    Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.










     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53340689%2fquestion-about-converting-void-to-int-in-c%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    10
    down vote



    accepted










    You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.



    void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).



    To illustrate this:



    int a = 5;
    void *p = (void *)a;
    int b = (int)p;


    a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:



    b = *(int *)p; // Undefined Behavior!


    Consider the following program:



    #include <limits.h>
    #include <stdio.h>

    int main(void)
    {
    int a, b;
    void *p;

    a = 5;
    p = (void *)a;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    a = INT_MAX;
    p = (void *)a + 1;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    return 0;
    }


    When compiled, I get the following warnings:




    $ gcc main.c -o main.exe
    main.c: In function ‘main’:
    main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    p = (void *)a;
    ^
    main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    b = (int)p;

    ...


    A warning is issued because, as pointed out by @Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.



    Output




    $ ./main.exe
    5 0x5 5
    2147483647 0x80000000 -2147483648





    share|improve this answer



















    • 1




      " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
      – Gerhardh
      Nov 16 at 15:47






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      Nov 16 at 15:47










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 at 15:59










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      Nov 16 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 at 20:38

















    up vote
    10
    down vote



    accepted










    You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.



    void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).



    To illustrate this:



    int a = 5;
    void *p = (void *)a;
    int b = (int)p;


    a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:



    b = *(int *)p; // Undefined Behavior!


    Consider the following program:



    #include <limits.h>
    #include <stdio.h>

    int main(void)
    {
    int a, b;
    void *p;

    a = 5;
    p = (void *)a;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    a = INT_MAX;
    p = (void *)a + 1;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    return 0;
    }


    When compiled, I get the following warnings:




    $ gcc main.c -o main.exe
    main.c: In function ‘main’:
    main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    p = (void *)a;
    ^
    main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    b = (int)p;

    ...


    A warning is issued because, as pointed out by @Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.



    Output




    $ ./main.exe
    5 0x5 5
    2147483647 0x80000000 -2147483648





    share|improve this answer



















    • 1




      " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
      – Gerhardh
      Nov 16 at 15:47






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      Nov 16 at 15:47










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 at 15:59










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      Nov 16 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 at 20:38















    up vote
    10
    down vote



    accepted







    up vote
    10
    down vote



    accepted






    You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.



    void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).



    To illustrate this:



    int a = 5;
    void *p = (void *)a;
    int b = (int)p;


    a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:



    b = *(int *)p; // Undefined Behavior!


    Consider the following program:



    #include <limits.h>
    #include <stdio.h>

    int main(void)
    {
    int a, b;
    void *p;

    a = 5;
    p = (void *)a;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    a = INT_MAX;
    p = (void *)a + 1;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    return 0;
    }


    When compiled, I get the following warnings:




    $ gcc main.c -o main.exe
    main.c: In function ‘main’:
    main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    p = (void *)a;
    ^
    main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    b = (int)p;

    ...


    A warning is issued because, as pointed out by @Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.



    Output




    $ ./main.exe
    5 0x5 5
    2147483647 0x80000000 -2147483648





    share|improve this answer














    You're returning the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.



    void * is used this way sometimes to return either a value (e.g. int) or an address to something (e.g. struct).



    To illustrate this:



    int a = 5;
    void *p = (void *)a;
    int b = (int)p;


    a, p, and b all have a value of 5. p does not point to a valid address. Trying to dereference p would result in undefined behavior:



    b = *(int *)p; // Undefined Behavior!


    Consider the following program:



    #include <limits.h>
    #include <stdio.h>

    int main(void)
    {
    int a, b;
    void *p;

    a = 5;
    p = (void *)a;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    a = INT_MAX;
    p = (void *)a + 1;
    b = (int)p;

    printf("%d %p %dn", a, p, b);

    return 0;
    }


    When compiled, I get the following warnings:




    $ gcc main.c -o main.exe
    main.c: In function ‘main’:
    main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    p = (void *)a;
    ^
    main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    b = (int)p;

    ...


    A warning is issued because, as pointed out by @Gerhardh, the sizeof(int) and the sizeof(void *) may be different. You may suffer data loss if the value of the void * exceeds the maximum value a int can hold.



    Output




    $ ./main.exe
    5 0x5 5
    2147483647 0x80000000 -2147483648






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 16 at 15:58

























    answered Nov 16 at 15:28









    Fiddling Bits

    6,96021938




    6,96021938








    • 1




      " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
      – Gerhardh
      Nov 16 at 15:47






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      Nov 16 at 15:47










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 at 15:59










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      Nov 16 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 at 20:38
















    • 1




      " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
      – Gerhardh
      Nov 16 at 15:47






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      Nov 16 at 15:47










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 at 15:59










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      Nov 16 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 at 20:38










    1




    1




    " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
    – Gerhardh
    Nov 16 at 15:47




    " in our case, this behavior is desired." Really? It's not only a warning about conversion, it is about different size. That is not the part that is desired. You probably have 4 byte integers and 8 byte pointers.
    – Gerhardh
    Nov 16 at 15:47




    2




    2




    note that the behavior of this is implementation defined
    – Sander De Dycker
    Nov 16 at 15:47




    note that the behavior of this is implementation defined
    – Sander De Dycker
    Nov 16 at 15:47












    @Gerhardh Excellent point.
    – Fiddling Bits
    Nov 16 at 15:59




    @Gerhardh Excellent point.
    – Fiddling Bits
    Nov 16 at 15:59












    a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    Nov 16 at 20:36




    a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    Nov 16 at 20:36












    @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    Nov 16 at 20:38






    @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    Nov 16 at 20:38














    up vote
    8
    down vote













    You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.






    share|improve this answer

























      up vote
      8
      down vote













      You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.






      share|improve this answer























        up vote
        8
        down vote










        up vote
        8
        down vote









        You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.






        share|improve this answer












        You can't do *(int*)local_sum because local_sum is not an int* cast to void*. local_sum is an int cast to void*. It is a number reinterpreted as an address, but only for transfer purposes, because pthread_exit only allows you to return a void*, not an int and because the standard explicitly allows implementation-defined conversion (6.3.2.3p5, 6.3.2.3p6) between integers and numbers as long as the values fit (if they don't then, UB). If you return, e.g., 0x42, it is highly unlikely there's anything at address 0x42, so you should forget about dereferencing it and instead you should convert it back to an integer ASAP, either with (int)local_sum; or perhaps better with (int)(intptr_t)local_sum; (though intptr_t isn't guaranteed to exist) or (perhaps best) with (int)(intmax_t)local_sum; so as to avoid possible compiler warnings about converting to an integer of a different size on LP64 platforms.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 at 15:41









        PSkocik

        31k54568




        31k54568






















            up vote
            0
            down vote













            A secure and portable solution could be the use of an union:



            union void_cast {
            void* ptr;
            int value;
            };


            Then for example you can safely reinterpret a void* pointer with:



            int VOID_TO_INT(void* ptr) {
            union void_cast u;
            u.ptr = ptr;
            return u.value;
            }

            void* INT_TO_VOID(int value) {
            union void_cast u;
            u.value = value;
            return u.ptr;
            }


            So your code can be changed to:



            sum += VOID_TO_INT(local_sum);





            share|improve this answer

















            • 2




              Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
              – PSkocik
              Nov 16 at 16:21















            up vote
            0
            down vote













            A secure and portable solution could be the use of an union:



            union void_cast {
            void* ptr;
            int value;
            };


            Then for example you can safely reinterpret a void* pointer with:



            int VOID_TO_INT(void* ptr) {
            union void_cast u;
            u.ptr = ptr;
            return u.value;
            }

            void* INT_TO_VOID(int value) {
            union void_cast u;
            u.value = value;
            return u.ptr;
            }


            So your code can be changed to:



            sum += VOID_TO_INT(local_sum);





            share|improve this answer

















            • 2




              Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
              – PSkocik
              Nov 16 at 16:21













            up vote
            0
            down vote










            up vote
            0
            down vote









            A secure and portable solution could be the use of an union:



            union void_cast {
            void* ptr;
            int value;
            };


            Then for example you can safely reinterpret a void* pointer with:



            int VOID_TO_INT(void* ptr) {
            union void_cast u;
            u.ptr = ptr;
            return u.value;
            }

            void* INT_TO_VOID(int value) {
            union void_cast u;
            u.value = value;
            return u.ptr;
            }


            So your code can be changed to:



            sum += VOID_TO_INT(local_sum);





            share|improve this answer












            A secure and portable solution could be the use of an union:



            union void_cast {
            void* ptr;
            int value;
            };


            Then for example you can safely reinterpret a void* pointer with:



            int VOID_TO_INT(void* ptr) {
            union void_cast u;
            u.ptr = ptr;
            return u.value;
            }

            void* INT_TO_VOID(int value) {
            union void_cast u;
            u.value = value;
            return u.ptr;
            }


            So your code can be changed to:



            sum += VOID_TO_INT(local_sum);






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 16 at 16:15









            Morpheus

            314




            314








            • 2




              Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
              – PSkocik
              Nov 16 at 16:21














            • 2




              Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
              – PSkocik
              Nov 16 at 16:21








            2




            2




            Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
            – PSkocik
            Nov 16 at 16:21




            Casting should work regardless of endianness. On a (very theoretical) big-endian machine where ints are half the width of pointers, the union approach would fail to extract the value while a cast shouldn't.
            – PSkocik
            Nov 16 at 16:21










            Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.










             

            draft saved


            draft discarded


















            Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.













            Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.












            Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.















             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53340689%2fquestion-about-converting-void-to-int-in-c%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

            Quarter-circle Tiles

            build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

            Mont Emei