Using Address as scalar value - c++

I am trying to understand some legacy code using AfxBeginThread.
To my understanding LPVOID is defined as a pointer to a void object. I have this function:
Start(LPVOID pParam){
...
int iTemp = (int)pParam;
...
}
And then the call:
int ch1 = 1;
AfxBeginThread(Start(), (LPVOID)ch1);
I am getting the following compiler warning when compiling for 64bit:
warning C4312: 'type cast': conversion from 'int' to 'LPVOID' of greater size
I am
not 100% sure this is a proper use of a pointer
to avoid the warning, I could use a helper function like (LPVOID) PtrToInt(ch1), but that doesn't look right to me as well
Could anyone help me understand the mechanics behind this? I've been trying to find an example online which uses AfxBeginThread in a similar fashion but failed so far.
MS states:
The parameter is a single value. The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. The controlling function can interpret this value in any manner it chooses. It can be treated as a scalar value or a pointer to a structure containing multiple parameters, or it can be ignored.

This warning occurs because you are compiling on a 64 bit machine where sizeof(void*) is 8 bytes but sizeof(int) is 4.
A proper way to handle this would be to use an integer type for ch1 which is the same size as a void pointer. This is the exact use case for intptr_t.
And so, it should be safe if you use ìntptr_t to hold the ch1 variable. See also this question: C++: Is it safe to cast pointer to int and later back to pointer again?

not 100% sure this is a proper use of a pointer
You have the right hunch. No, it is not proper use of a pointer.
You can pass a pointer to the function.
int ch1 = 1;
int* ptr = &ch1;
AfxBeginThread(Start(), ptr);

Related

Can you cast the result of sizeof

I was wondering if it makes sense to cast the result of sizeof?
Example:
Change sizeof(example) to (size_t) sizeof(example)
The return type is std::size_tbut I get the error "Invalid arguements" in many functions (malloc, memset, ...) and after the cast it works. A quick check with printf showed me, that the results stayed the same.
-edited-
As requested a short example function:
__cxa_dependent_exception* __cxxabiv1:: __cxa_allocate_dependent_exception() throw()
{
__cxa_dependent_exception *ps_ret;
ps_ret = static_cast<__cxa_dependent_exception *> (o_exception_pool.allocate (
(size_t) sizeof(__cxa_dependent_exception )));
if (!ps_ret)
{
std::terminate ();
}
memset (ps_ret, 0, (size_t) sizeof(__cxa_dependent_exception ));
return ps_ret;
}
Without the casts this code throws the mentioned error. The full example can be found in the gcc 4.5.4 source code "libstdc++-v3/libsupc++/eh_alloc.cc"
I am using MinGW.
Yes, you can cast result of sizeof, since sizeof(something) is compile time and you will get result in type of (size_t)5 if sizeof(something) returns 5.
Your question condenses to "can you cast std::size_t to another type".
Of course you can, subject to the normal type casting rules. For example, casting this to an int could get you in hot water for a very large type on a system with a 16 bit int. In other words, check that the new type has adequate capacity.
Extra brownie points if you can do that at compile time in C++.

Freetype 2, building visual studio 2015

Getting the following warning:
ttgload.c(1654): warning C4312: 'type cast': conversion from 'FT_UInt' to 'void *' of greater size
Which seems rather odd.
The line of code in question is this:
if ( FT_List_Find( &loader->composites,
(void*)(unsigned long)glyph_index ) )
and glyph_index is declared FT_UInt.
FT_UInt is typedef unsigned int so it is rather strange to convert an int to a void*.
Any ideas on how to deal with this warning?
FT_UInt is typedef unsigned int so it is rather strange to convert an int to a void*.
Actually it's not. It's perfectly fine and allowed to convert between integers and pointers. A particular application of this is "user parameters" to a function where you register integer or a pointer together with a function callback.
However the two-fold typecast (void*)(unsigned long) is a recipe for getting problems. It's not guaranteed that sizeof(unsigned ling) >= sizeof(void*) which may cause all kinds of problems (i.e. undefined behaviour) of pointers get truncated.
The proper types to use when someone wants an integer that also can hold a pointer are uintptr_t and intptr_t.
Any ideas on how to deal with this warning?
In this particular case it's likely not a cause of problems, because that pointer is going to be cast back to an FT_UInt. In the long run it would make sense to file an issue and change the prototype of FT_List_Find to accept a uintptr_t instead of a pointer; unfortunately this would also break a lot of existing programs.

