Assign values to a dereferenced void pointer - c

I'm doing a class in c++ that supports any kind of variable to help me in a future project. The thing is, when I try to assign a value to a void* variable, I get the error: void* is not a pointer-to-object type. Here is the code:
int main (void) {
void* a;
int x;
a = malloc(sizeof(int));
x = 120;
((int)(*a)) = x;
printf("%d",((int)*a));
free(a);
system("pause");
return 0;
}
I see it like I am trying to assign the value of x in the memory block reserved for a. I want that the value stored in x be stored in the memory block of a. Can any1 help me?

You probably want to do:
void* a;
int x;
a = malloc(sizeof(int));
x = 120;
*(int*)a = x;
printf("%d", * (int*)a);
free(a);

You're making it too complicated. Just cast a to be an int *, or better yet declare a as int * to start with.
int x = 120;
int * a ;
// now just cast the result from malloc as int*
if((a = (int *)malloc(sizeof(int))) == NULL){ //ALWAYS check
exit(-1);
}
*a = x;
There are slicker ways to do similar things in C++, but you appear to be primarily caught up in pointer syntax.

You need the cast as *(int*)(a) = x;.

Firstly, you must cast a to the appropriate pointer type and then de-reference it. Secondly, use a template- that's what they're for. Thirdly, malloc and free is baaaad, OK? Don't. If you think that this is good code, you need serious remedial C++. Fourthly, this is already done- boost::any serves this purpose.

There are other elegant ways to assign a variable of different types. For your current question you can follow the standard way as,
int* const a = new int;
//...
*a = 120;
//...
delete a;
Or just for this problem specifically,
int a = 120; // simple
[Note: In your current solution if you do,
*((int*)(a)) = x;
it might be breaking strict aliasing rule.]

Related

Initialization problem with malloc in C across functions

I'm having trouble understanding why the following code gives a garbage value.
EDIT: I need to use malloc, as it's part of the project requirements. I am well aware that it would be easier without using it, but I can't just not use it.
void int_init(int * x) {
x = malloc(sizeof(int));
*x = 7; //could be any number, 7 was chosen for fun
}
int main(void) {
int x;
int_init(&x);
printf("X: %d", x); //Should be "X: 7", is actually "X: 1595803432" or other garbage value
return 0;
}
I'm new to this, so apologies if this question is phrased poorly or is too trivial.
FINAL EDIT: Thanks to Vlad and Avi for helping me out. I may have misread the project description, since it seems like there is no way to use malloc to edit the original value of the variable. In my project, there is a struct that is associated with dynamically allocated memory (it contains an array of dynamically allocated structs), but I thought that it wanted us to dynamically allocate the entire struct. I apologize for the mistake, but am infinitely grateful for everyone's help.
In this function
void int_init(int * x) {
x = malloc(sizeof(int));
*x = 7; //could be any number, 7 was chosen for fun
}
the passed pointer was reassigned with the address of the dynamically allocated memory. So after that the pointer does not pointer to the original variable x declared in main.
As a result this statement
*x = 7; //could be any number, 7 was chosen for fun
assigns a value to the object in the dynamically allocated memory.
Moreover the function produces a memory leak because the allocated memory was not freed.
If you want to change the original variable x declared in main then define the function like
void int_init(int * x) {
*x = 7; //could be any number, 7 was chosen for fun
}
Taking into account your comment to my answer it seems you mean something like the following.
void int_init(int **x) {
*x = malloc(sizeof(int));
**x = 7; //could be any number, 7 was chosen for fun
}
int main(void) {
int *x;
int_init(&x);
printf("X: %d", *x);
free( x );
return 0;
}

Why would a double pointer be needed? In which example of a situation?

I have 2 pieces of codes shown below:
The first one is:
void input(int * a) {
(*a) = 10;
}
int main()
{
int * a = (int *) malloc(sizeof(int));
input(a);
printf("%d", *a);
free(a);
return 0;
}
And the second is:
void input(int ** a) {
*(*a) = 10;
}
int main()
{
int * a = (int *) malloc(sizeof(int));
input(&a);
printf("%d", *a);
free(a);
return 0;
}
I ran those two codes, and they showed the same output (which is 10). I wonder if they had the same meaning? Can you help me to point out the difference (if any)?
You demonstrated that you understand the need for a pointer to int,
i.e. in cases where the result/effect of a function is expected to be a modification of the int pointed to.
The need for a double pointer arises when the expected effect is a modification of a pointer.
The most popular need for having a pointer modified (or potentially modified) is the insertion, sorting or deletion operation of linked lists. The need to be able to modifiy the pointer which refers to the list (or the first element in the list).
For example StackOverflow has many questions along the lines of "Why does my linked-list deletion only work after the first element?".
About half of the answers propose to return the new head pointer and update it outside of the function. The other half recommends to use a double pointer to allow modifying it (the pointer-to head pointer) inside the function. Both works, it is a matter of taste/habit/opinion which approach to use.
You're ultimately setting it to an int value (10), so obviously an int** is not really needed in your example.
However, if you needed to set it to an int* value, then an int** would be needed.
For example:
void input(int** a) {
*a = (int*)malloc(sizeof(int));
}
int main()
{
int* a;
input(&a);
printf("%p", a);
free(a);
return 0;
}

