Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid conversion from std::size_t* to long unsigned int*

Tags:

c++

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

like image 969
bergercookie Avatar asked May 09 '19 13:05

bergercookie


People also ask

Is Size_t same as unsigned long?

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.

Is std :: Size_t unsigned?

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.

Is Size_t always unsigned int?

No. size_t can and does differ from unsigned int .

Can you cast Size_t to int in C?

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.


4 Answers

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.

like image 148
NathanOliver Avatar answered Oct 23 '22 05:10

NathanOliver


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.

like image 44
Lightness Races in Orbit Avatar answered Oct 23 '22 05:10

Lightness Races in Orbit


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.

like image 42
dbush Avatar answered Oct 23 '22 07:10

dbush


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));
like image 21
Simo Simov Avatar answered Oct 23 '22 06:10

Simo Simov