Invalid conversion while allocating memory with alloca - c++

This code
#include "alloca.h"
String str = "abc";
unsigned int *i;
void setup() {
Serial.begin(9600);
i = alloca(StringLength() * sizeof(i));
unsigned int j[StringLength() * sizeof(i)];
}
int StringLength() {
return str.length();
}
void loop() {
}
gives me the following error messages:
sketch_dec11f.cpp: In function ‘void setup()’:
sketch_dec11f.cpp:14:7: error: invalid conversion from ‘void*’ to ‘unsigned int*’
What am I doing wrong?
(tried it with malloc() as well, also didn't work!)

You definitely don't want alloca(). That's an allocation that is on the stack of the function and only lasts for the duration of the call. It lets you have dynamic arrays that go away on function return (in C++ you could do this with RAII, but in C alloca was the only way).
You just need a cast in your allocation. Try i = (unsigned int *)malloc(StringLength() * sizeof(*i)). Note the sizeof(*i). That's the size of one member: sizeof(i) is the size of the pointer and is not likely to be related to what's inside.

Malloc and alloca return void * pointers. Just change
i = alloca(StringLength() * sizeof(i));
to
i = (unsigned int *)alloca(StringLength() * sizeof(i));

I am not sure of alloca, but malloc return's void * and C++ unlike C doesn't support implicit conversion from void * to any other pointer type. This is one of the many areas where C++ differs from C.

Cast the returning pointer from alloca:
i = (unsigned int *) alloca(StringLength() * sizeof(i));

In C++, void pointers are not implicitly convertible to other pointers, unlike in C. Therefore you need a cast:
i = static_cast<unsigned int *>(alloca(StringLength() * sizeof(i)));

Related

C vs. C++, handling of void** pointers

I found out that using a C compiler the code below works but not with a C++ compiler. I understand that casting to void** is the correct usage but I can't understand why it compiles with the C compiler even if I use the void* (commented out).
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
Can someone explain why this is the case?
In C there is allowed to assign a pointer of the type void * to a pointer of other type. This takes place in this call
fn((void *)&pvalue)
where the argument has the type void * that is assigned to the function parameter that has the type void **.
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
However such an assignment in general is unsafe. For example the value of a pointer of the type void * can not be properly aligned to be assigned to a pointer of other type.
So it was decided to not allow such an assignment in C++ to make programs more safer.
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
It compiles because void* is implicitly convertible to other pointers in C.
fn((void **)&pvalue); // correct, works for both C/C++
This may be well-formed because of the cast, the standard doesn't technically give explicit guarantee that conversion to void** and back yields the same address.
While this may be likely to work in practice, there is no reason to not use void* as the function argument instead, which does have the guarantee. As a bonus, you won't need the cast in the call. Like this:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
Of course, this is assuming type erasure is needed in the first place. Avoid void* when it is not needed.
For avoidance of doubt, there is nothing correct in
fn((void **)&pvalue);
It is just as incorrect as
fn((void *)&pvalue);
The correct way to use the API is to do
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
or
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
with
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
You're not allowed to access an object using any other pointer type, other than the declared type, compatible type, or a character type. Furthermore, while void * is used as a generic pointer type to all sorts of objects in C, there is no generic pointer to a pointer type in C - other than void *!
And this is the reason why the void ** is almost always a sign of a design error in APIs - most usages are just wrong.

unable to typecast from float* to char*

error while pointer typecasting
without typecasting the float* to char*, the code runs fine, but when I tyepcast it, it gives the error "cannot convert ‘float*’ to ‘char*’ in initialization", even though the float* and char* will be of same size, i just wanted to try it.
#include <stdio.h>
#include <iostream>
using namespace std;
int processing_block(char*,short*,short*,short*,char*,bool*,bool*);
#define monitor_w 640
#define monitor_h 480
int main()
{
short w=monitor_w/1.05, h=monitor_h/1.05;
short x=monitor_w/2, y=monitor_h/2;
float zoomer=0.5f;
bool resume = false;
bool fix1 = false;
float *pfz= &zoomer;
short *psx= &x;
pfz=(char*)pfz;
char *pcz= pfz;
psx=(char*)psx;
char *pcx= psx;
processing_block(psx,&y,&w,&h,pcz,&resume,&fix1);
cout<<"\nx-\t"<<x<<"\ny-\t"<<y<<"\nw-\t"<<w<<"\nh-\t"<<h<<"\nzoomer-\t"<<zoomer<<"\nresume-\t"<<resume<<"\nfix1-\t"<<fix1<<endl;
return 0;
}
int processing_block(short* px,short* ya,short* wa,short* ha,char* pzoom,bool* resume,bool* fix1)
{
*pzoom=0.02+(*pzoom);
if((*px)-(*ya)>25)
*resume = true;
else{
*fix1= true;
*pzoom=10.0f;
}
}
Your compiler is correct. char* is not implicitly convertible to float* and vice versa.
All data pointers can however be explicitly converted (reinterpreted) to all other data pointer types, so following would be well-formed:
char *pcz = reinterpret_cast<char*>(pfz);
Note that although reinterpretation is well formed, another matter is whether indirection through the reinterpreted pointer has well defined behaviour. If the original type and the new type are not pointer-interconvertible, then the behaviour would be undefined.
char, unsigned char, and std::byte are exceptional in that indirection through a pointer to them is well defined even if the pointer was reinterpreted from any other type as long as the pointed object exists - although, remember that behaviour is undefined if you read an indeterminate value.
Instead of:
pfz=(char*)pfz; // Does nothing, maybe give an error (assigning char* to float*)
char *pcz= pfz; // Tries to assign pfz (float*) to pcz (char*)
psx=(char*)psx; // Same
char *pcx= psx; // Same
You should do:
char *pcz= (char*) pfz;
char *pcx= (char*) psx;

error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

Getting error:
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
on g++
on the following code:
void* func(void *s)
{
int i = 0;
int self = (int *)s;
printf("Thread Entered: %d\n", self);
sm.lock(self);
// Critical section (Only one thread
// can enter here at a time)
for (i=0; i<MAX; i++)
ans++;
sm.unlock(self);
}
You need to change int self = (int *)s; to int self = *((int *)s); or to int * self = (int *)s;.
You need to think of these as two different things. One is a pointer to memory where the value is stored (int*) and the other is an actual value (int).
Looking at your function declaration void* func(void *s), your s parameter is of type void, this will need to be int if you wish to convert it.
Your data types seem a bit mixed, which just doesn't fly do well in C/C++. Can you clean it? If you are using this function with pthread_create(), as per the documentation with example for this function, try..
// your pthread_create call..
int SOME_INT = 123;
s = pthread_create(&thread_id, &attr, &thread_start, &SOME_INT);
//...and your function
void* func(void *s)
{
int self = (int*) s;
Pointers can be confusing. See if that above code looks similar, in particular to passing the last parameter for pthread_create as a pointer reference. And then try your original code. It might just be that it wasn't passed as a reference.
See what that yields you, else try storing it as a pointer and then converting on use.
void* func(void *s)
{
int *self = s;
sm.lock(*self); // but can give a potential race condition.
In the second line of the function body, I suspect you were trying obtain the value at s (as an int pointer), but you actually cast it directly to an int. That would yield the address in s rather than the value stored there.

Can I assign void* pointer to char* pointer?

I am coding for re-implementing malloc function. I saw a man's example code , which has some strange code like this
struct s_block{
size_t size; // size per block
int free; // whether free flag exist
t_block pre;
t_block next;
void *magic_ptr;
int padding; // bytes for padding
char data[1]; // first byte of data, i.e. the address returned from malloc
};
typedef struct s_block *t_block;
t_block get_block(void *p) {
char *tmp;
tmp = p;
...
}
but I use gcc or g++ to compile this code, the error is "can't use void* pointer to char* pointer".
I want to know where the question arise? gcc or g++ ? code is error?
In C++ you must explicitly cast a void* to another type:
char *tmp = static_cast<char*>(p);
In C this isn't the case and you can assign a void* to any pointer type without casting.
You have to use explicit cast to cast void* to any other pointer whereas other way is implicit.
char* temp = static_cast<char*> (p);
One thing to note here is your initial pointer ( which currently is represented by void* ) should be of type char* to avoid any issues.
That is valid C code, the error you're getting is from the (more strict) C++ standard. If you want to compile that in C++, simply cast the pointer to char * explicitly.

Increment void pointer by one byte? by two?

I have a void pointer called ptr. I want to increment this value by a number of bytes. Is there a way to do this?
Please note that I want to do this in-place without creating any more variables.
Could I do something like ptr = (void *)(++((char *) ptr)); ?
You cannot perform arithmetic on a void pointer because pointer arithmetic is defined in terms of the size of the pointed-to object.
You can, however, cast the pointer to a char*, do arithmetic on that pointer, and then convert it back to a void*:
void* p = /* get a pointer somehow */;
// In C++:
p = static_cast<char*>(p) + 1;
// In C:
p = (char*)p + 1;
No arithmeatic operations can be done on void pointer.
The compiler doesn't know the size of the item(s) the void pointer is pointing to. You can cast the pointer to (char *) to do so.
In gcc there is an extension which treats the size of a void as 1. so one can use arithematic on a void* to add an offset in bytes, but using it would yield non-portable code.
Just incrementing the void* does happen to work in gcc:
#include <stdlib.h>
#include <stdio.h>
int main() {
int i[] = { 23, 42 };
void* a = &i;
void* b = a + 4;
printf("%i\n", *((int*)b));
return 0;
}
It's conceptually (and officially) wrong though, so you want to make it explicit: cast it to char* and then back.
void* a = get_me_a_pointer();
void* b = (void*)((char*)a + some_number);
This makes it obvious that you're increasing by a number of bytes.
You can do:
++(*((char **)(&ptr)));