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












9














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


















  • 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 '18 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 '18 at 15:46
















9














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


















  • 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 '18 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 '18 at 15:46














9












9








9







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













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













share|improve this question











share|improve this question




share|improve this question










asked Nov 16 '18 at 15:20









Frost-Lee

514




514








  • 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 15:46












3 Answers
3






active

oldest

votes


















10














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 '18 at 15:47






  • 2




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










  • @Gerhardh Excellent point.
    – Fiddling Bits
    Nov 16 '18 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 '18 at 20:36










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





















8














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





























    0














    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 '18 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',
    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%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









    10














    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 '18 at 15:47






    • 2




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










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 '18 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 '18 at 20:36










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


















    10














    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 '18 at 15:47






    • 2




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










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 '18 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 '18 at 20:36










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
















    10












    10








    10






    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 '18 at 15:58

























    answered Nov 16 '18 at 15:28









    Fiddling Bits

    7,09821938




    7,09821938








    • 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 '18 at 15:47






    • 2




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










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 '18 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 '18 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 '18 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 '18 at 15:47






    • 2




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










    • @Gerhardh Excellent point.
      – Fiddling Bits
      Nov 16 '18 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 '18 at 20:36










    • @DavidBrown Of course, this is undefined behavior. On my machine, this behavior is so.
      – Fiddling Bits
      Nov 16 '18 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 '18 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 '18 at 15:47




    2




    2




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




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












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




    @Gerhardh Excellent point.
    – Fiddling Bits
    Nov 16 '18 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 '18 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 '18 at 20:36












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






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















    8














    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


























      8














      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
























        8












        8








        8






        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 '18 at 15:41









        PSkocik

        32.2k54770




        32.2k54770























            0














            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 '18 at 16:21
















            0














            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 '18 at 16:21














            0












            0








            0






            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 '18 at 16:15









            Morpheus

            1385




            1385








            • 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 '18 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 '18 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 '18 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 '18 at 16:21


















            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


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

            How to change which sound is reproduced for terminal bell?

            Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

            Can I use Tabulator js library in my java Spring + Thymeleaf project?