C++ pointer syntax problems

I am a professional software developer but I'm largely unfamiliar with C++ syntax. I am trying to compare the value at the end of a pointer with a double in an inherited C++ project.
The following bit of code successfully grabs the valueAddress from a text file and prints, for example
|"Primary key value"|123.456|
where the 123.456 is the value of the double at the address in the text file.
...
char DebugString[64];
int valueAddress;
fscanf(inputFile, "%s %d", key, &valueAddress);//inputFile declared elsewhere
printf("|");
printf(database->primaryKey);// Defined elsewhere and not the focus of this question
printf("|");
sprintf_s(DebugString,64,"%g",* ((double *)valueAddress));
printf(DebugString);
printf("|");
...
Why then, can't I access the value using:
if ((double *)valueAddress < -0.5)
{...}
as I get the error "error C2440: '>' : cannot convert from 'double' to 'double *'"
I also can't do:
if ((double) *valueAddress < -0.5)
{...}
as I get the error "error C2100: illegal indirection". Creating a variable and trying to assign that doesn't work either.
valueAddress is an integer in a text file, which is the memory address of a double value. So I need to use the int valueAddress as a double pointer. It clearly works when putting the value in the DebugString, so why won't it work in an if statement? How can I get around this?
I'm clearly misunderstanding the syntax here. What have I got wrong?
Using an int to represent the address of a double stored somewhere and attempting to cast an int to a double* is undefined behaviour in C++.
An int might not even be large enough to hold a pointer address. On a 64 bit system, a 32 bit int is not sufficient.
You might get away with using intptr_t to represent the address, and cast using *(double*)valueAddress. But it's still not well-defined.
I'm willing to be corrected on this point but I think the only realistic choice is an inline assembly solution specific to your platform to effect this conversion. That said, you're only reading data from a text file, and you can do that using perfectly normal C++.
First off, int is not the correct data type to store a memory address. You really should use intptr_t from <stdint.h>, which is guaranteed to be the correct size.
To reinterpret this value as a double* and dereference for comparison, you would do:
if ( *(double*)valueAddress < -0.5 )
But I am a little concerned about this. Unless that pointer references memory that already belongs to your program, you are not allowed to access it. Doing so will fall in the realm of undefined behaviour.
You need to dereference your pointer
if ( * ( (double * ) valueAddress ) < -0.5)
This first converts to a pointer, then finds the value pointed to.

cast to ‘uint32_t’ loses precision [duplicate]