How to pass the 2D array point to the other functions?

I have a question. I wanna pass my own 2D array to pass function.And in that function,i will change my own array.So,there is a return.What i exactly know is that the code blow can be accepted by the compiler.But, i don't why it is.When i take the int (* aaa)[3]; out of the main function,it works well.But , when it is inside the main,there will throw an exception that unable to use the uninitialized aaa.I wonder why could this happan.
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int (* aaa)[3];
int main() {
aaa = pass(aaa);
printf("%d", aaa[0][2]);
}
this could work.
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int main() {
int (* aaa)[3];
aaa = pass(aaa);
printf("%d", aaa[0][2]);
}
but,this can't work.
When int (* aaa)[3]; appears outside of any function, it aaa is automatically initialized to a null pointer. When it appears inside a function, it is not initialized.
The code aaa = pass(aaa); passes aaa to the routine named pass. This is a use of the value of aaa. When aaa has been initialized, that is fine. But, when aaa is not initialized and you attempt to pass its value, the behavior is not defined by the C standard. This is what the compiler is warning you about.
Next, let’s examine this code:
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
This code never uses the value of a that is passed to it. When a function is called, its parameter, a in this case, is given a value (which comes from the argument the caller passed). This parameter is a separate variable from the argument. Assigning a a value with a=(int*)malloc(sizeof(int*)*2); does not change the value of aaa in the calling routine. So this code assigns a new value to a without using the old value.
Because of that, the routine does not need a parameter passed to it. It could be written to use a local variable instead, like this:
int (*pass(void))[3] {
int (*a)[3] = malloc(2 * sizeof *a);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
The void in this means pass does not take any arguments.
Note that I changed malloc(sizeof(int*)*2 to malloc(2 * sizeof *a). sizeof(int*)*2 is wrong because it requests space for two pointers to int. But a points to arrays of three int, so, to get two of those, you need space for two arrays of three int. That is 2 * sizeof(int [3]). However, it is easier to write this as malloc(2 * sizeof *a), which means “two of whatever a points to”. This is also better because it reduces the frequency with which errors are made: Even if the declaration of a is changed, this sizeof *a will automatically adjust without needing to be edited. With sizeof(int [3]), any edit to the declaration of a would require another edit to the sizeof.
Also, I removed the (int*) to cast the result of malloc. In C, a void *, which is the type malloc returns, will automatically be converted to whatever object pointer type it is assigned to. There is no need for an explicit cast, and using an explicit cast can mask certain errors. (However, if you compile the program with a C++ compiler, it will complain about the lack of a cast, because the rules are different in C++.)
Since the function is returning a pointer to an array of three int, not an pointer to an int, I changed its declaration to int (*pass(void))[3].
With these changes, the program could be:
#include <stdio.h>
#include <stdlib.h>
int (*pass(void))[3]
{
int (*a)[3] = malloc(2 * sizeof *a);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int main(void)
{
int (*aaa)[3] = pass();
printf("%d\n", aaa[0][2]);
}
maybe this helps you a bit to see that C is 'flexible' when it comes to arrays.Because in the first part the assumed array declaration is given by datalen in malloc of the initAAA function and returns the pointer to the memory that is allocated. And still in the for loop we can access the data with index.
The second part of main declares just same data 'bbb' as the first 'aaa' but this time not as pointer and the initiation of the data fields with zeros (0) is done with the curly parenthesis. {}. A boring for loop thru all the indexes and set each data field with int 0 would just do it also. But who wants more code than needed.
#include <stdio.h>
#include <string.h>
int *initAAA(int *p, uint entrys) {
size_t datalen = entrys * sizeof *p;
p = malloc(datalen); // p is a pointer here.
// copy character '0' starting at address of p up to datalen addresses
// easier then writing a for loop to initiate safely.
memset(p, 0, datalen); // defined in string.h
return p;
}
int main(void) {
const uint maxAssets = 3;
const uint entrysPerAsset = 2;
int *aaa = NULL; // always a good idea, to set pointers to NULL before allocating memory for it. Because you can check if (aaa==NULL) initAAA(...
uint entrys = maxAssets * entrysPerAsset;
aaa = initAAA(aaa,entrys);
printf("address:%p items:%d \n",aaa, entrys);
for (uint i = 0; i < entrys; i++) {
printf("%d ", aaa[i]);
}
free(aaa); // malloc without free, bad idea!
printf("\n---\n");
int bbb[maxAssets][entrysPerAsset] = {0,0,0,0,0,0};
for (uint a = 0; a < maxAssets; a++) {
for (uint e = 0; e < entrysPerAsset; e++) {
printf("%d ", bbb[a][e]);
}
}
// bbb does not need free(bbb); because it is released with the function end.
// and yep, there was no malloc for bbb. so we are done.
}
and by the way. welcome to C.

Structures and linked list accessing.

#include <stdio.h>
int main(void)
{
typedef struct{
int a;
} cool;
cool x;
(&x)->a = 3;
x.a = 4;
}
I was wondering if the (&x)-> a does the same thing as the x.a. I coded both of them up, and it seemed that both of them changed the value of x.a. I know it must be a pointer on the left side of ->, but the (&x) seems to work without problem. Printing out x.a works for both of them, and gives me the correct answer. I looked up a lot about pointers, linked list, and structures and am still not able to find out the answer. Would it be possible to get an explanation? Thank you!
The -> operator expects a pointer on the left hand side. &x returns the address of x so it satisfies that requirement (even if it is totally redundant). To think about it another way...
cool *y = x;
y->a = 3;
The . operator expects a stack allocated struct on the left hand side. x is that, so x.a works fine.
You can also go the other way, if you have a pointer y you can dereference it with *y and use . on it: (*y).a. This is also totally redundant.
The & prefix operator returns the memory address of whatever object you put it in front of.
This means that you have to put it in front of objects that actually have a memory address. For example, literals and temporary expression results don't necessarily have an address. Variables declared with register storage class don't have an address, either.
Thus:
int i = 5;
&i; // works
&5; // Nope!
&(i + 1); // Nope!
&i + 1; // Works, because &i has higher precedence than +1.
So what does the address of an object give you? It is a pointer to the object. This is how you can do dynamic memory allocation using the heap. This is where functions like malloc() come in. And this is how you can build arbitrarily large data structures.
In C, arrays are represented as pointers. So arrays and pointers are often used interchangeably. For example:
char buffer[100]; // array
strcpy(buffer, "hello"); // strcpy is declared to take (char *, const char *)
The opposite of the address_of operator is the * dereference operator. If I declare a pointer to something, I can get "what it points at" using this syntax:
int i = 5;
int *pi = &i; // pointer to int. Note the * in the declaration?
i + i; // 10
i + *pi; // Also 10, because pi "points to" i
In the case where you have an aggregate type like a struct or union, you would have to do something like this:
struct {
int a;
} s;
s.a = 5;
/* ??? */ ps = &s; // pointer to s
s.a; // 5
(*ps).a; // Also 5, because ps points to s.
ps->a; // 5, because a->b is shorthand for (*a).b
This only works, of course, if you have a pointer to an object that CAN use the .member and that has an appropriately named member. For example, you can't do this:
i = 5;
pi = &i;
pi->a; // WTF? There is no i.a so this cannot work.
If you have a pointer, you can take the address of it. You then have a pointer to a pointer. Sometimes this is an array of pointers, as with the argv array passed to main:
int main(int argc, const char *argv[]);
int main(int argc, const char **argv); // Effectively the same.
You can do weird stuff with pointers to pointers:
int i = 5;
int j = 100;
int * pij;
for (pij = &i; i < j; ) {
if (i & 1) {
*pij *= 2;
pij = &j;
}
else {
i += 1;
*pij -= 1;
pij = &i;
}
}
Note: I have no idea what that code does. But it's the kind of thing you can wind up doing if you're working with pointers.

If I have a void pointer, how do I put an int into it?

I have an array of arbitrary values, so I have defined it as an array of void pointers, so I can point to any kind of information (like int, character arrays, etc). However, how do I actually assign an int to it?
Take for example these initializations:
void* data[10];
int x = 100;
My intuition would think this, but this gives a compile error:
data[0] = malloc(sizeof(int));
*(data[0]) = x;
Also I thought about using &x, but I would take the address of a local variable, which (to my understanding) would be cleared after exiting from the procedure. So if I have a local variable x, how would I get it into a void pointer type of variable correctly?
*((int*)data[0])=x;
will do it.
You might want to consider using a union. Something like this:
union myvalues
{
int i;
double d;
long l;
};
You could then have
union myvalues *foo[10];
foo[0] = malloc(sizeof(union myvalues));
foo[0]->i = x;
You can also typedef the union. sizeof(union myvalues) will be the maximum of sizeof the members. So if you have int i; and char c[40] in the union, sizeof(union myvalues) will be 40. Writing to i will then overwrite the first 4 characters in c (assuming your ints are 4 bytes).
*((int *)data[0]) = x;
A copy of x will be made, so the fact it is a local variable is not important.
for aliasing reasons its far better to do
mempcy( data[0], &x, sizeof( int ) );
As it happens the compiler will optimise the memcpy call out as sizeof( int ) is a constant value but it won't break various aliasing rules.
Although you can use a cast to make the assignment, it is probably much cleaner to write the code like:
void *data[ 10 ];
int x = 100;
int *p;
p = malloc( sizeof *p );
data[ 0 ] = p;
*p = x;
try this:
data[0] = malloc(sizeof(int));
*((int*)data[0]) = x;
or
(int) (*(data[0])) = x;
don't forget to
free (data[0]);
afterwards.

Resources