Cannot convert argument 1 from " unsigned int *" to "size t *" - c++

I am working on Student Project and got SDK from site and building libraries on Visual Studio. Once I build libraries using cmake opened solution in VS and build in VS gives me above error. Not sure how to fix it.
This is proc where I get error.
pmdDllExport int pmdpGetSourceDataDescription (unsigned hnd, PMDDataDescription *result)
{
if (!idOk (hnd))
{
globalErrorMessage = "unknown handle";
return PMD_UNKNOWN_HANDLE;
}
SrcPluginData *dat = g_data[hnd];
int c_channels = 1;
//
dat->currentDD.type = PMD_USER_DEFINED_0; /* USER DEFINE TYPE DATA for O3D3xx data*/
dat->currentDD.subHeaderType = PMD_IMAGE_DATA;
dat->currentDD.img.numSubImages = 6;/* Mentions number of images in image data
buffer. We have six images*/
...
/* Get Size of image data buffer */
**dat->o3d3xxCamera->getFrameDataSize (& (dat->currentDD.size));**
dat->currentDD.PID = hnd;
dat->currentDD.DID = g_did;
/*Output this descriptor to calling function */
memcpy (result , &dat->currentDD, sizeof (PMDDataDescription));
return PMD_OK;
}
When I checked what is o3d3xxCamera->getFrameDataSize defined as it is defined as
int32_t getFrameDataSize (size_t *dataSize);
I looked at many queries and they say better to pass variable as type size_t When I checked what is dat->currentdd its struct. So I am not sure how to change this type to size_t.
/**<local datadescriptor of the current data */
PMDDataDescription currentDD;
struct PMDDataDescription
{
unsigned PID;
unsigned DID;
unsigned type;
unsigned size;
unsigned subHeaderType;
...

Do not be tempted to just reintepret_cast the pointer! That will not do what you want, unless size_t happens to be the same as unsigned int, which varies from platform to platform.
Instead, you'll want to use a temporary, and copy back when you're done:
size_t size = dat->currentDD.size; // this will promote as necessary
dat->o3d3xxCamera->getFrameDataSize(&size);
dat->currentDD.size = size; // write it back
One or other of the assignments may need a static_cast, if sizeof (size_t) differs from sizeof (unsigned int). This is fine, as it will be value-preserving (assuming that the value is representable in both types).

If the types have different sizes, you can't reliably cast!
The receiver will treat the pointer as a pointer to a variable with a different size from what you actually have, and there will be breakage (undefined behavior).
Simply change the structure to have
size_t size;
If you can't change the structure, then of course you can use a temporary for the call, then cast that value into the struct. That will work, assuming you never need the higher precision of size_t of course.

dat->o3d3xxCamera->getFrameDataSize (& (dat->currentDD.size));
This passes the address of dat->currentDD.size as parameter to the getFrameDataSize() function.
PMDDataDescription currentDD;
struct PMDDataDescription
{
unsigned PID;
unsigned DID;
unsigned type;
unsigned size;
currentDD.size is of type unsigned.
int32_t getFrameDataSize (size_t *dataSize);
The function expects the addess of a size_t.
Cannot convert argument 1 from " unsigned int *" to "size t *"
Apparently on your system size_t is typedef'ed to something different than unsigned int, making the two pointers incompatible. This might happen on 64-bit systems, where int is 32bit, but size_t is 64bit.
The easy fix is to simply cast the type (1):
dat->o3d3xxCamera->getFrameDataSize(& ( static_cast< size_t >(dat->currentDD.size) ) );
The Right Thing (tm) would probably (2) be to refactor PMDDataDescription to use size_t for its size member.
(1): I say it's easy, not that it's correct. I have no idea what PMDDataDescription is, what library it might come from, or what it is used for. I do not know what getFrameDataSize() does with its parameter. If it does pointer arithmetics on it, casting will break your application, and there is virtually nothing you can do about it because the two API's involved apparently to not agree on data types. We're looking at a very fragile setup here.
(2): You might not have control over its sources. You might be looking at something that is part of a specified API, i.e. cannot be changed for practical reasons. I'm just sayin' that properly constructed software shouldn't have run into this problem in the first place.

You cannot cast pointers. You should try instead to cast only 'unsigned char' into 'size_t', not 'unsigned char*' and 'size_t*'

Related

Why can't we use a void* to operate on the object it addresses

I am learning C++ using C++ Primer 5th edition. In particular, i read about void*. There it is written that:
We cannot use a void* to operate on the object it addresses—we don’t know that object’s type, and the type determines what operations we can perform on that object.
void*: Pointer type that can point to any nonconst type. Such pointers may not
be dereferenced.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*. Also, i am not sure if the above quoted statement from C++ Primer is technically correct because i am not able to understand what it is conveying. Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses". So can someone please provide some example to clarify what the author meant and whether he is correct or incorrect in saying the above statement.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*
It's indeed quite rare to need void* in C++. It's more common in C.
But where it's useful is type-erasure. For example, try to store an object of any type in a variable, determining the type at runtime. You'll find that hiding the type becomes essential to achieve that task.
What you may be missing is that it is possible to convert the void* back to the typed pointer afterwards (or in special cases, you can reinterpret as another pointer type), which allows you to operate on the object.
Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses"
Example:
int i;
int* int_ptr = &i;
void* void_ptr = &i;
*int_ptr = 42; // OK
*void_ptr = 42; // ill-formed
As the example demonstrates, we cannot modify the pointed int object through the pointer to void.
so since a void* has no size(as written in the answer by PMF)
Their answer is misleading or you've misunderstood. The pointer has a size. But since there is no information about the type of the pointed object, the size of the pointed object is unknown. In a way, that's part of why it can point to an object of any size.
so how can a int* on the right hand side be implicitly converted to a void*
All pointers to objects can implicitly be converted to void* because the language rules say so.
Yes, the author is right.
A pointer of type void* cannot be dereferenced, because it has no size1. The compiler would not know how much data he needs to get from that address if you try to access it:
void* myData = std::malloc(1000); // Allocate some memory (note that the return type of malloc() is void*)
int value = *myData; // Error, can't dereference
int field = myData->myField; // Error, a void pointer obviously has no fields
The first example fails because the compiler doesn't know how much data to get. We need to tell it the size of the data to get:
int value = *(int*)myData; // Now fine, we have casted the pointer to int*
int value = *(char*)myData; // Fine too, but NOT the same as above!
or, to be more in the C++-world:
int value = *static_cast<int*>(myData);
int value = *static_cast<char*>(myData);
The two examples return a different result, because the first gets an integer (32 bit on most systems) from the target address, while the second only gets a single byte and then moves that to a larger variable.
The reason why the use of void* is sometimes still useful is when the type of data doesn't matter much, like when just copying stuff around. Methods such as memset or memcpy take void* parameters, since they don't care about the actual structure of the data (but they need to be given the size explicitly). When working in C++ (as opposed to C) you'll not use these very often, though.
1 "No size" applies to the size of the destination object, not the size of the variable containing the pointer. sizeof(void*) is perfectly valid and returns, the size of a pointer variable. This is always equal to any other pointer size, so sizeof(void*)==sizeof(int*)==sizeof(MyClass*) is always true (for 99% of today's compilers at least). The type of the pointer however defines the size of the element it points to. And that is required for the compiler so he knows how much data he needs to get, or, when used with + or -, how much to add or subtract to get the address of the next or previous elements.
void * is basically a catch-all type. Any pointer type can be implicitly cast to void * without getting any errors. As such, it is mostly used in low level data manipulations, where all that matters is the data that some memory block contains, rather than what the data represents. On the flip side, when you have a void * pointer, it is impossible to determine directly which type it was originally. That's why you can't operate on the object it addresses.
if we try something like
typedef struct foo {
int key;
int value;
} t_foo;
void try_fill_with_zero(void *destination) {
destination->key = 0;
destination->value = 0;
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
try_fill_with_zero(foo_instance, sizeof(t_foo));
}
we will get a compilation error because it is impossible to determine what type void *destination was, as soon as the address gets into try_fill_with_zero. That's an example of being unable to "use a void* to operate on the object it addresses"
Typically you will see something like this:
typedef struct foo {
int key;
int value;
} t_foo;
void init_with_zero(void *destination, size_t bytes) {
unsigned char *to_fill = (unsigned char *)destination;
for (int i = 0; i < bytes; i++) {
to_fill[i] = 0;
}
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
int test_int;
init_with_zero(foo_instance, sizeof(t_foo));
init_with_zero(&test_int, sizeof(int));
}
Here we can operate on the memory that we pass to init_with_zero represented as bytes.
You can think of void * as representing missing knowledge about the associated type of the data at this address. You may still cast it to something else and then dereference it, if you know what is behind it. Example:
int n = 5;
void * p = (void *) &n;
At this point, p we have lost the type information for p and thus, the compiler does not know what to do with it. But if you know this p is an address to an integer, then you can use that information:
int * q = (int *) p;
int m = *q;
And m will be equal to n.
void is not a type like any other. There is no object of type void. Hence, there exists no way of operating on such pointers.
This is one of my favourite kind of questions because at first I was also so confused about void pointers.
Like the rest of the Answers above void * refers to a generic type of data.
Being a void pointer you must understand that it only holds the address of some kind of data or object.
No other information about the object itself, at first you are asking yourself why do you even need this if it's only able to hold an address. That's because you can still cast your pointer to a more specific kind of data, and that's the real power.
Making generic functions that works with all kind of data.
And to be more clear let's say you want to implement generic sorting algorithm.
The sorting algorithm has basically 2 steps:
The algorithm itself.
The comparation between the objects.
Here we will also talk about pointer functions.
Let's take for example qsort built in function
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
We see that it takes the next parameters:
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
And based on the article that I referenced above we can do something like this:
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Where you can define your own custom compare function that can match any kind of data, there can be even a more complex data structure like a class instance of some kind of object you just define. Let's say a Person class, that has a field age and you want to sort all Persons by age.
And that's one example where you can use void * , you can abstract this and create other use cases based on this example.
It is true that is a C example, but I think, being something that appeared in C can make more sense of the real usage of void *. If you can understand what you can do with void * you are good to go.
For C++ you can also check templates, templates can let you achieve a generic type for your functions / objects.

C++ Cast from ‘std::__tuple... {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision

You may have to forgive me as I'm new to C++ and may have made some fundamental errors with the code I have worked up so far.
static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
read_result result;
tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);
result = (read_result)get<0>(rd_rec_size_result);
if (result != read_success )
{
return tuple<read_result, uint8_t*>(result, nullptr);
}
size = (uint32_t) get<1>(rd_rec_size_result);
if ( skip )
{
fseek(file, size, SEEK_CUR);
}
// ...
}
template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
T ret = 0;
read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);
if (result == read_success)
{
return tuple<read_result, T*>(result, &ret);
}
return tuple<read_result, T*>(result, nullptr);
}
When I compile this code I am getting this error:
cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
My intentions and what I am expected to do/happen:
In the declaration of m_scan_record, the size argument is declared with a & which is intended to allow me to pass the value by reference, analogous to using the REF c# keyword
I make a call to generic (template) function m_read_generic_t which is called with the specified type <unit32_t> and therefore (according to its definition) will return a type of tuple<read_result, uint32_t*>
Once I have the tuple returned by m_read_generic_t, I want to take the unit32_t value pointed to by the second value of the tuple, and put that value into the size variable mentioned at point 1, above, which presumably will then be accessible to the calling function one step further up the stack.
From the above points you can hopefully see that my intention (and I appreciate that I may be far away in reality!) is that at this line:
size = (uint32_t) get<1>(rd_rec_size_result);
all I am doing is simply grabbing a 'pointed to' value and putting it into a variable of a matching type, much like the oft-cited textbook example:
uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v; // x == 123
Clearly this is not what is really going on with my code, though, because if it were, I presume that the cast would be un-needed. But if I remove it, like this:
size = get<1>(rd_rec_size_result);
then I get a compile-time error:
a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"
I believe therefore that I am doing something badly wrong - but I can't work out what. Is this to do with the way I am taking the pointer out of the tuple; or is there something else going on when it comes to the getting a uint32_t value from a uint32_t* ?
This is all in a C++ environment on Ubuntu 20.04, FWIW
Many thanks in advance for any/all suggestions; please go easy on me!
tuple<read_result, uint32_t*> rd_rec_size_result = ...
The 2nd member of this tuple, as explicitly declared here, is a pointer to a uint32_t. That's what uint32_t * means, in C++.
size = (uint32_t) get<1>(rd_rec_size_result);
This retrieves the uint32_t * and attempts to convert it to a uint32_t. C++ does not work this way. Although this conversion can be forced your compiler has every right to believe that whatever this code is trying to do it must be wrong.
Perhaps I was wondering initially, your intention was to dereference the pointer. This is the reason for your compilation error, in any case. If your intention was to, truly, dereference this pointer, then this would've been a simple matter of changing this to
size = *get<1>(rd_rec_size_result);
However, that's not going to be the end of your troubles. Even after this compilation error is fixed, this way, the shown code will still be badly, badly broken.
This is because m_read_generic_t returns a pointer to a local object, which will get destroyed when the function returns, and attempting to dereference this pointer, here, will make demons fly out of your nose.
The real fix here is to change m_read_generic_t to not return a pointer as the 2nd value in the tuple in the first place, thus eliminating the compilation error in the first place.