I have a function with prototype void* myFcn(void* arg) which is used as the starting point for a pthread. I need to convert the argument to an int for later use:
int x = (int)arg;
The compiler (GCC version 4.2.4) returns the error:
file.cpp:233: error: cast from 'void*' to 'int' loses precision
What is the proper way to cast this?
You can cast it to an intptr_t type. It's an int type guaranteed to be big enough to contain a pointer. Use #include <cstdint> to define it.
Again, all of the answers above missed the point badly. The OP wanted to convert a pointer value to a int value, instead, most the answers, one way or the other, tried to wrongly convert the content of arg points to to a int value. And, most of these will not even work on gcc4.
The correct answer is, if one does not mind losing data precision,
int x = *((int*)(&arg));
This works on GCC4.
The best way is, if one can, do not do such casting, instead, if the same memory address has to be shared for pointer and int (e.g. for saving RAM), use union, and make sure, if the mem address is treated as an int only if you know it was last set as an int.
Instead of:
int x = (int)arg;
use:
int x = (long)arg;
On most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms. If you convert (void*) to (long) no precision is lost, then by assigning the (long) to an (int), it properly truncates the number to fit.
There's no proper way to cast this to int in general case. C99 standard library provides intptr_t and uintptr_t typedefs, which are supposed to be used whenever the need to perform such a cast comes about. If your standard library (even if it is not C99) happens to provide these types - use them. If not, check the pointer size on your platform, define these typedefs accordingly yourself and use them.
Casting a pointer to void* and back is valid use of reinterpret_cast<>. So you could do this:
pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int*
Then in myFcn:
void* myFcn(void* arg)
{
int* data = reinterpret_cast<int*>(arg);
int x = *data;
delete data;
Note: As sbi points out this would require a change on the OP call to create the thread.
What I am trying to emphasis that conversion from int to pointer and back again can be frough with problems as you move from platform to platform. BUT converting a pointer to void* and back again is well supported (everywhere).
Thus as a result it may be less error prone to generate a pointer dynamcially and use that.
Remembering to delete the pointer after use so that we don't leak.
Instead of using a long cast, you should cast to size_t.
int val= (int)((size_t)arg);
The proper way is to cast it to another pointer type. Converting a void* to an int is non-portable way that may work or may not! If you need to keep the returned address, just keep it as void*.
Safest way :
static_cast<int>(reinterpret_cast<long>(void * your_variable));
long guarantees a pointer size on Linux on any machine. Windows has 32 bit long only on 64 bit as well. Therefore, you need to change it to long long instead of long in windows for 64 bits.
So reinterpret_cast has casted it to long type and then static_cast safely casts long to int, if you are ready do truncte the data.
There is no "correct" way to store a 64-bit pointer in an 32-bit integer. The problem is not with casting, but with the target type loosing half of the pointer. The 32 remaining bits stored inside int are insufficient to reconstruct a pointer to the thread function. Most answers just try to extract 32 useless bits out of the argument.
As Ferruccio said, int must be replaced with intptr_t to make the program meaningful.
If you call your thread creation function like this
pthread_create(&thread, NULL, myFcn, reinterpret_cast<void*>(5));
then the void* arriving inside of myFcn has the value of the int you put into it. So you know you can cast it back like this
int myData = reinterpret_cast<int>(arg);
even though the compiler doesn't know you only ever pass myFcn to pthread_create in conjunction with an integer.
Edit:
As was pointed out by Martin, this presumes that sizeof(void*)>=sizeof(int). If your code has the chance to ever be ported to some platform where this doesn't hold, this won't work.
I would create a structure and pass that as void* to pthread_create
struct threadArg {
int intData;
long longData;
etc...
};
threadArg thrArg;
thrArg.intData = 4;
...
pthread_create(&thread, NULL, myFcn, (void*)(threadArg*)&thrArg);
void* myFcn(void* arg)
{
threadArg* pThrArg = (threadArg*)arg;
int computeSomething = pThrArg->intData;
...
}
Keep in mind that thrArg should exist till the myFcn() uses it.
What you may want is
int x = reinterpret_cast<int>(arg);
This allows you to reinterpret the void * as an int.
//new_fd is a int
pthread_create(&threads[threads_in_use] , NULL, accept_request, (void*)((long)new_fd));
//inside the method I then have
int client;
client = (long)new_fd;
Hope this helps
Don't pass your int as a void*, pass a int* to your int, so you can cast the void* to an int* and copy the dereferenced pointer to your int.
int x = *static_cast<int*>(arg);
In my case, I was using a 32-bit value that needed to be passed to an OpenGL function as a void * representing an offset into a buffer.
You cannot just cast the 32-bit variable to a pointer, because that pointer on a 64-bit machine is twice as long. Half your pointer will be garbage. You need to pass an actual pointer.
This will get you a pointer from a 32 bit offset:
int32 nOffset = 762; // random offset
char * pOffset = NULL; // pointer to hold offset
pOffset += nOffset; // this will now hold the value of 762 correctly
glVertexAttribPointer(binding, nStep, glType, glTrueFalse, VertSize(), pOffset);
A function pointer is incompatible to void* (and any other non function pointer)
Well it does this because you are converting a 64 bits pointer to an 32 bits integer so you loose information.
You can use a 64 bits integer instead howerver I usually use a function with the right prototype and I cast the function type :
eg.
void thread_func(int arg){
...
}
and I create the thread like this :
pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);

error: cast from 'void*' to 'int' loses precision

