On a raspberry pi - arv7l I'm compiling the following C++ program
#include <iostream>
void fun(unsigned long int* i)
{
std::cout << *i << std::endl;
}
int main()
{
std::size_t i = 1;
fun(&i);
return 0;
}
For the code above I'm getting the following error:
a.cpp: In function 'int main()':
a.cpp:12:9: error: invalid conversion from 'std::size_t* {aka unsigned int*}' to 'long unsigned int*' [-fpermissive]
fun(&i);
^~
a.cpp:3:6: note: initializing argument 1 of 'void fun(long unsigned int*)'
void fun(unsigned long int* i)
^~~
I understand that on 32-bit systems size_t is 32 bit and may be different than unsigned long
but still this should compile?
With regards to the sizes of the various types:
sizeof(size_t): 4
sizeof(unsigned int): 4
sizeof(unsigned long int): 4
sizeof(size_t*): 4
sizeof(unsigned int*): 4
sizeof(unsigned long int*): 4
System: Linux turtlebot 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l GNU/Linux
Compiler: gcc-6.3
One standard recommendation is that the size_t be at most as big as an unsigned long. So you may think that we can use unsigned long in the place of size_t, but unsigned long on 64-bit system, if the OS ins Windows, will be of 32-bits, but size_t will be of 64-bits.
std::size_t is the unsigned integer type of the result of the sizeof operator as well as the sizeof... operator and the alignof operator (since C++11). The bit width of std::size_t is not less than 16.
No. size_t can and does differ from unsigned int .
Just use casting. You can safely convert size_t to int by checking its range before casting it. If it is outside the valid int range, you can't. Test against INT_MAX to ensure no possible signed integer overflow before casting it.
I understand that on 32-bit systems size_t is 32 bit and may be different than unsigned long but still this should compile?
This is not correct. You are correct that the types have the same size, but size is not what makes a type a type. For instance we have signed char
, unsigned char
, and char
. All three have a size of 1
, but all three are distinct types named by the standard.
In your case size_t*
is a unsigned int*
and since that is a different type than a long unsigned int*
, you cannot implicitly cast it to one.
Why should it compile? You have an unsigned int
(on your system a std::size_t
), and you are pretending that it is a long unsigned int
.
But it isn't, regardless of size, so it doesn't work.
There is more to types than their width.
Use consistent types for portable code.
A unsigned long int*
and a unsigned int*
are not the same type, even though the sizes are the same.
There are implicit conversions between integer types, however this does not apply to pointers to integer types which is why you get the error.
You'll need to change either the type of the variable or the type of the function parameter for them to match.
In C++ types with different size modifiers are different even if same size. There are systems with sizeof(char) == sizeof(short int) == sizeof (int) == sizeof(long int) ...
Add a std::static_assert to your code to ensure that both types are equal size and than you may call the function like this:
fun(&reinterpret_cast<unsigned long&>(i));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With