Getting a pointer of a primitive type in a function

I have a union (ValueDefinition) with pointers of different datatypes in it and functions to create it. With String it works fine:
ValueDefinition CreateValDefString(String value){
ValueDefinition valDef = {.ValueString = new String(value)};
return valDef;
}
But when I do the same with e.g. uint8_t it compiles, but at runtime I get this error:
[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged
That's the code for the uint8_t:
ValueDefinition CreateValDefUint8(uint8_t value){
ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
return valDef;
}
What am I doing wrong? I tried it without "new" and with malloc, but I still get the same error.
Edit: As requested, the definition of ValueDefinition:
union ValueDefinition{
bool* ValueBool;
int8_t* ValueInt8;
int16_t* ValueInt16;
int32_t* ValueInt32;
uint8_t* ValueUInt8;
uint16_t* ValueUInt16;
uint32_t* ValueUInt32;
float* ValueFloat;
ulong* ValueULong;
String* ValueString;
};
In your code, it looks like C++ is throwing an error to a function to create a WString instead of uint8_t, hence the stacktrace in a completely separate header. Searching the source code in the repository for arduino shows that there is an error in WString.cpp here, which is what your compiler's detecting.
The github users suggest using a different string library, and since the bug hasn't been fixed you'll have to change, probably to the standard string library defined by C++ and not arduino. As the users have stated on github, arduino strings are notoriously unreliable.
In other words, this error has nothing to do with your code, but a question that I'd like to ask is "Why use unions in C++?" If you want to define a generic type just use templates, ex:
template<class T>
class ValueDefinition<T> {
private:
T typeDat;
public:
Valuedefinition(T t);
/* etc. */
}
Unions were made so that C could have a way to use generic typing by having several types share the data in the union. Another common use is taking advantage of the data types using the same memory to find the underlying binary of more complex types, such as using individual uint8_t values underlying a long long to find the value of its bits or using an int to get the binary value of a float, ex:
union foo {
uint8_t bits[4]; /* Represent the bits of 'data' */
long long int data;
}
union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong
However note that this is undefined behavior because unions are usually padded and architectures use a different form of endianess. Whatever you're doing, if you're using C++ there's a better way to implement your solution than using unions, since this was a feature meant for a language that had no generic typing in order to save memory.
Edit:
Initialize ValueDefinition using C's malloc like so:
union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */
Or with C++'s new:
union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */

Casting Function Pointer to Integer in C++

I have an array of unsigned integers that need to store pointers to data and functions as well as some data. In the device I am working with, the sizeof pointer is the same as sizeof unsigned int. How can I cast pointer to function into unsigned int? I know that this makes the code not portable, but it is micro controller specific. I tried this:
stackPtr[4] = reinterpret_cast<unsigned int>(task_ptr);
but it give me an error "invalid type conversion"
Casting it to void pointer and then to int is messy.
stackPtr[4] = reinterpret_cast<unsigned int>(static_cast<void *> (task_ptr));
Is there a clean way of doing it?
Edit - task_ptr is function pointer void task_ptr(void)
Love Barmar's answer, takes my portability shortcoming away. Also array of void pointer actually makes more sense then Unsigned Ints. Thank you Barmar and isaach1000.
EDIT 2: Got it, my compiler is thinking large memory model so it is using 32 bit pointers not 16 bit that I was expecting (small micros with 17K total memory).
A C-style cast can fit an octogonal peg into a trapezoidal hole, so I would say that given your extremely specific target hardware and requirements, I would use that cast, possibly wrapped into a template for greater clarity.
Alternately, the double cast to void* and then int does have the advantage of making the code stand out like a sore thumb so your future maintainers know something's going on and can pay special attention.
EDIT for comment:
It appears your compiler may have a bug. The following code compiles on g++ 4.5:
#include <iostream>
int f()
{
return 0;
}
int main()
{
int value = (int)&f;
std::cout << value << std::endl;
}
EDIT2:
You may also wish to consider using the intptr_t type instead of int. It's an integral type large enough to hold a pointer.
In C++ a pointer can be converted to a value of an integral type large enough to hold it. The conditionally-supported type std::intptr_t is defined such that you can convert a void* to intptr_t and back to get the original value. If void* has a size equal to or larger than function pointers on your platform then you can do the conversion in the following way.
#include <cstdint>
#include <cassert>
void foo() {}
int main() {
void (*a)() = &foo;
std::intptr_t b = reinterpret_cast<std::intptr_t>(a);
void (*c)() = reinterpret_cast<void(*)()>(b);
assert(a==c);
}
This is ansi compliant:
int MyFunc(void* p)
{
return 1;
}
int main()
{
int arr[2];
int (*foo)(int*);
arr[0] = (int)(MyFunc);
foo = (int (*)(int*))(arr[0]);
arr[1] = (*foo)(NULL);
}

casting object addresses to char ptrs then using pointer math on them

According to Effective C++, "casting object addresses to char* pointers and then using pointer arithemetic on them almost always yields undefined behavior."
Is this true for plain-old-data? for example in this template function I wrote long ago to print the bits of an object. It works splendidly on x86, but... is it portable?
#include <iostream>
template< typename TYPE >
void PrintBits( TYPE data ) {
unsigned char *c = reinterpret_cast<unsigned char *>(&data);
std::size_t i = sizeof(data);
std::size_t b;
while ( i>0 ) {
i--;
b=8;
while ( b > 0 ) {
b--;
std::cout << ( ( c[i] & (1<<b) ) ? '1' : '0' );
}
}
std::cout << "\n";
}
int main ( void ) {
unsigned int f = 0xf0f0f0f0;
PrintBits<unsigned int>( f );
return 0;
}
It certainly is not portable. Even if you stick to fundamental types, there is endianness and there is sizeof, so your function will print different results on big-endian machines, or on machines where sizeof(int) is 16 or 64. Another issue is that not all PODs are fundamental types, structs may be POD, too.
POD struct members may have internal paddings according to the implementation-defined alignment rules. So if you pass this POD struct:
struct PaddedPOD
{
char c;
int i;
}
your code would print the contents of padding, too. And that padding will be different even on the same compiler with different pragmas and options.
On the other side, maybe it's just what you wanted.
So, it's not portable, but it's not UB. There are some standard guarantees: you can copy PODs to and from array of char or unsigned char, and the result of this copying via char buffer will hold the original value. That implies that you can safely traverse that array, so your function is safe. But nobody guarantees that this array (or object representation) of objects with same type and value will be the same on different computers.
BTW, I couldn't find that passage in Effective C++. Would you quote it, pls? I could say, if a part of your code already contains lots of #ifdef thiscompilerversion, sometimes it makes sense to go all-nonstandard and use some hacks that lead to undefined behavior, but work as intended on this compiler version with this pragmas and options. In that sense, yes, casting to char * often leads to UB.
Yes, POD types can always be treated as an array of chars, of size sizeof (TYPE). POD types are just like the corresponding C types (that's what makes them "plain, old"). Since C doesn't have function overloading, writing "generic" functions to do things like write them to files or network streams depends on the ability to access them as char arrays.