I have a function with prototype void* myFcn(void* arg) which is used as the starting point for a pthread. I need to convert the argument to an int for later use:
int x = (int)arg;
The compiler (GCC version 4.2.4) returns the error:
file.cpp:233: error: cast from 'void*' to 'int' loses precision
What is the proper way to cast this?
You can cast it to an intptr_t type. It's an int type guaranteed to be big enough to contain a pointer. Use #include <cstdint> to define it.
Again, all of the answers above missed the point badly. The OP wanted to convert a pointer value to a int value, instead, most the answers, one way or the other, tried to wrongly convert the content of arg points to to a int value. And, most of these will not even work on gcc4.
The correct answer is, if one does not mind losing data precision,
int x = *((int*)(&arg));
This works on GCC4.
The best way is, if one can, do not do such casting, instead, if the same memory address has to be shared for pointer and int (e.g. for saving RAM), use union, and make sure, if the mem address is treated as an int only if you know it was last set as an int.
Instead of:
int x = (int)arg;
use:
int x = (long)arg;
On most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms. If you convert (void*) to (long) no precision is lost, then by assigning the (long) to an (int), it properly truncates the number to fit.
There's no proper way to cast this to int in general case. C99 standard library provides intptr_t and uintptr_t typedefs, which are supposed to be used whenever the need to perform such a cast comes about. If your standard library (even if it is not C99) happens to provide these types - use them. If not, check the pointer size on your platform, define these typedefs accordingly yourself and use them.
Casting a pointer to void* and back is valid use of reinterpret_cast<>. So you could do this:
pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int*
Then in myFcn:
void* myFcn(void* arg)
{
int* data = reinterpret_cast<int*>(arg);
int x = *data;
delete data;
Note: As sbi points out this would require a change on the OP call to create the thread.
What I am trying to emphasis that conversion from int to pointer and back again can be frough with problems as you move from platform to platform. BUT converting a pointer to void* and back again is well supported (everywhere).
Thus as a result it may be less error prone to generate a pointer dynamcially and use that.
Remembering to delete the pointer after use so that we don't leak.
Instead of using a long cast, you should cast to size_t.
int val= (int)((size_t)arg);
The proper way is to cast it to another pointer type. Converting a void* to an int is non-portable way that may work or may not! If you need to keep the returned address, just keep it as void*.
Safest way :
static_cast<int>(reinterpret_cast<long>(void * your_variable));
long guarantees a pointer size on Linux on any machine. Windows has 32 bit long only on 64 bit as well. Therefore, you need to change it to long long instead of long in windows for 64 bits.
So reinterpret_cast has casted it to long type and then static_cast safely casts long to int, if you are ready do truncte the data.
There is no "correct" way to store a 64-bit pointer in an 32-bit integer. The problem is not with casting, but with the target type loosing half of the pointer. The 32 remaining bits stored inside int are insufficient to reconstruct a pointer to the thread function. Most answers just try to extract 32 useless bits out of the argument.
As Ferruccio said, int must be replaced with intptr_t to make the program meaningful.
If you call your thread creation function like this
pthread_create(&thread, NULL, myFcn, reinterpret_cast<void*>(5));
then the void* arriving inside of myFcn has the value of the int you put into it. So you know you can cast it back like this
int myData = reinterpret_cast<int>(arg);
even though the compiler doesn't know you only ever pass myFcn to pthread_create in conjunction with an integer.
Edit:
As was pointed out by Martin, this presumes that sizeof(void*)>=sizeof(int). If your code has the chance to ever be ported to some platform where this doesn't hold, this won't work.
I would create a structure and pass that as void* to pthread_create
struct threadArg {
int intData;
long longData;
etc...
};
threadArg thrArg;
thrArg.intData = 4;
...
pthread_create(&thread, NULL, myFcn, (void*)(threadArg*)&thrArg);
void* myFcn(void* arg)
{
threadArg* pThrArg = (threadArg*)arg;
int computeSomething = pThrArg->intData;
...
}
Keep in mind that thrArg should exist till the myFcn() uses it.
What you may want is
int x = reinterpret_cast<int>(arg);
This allows you to reinterpret the void * as an int.
//new_fd is a int
pthread_create(&threads[threads_in_use] , NULL, accept_request, (void*)((long)new_fd));
//inside the method I then have
int client;
client = (long)new_fd;
Hope this helps
Don't pass your int as a void*, pass a int* to your int, so you can cast the void* to an int* and copy the dereferenced pointer to your int.
int x = *static_cast<int*>(arg);
In my case, I was using a 32-bit value that needed to be passed to an OpenGL function as a void * representing an offset into a buffer.
You cannot just cast the 32-bit variable to a pointer, because that pointer on a 64-bit machine is twice as long. Half your pointer will be garbage. You need to pass an actual pointer.
This will get you a pointer from a 32 bit offset:
int32 nOffset = 762; // random offset
char * pOffset = NULL; // pointer to hold offset
pOffset += nOffset; // this will now hold the value of 762 correctly
glVertexAttribPointer(binding, nStep, glType, glTrueFalse, VertSize(), pOffset);
A function pointer is incompatible to void* (and any other non function pointer)
Well it does this because you are converting a 64 bits pointer to an 32 bits integer so you loose information.
You can use a 64 bits integer instead howerver I usually use a function with the right prototype and I cast the function type :
eg.
void thread_func(int arg){
...
}
and I create the thread like this :
pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);