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











up vote
8
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
    yesterday












  • 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
    yesterday















up vote
8
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
    yesterday












  • 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
    yesterday













up vote
8
down vote

favorite









up vote
8
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 yesterday









Frost-Lee

464




464




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
    yesterday












  • 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
    yesterday














  • 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
    yesterday












  • 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
    yesterday








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
yesterday






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
yesterday














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
yesterday




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
yesterday












3 Answers
3






active

oldest

votes

















up vote
9
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
    yesterday






  • 2




    note that the behavior of this is implementation defined
    – Sander De Dycker
    yesterday










  • @Gerhardh Excellent point.
    – Fiddling Bits
    yesterday










  • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    yesterday










  • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    yesterday




















up vote
7
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
      yesterday











    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
    9
    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
      yesterday






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      yesterday










    • @Gerhardh Excellent point.
      – Fiddling Bits
      yesterday










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      yesterday










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      yesterday

















    up vote
    9
    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
      yesterday






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      yesterday










    • @Gerhardh Excellent point.
      – Fiddling Bits
      yesterday










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      yesterday










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      yesterday















    up vote
    9
    down vote



    accepted







    up vote
    9
    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 yesterday

























    answered yesterday









    Fiddling Bits

    6,87221837




    6,87221837








    • 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
      yesterday






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      yesterday










    • @Gerhardh Excellent point.
      – Fiddling Bits
      yesterday










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      yesterday










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      yesterday
















    • 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
      yesterday






    • 2




      note that the behavior of this is implementation defined
      – Sander De Dycker
      yesterday










    • @Gerhardh Excellent point.
      – Fiddling Bits
      yesterday










    • a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
      – David Brown
      yesterday










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      yesterday










    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
    yesterday




    " 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
    yesterday




    2




    2




    note that the behavior of this is implementation defined
    – Sander De Dycker
    yesterday




    note that the behavior of this is implementation defined
    – Sander De Dycker
    yesterday












    @Gerhardh Excellent point.
    – Fiddling Bits
    yesterday




    @Gerhardh Excellent point.
    – Fiddling Bits
    yesterday












    a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    yesterday




    a, p, and b all have a value of 5. a and b are not guaranteed to have the same value.
    – David Brown
    yesterday












    @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    yesterday






    @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
    – Fiddling Bits
    yesterday














    up vote
    7
    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
      7
      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
        7
        down vote










        up vote
        7
        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 yesterday









        PSkocik

        30.8k54468




        30.8k54468






















            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
              yesterday















            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
              yesterday













            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 yesterday









            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
              yesterday














            • 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
              yesterday








            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
            yesterday




            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
            yesterday










            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

            flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

            Mangá

            Eduardo VII do Reino Unido