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;
}
c pointers type-conversion pthreads
New contributor
add a comment |
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;
}
c pointers type-conversion pthreads
New contributor
12
Passing anint
inside the thevoid*
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
add a comment |
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;
}
c pointers type-conversion pthreads
New contributor
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
c pointers type-conversion pthreads
New contributor
New contributor
New contributor
asked Nov 16 at 15:20
Frost-Lee
514
514
New contributor
New contributor
12
Passing anint
inside the thevoid*
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
add a comment |
12
Passing anint
inside the thevoid*
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
add a comment |
3 Answers
3
active
oldest
votes
up vote
10
down vote
accepted
You're return
ing 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
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
andb
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
|
show 1 more comment
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.
add a comment |
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);
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
add a comment |
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 return
ing 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
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
andb
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
|
show 1 more comment
up vote
10
down vote
accepted
You're return
ing 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
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
andb
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
|
show 1 more comment
up vote
10
down vote
accepted
up vote
10
down vote
accepted
You're return
ing 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
You're return
ing 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
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
andb
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
|
show 1 more comment
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
andb
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
|
show 1 more comment
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 16 at 15:41
PSkocik
31k54568
31k54568
add a comment |
add a comment |
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);
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
add a comment |
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);
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
add a comment |
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);
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);
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
add a comment |
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
add a comment |
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.
Frost-Lee is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
12
Passing an
int
inside the thevoid*
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