I understand this question has been asked before, but I can't quite narrow down what i've done wrong here
int* arr[2];
arr = (int (*)[2]) malloc(sizeof(int) * size);
why is visual studio telling me the expression must be a modifiable lvalue? I'm trying to create an array with a constant column size, since that will always be two, but the rows will vary.
arr is an array of pointers. You cannot assign anything to it once it is initialized. Since you are trying to set its value to be the return value of a call to malloc, you probably want it be a pointer to an array. In that case, use:
int (*arr)[2];
Also, don't cast the return value of malloc. See Do I cast the result of malloc?.
Use
int (*arr)[2];
arr = malloc(sizeof(*arr) * size);
// ^^^^^^^^^^^^ We are speculating this is what you need,
// not sizeof(int)
If you want arr to point to an array of 15 x 2 objects, you will need to use:
arr = malloc(sizeof(*arr) * 15);
you have an array of pointers.... that array can't be used as a pointer itself, only the array entries are pointers.
you need a pointer to pointers, int **, unless you are wanting an array of ints, then you just int* arr
Did you consider using a struct? Then the syntax is a little more straight forward.
#include <stdlib.h>
typedef struct Two Two;
struct Two{
int b[2];
};
int main(){
int size = 100;
Two* two = malloc(sizeof(Two)*size);
return 0;
}
Related
I have noticed that pointers are 4 bytes while ints are 2 bytes. When I make a declaration such as:
int * myGreatArray[50];
am I declaring an array of 50 pointers to ints? I thought I was declaring a pointer to an array of integers, which is functionally the same as
int ** myGreatArray = malloc(50 * sizeof(int *));
However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.
https://www.tutorialspoint.com/cprogramming/c_array_of_pointers.htm
Can anyone clarify this for me?
It is a question of precedence of operators.
int * myGreatArray[50]; // array of 50 pointers to int
int (*ptArray)[50]; // pointer to array of 50 ints
int * myGreatArray[50];
is indeed creating an array of pointers to int. If you wanted a pointer to an array of int, it would be written as
int (*myGreatArray)[50];
However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.
Depends on what you are trying to do. It's useful for creating "jagged" 2D arrays, where each "row" can be a different length:
for ( size_t i = 0; i < 50; i++ )
myGreatArray[i] = malloc( sizeof *myGreatArray[i] * some_length(i) );
where some_length(i) represents the number of elements for a particular "row". It can also be used to point to existing arrays:
int foo[] = {1, 2, 3};
int bar[] = {4, 5, 6, 7, 8};
...
int *myGreatArray[] = {foo, bar, ...};
When you are writing this declaration:
int * myGreatArray[50];
its the same as writing -
int ** myGreatArray = malloc(50 * sizeof(int *));
and you will get an array of 50 pointers to int, while if you will use this line:
int myGreatArray[50];
or:
int* myGreatArray = (int*)malloc(sizeof(int)*50)
you will get an array of 50 int variables.
I hope that my comment was helpful for you :D
and if you still have questions ask and i will answer you ASAP.
Have a great day ;)
Declaring an array:
int * myGreatArray[50];
This is an array that stores 50 pointers to int. Be aware that it does not allocate the storage for those integers, just for the storage of the pointers.
int arr[50]; //array of 50 integers
int * parr = arr; /*pointer to an int, which may be
the beginning of an array*/
Passing to a function:
This is exactly what I was hoping I'd discover, so when passing an array into a function, is it more efficient to pass a pointer to an array as opposed to an array of pointers? I'd think yes. – Michael Hackman
The two function definitions:
void doStuffToArray(int ** array, size_t len)
{
//dostuff
}
and
void doStuffToArray(int * array[], size_t len)
{
//dostuff
}
are functionally identical. When you pass an array, the function actually receives a pointer to the array.
To call the functions, you can pass the array (devolves to pointer to the beginning of the array, (recommended) or a pointer to the beginning of the array (not recommended for full arrays, but is useful to pass pointers to sections of arrays):
int arr[10] = {};
doStuffToArray(arr, sizeof(arr)/sizeof(arr[0])); //functionally identical
doStuffToArray(&arr[0], sizeof(arr)/sizeof(arr[0])); //functionally identical
When passing an array of pointers, there are two function definitions that can be used, e.g. argv is an array of pointers to char arrays:
int main(int argc, char * argv[]){return 0;} //functionally identical
int main(int argc, char ** argv ){return 0;} //functionally identical
My advice is to use the array notation (with the []) as this is a declaration of intent, instead of the equivalent but more ambiguous pointer notation.
If you know how big the array is, then argv could have been defined as an 'array of arrays' char argv[][] which would be great, but can't be done. When defining a function, only the first array dimension can be undefined, any further dimensions have to be defined. If you know how big it is though, there is nothing to stop you from creating a function:
void doStuffToMyArray( int array[][10]){
/*...*/
}
In fact in this call
malloc(50 * sizeof(int));
there is allocated neither array.:) There is allocated an extent of memory. You can interpret it in various ways.
For example you can write
int *myGreatArray = malloc(50 * sizeof(int));
char *myGreatArray = malloc(50 * sizeof(int));
or even like
long *myGreatArray = malloc(50 * sizeof(int));
provided that sizeof( long ) is equal to 2 * sizeof( int ).
or like
int ( *myGreatArray )[50] = malloc(50 * sizeof(int));
The only requirement is that there was allocated enough memory for the object(s) you are going to store there.
If you want to allocate dynamically an extent of memory for an array similar to this declaration
int * myGreatArray[50];
then you should write
int ** myGreatArray = malloc(50 * sizeof(int *));
^^^^^^ ^^^^^
If you want to allocate dynamically an extent of memory for an array similar to this declaration
int myGreatArray[50];
that is an array of 50 objects of type int then you should write
int * myGreatArray = malloc(50 * sizeof(int));
^^^^^ ^^^^^
I have the following struct:
struct Map {
void* arr; // includes pointers to certain blocks of memory
int mem_block_count;
};
The void* arr holds pointers to certain cells in memory. Each cell holds a void* pointer to another cell in memory (as a linked list) a char* string, and a value with its own size.
You should be able to grab one of these pointers to a cell by doing arr[i] where i is an index - is this right?
I am trying to access the first pointer to one of these cells, which is probably arr[0]. Then, I want to get access to the pointer to the next cell in memory. But this is of void type. So how do I get at it? For getting access to the char*, I just move forward in memory, and then do a strcpy. But how do I get access/deref the next pointer?
EDIT: I also thought about casting the void pointer to an int, but I'm not sure I would get the right value. Something like:
int *next_pointer;
next_pointer = (int*) map->arr[i]
But is this not preserving the pointer to the pointer when I cast this as an int? How do I dereference a pointer to a pointer correctly?
EDIT - Couldn't I also, because it is a linked list of pointers, also do something like - map->arr + index * sizeof(void*) to get to the start of a given cell?
You can't use array indexing on a void pointer, as it really just a generic pointer without a type. And if there's no type then there's no way of adding the correct offset to the base memory address. You have to cast it to the correct structure before using array indexing:
((struct some_structure *) arr)[1]
You need pointers to pointers.
#include <stdio.h>
#include <stdlib.h>
struct Map {
void **arr; // includes pointers to certain blocks of memory
int mem_block_count;
};
int main(void) {
struct Map map = {0};
int a1[100];
double a2[100];
char a3[100];
map.arr = malloc(3 * sizeof *map.arr);
if (!map.arr) /* error */;
a1[42] = 42;
a2[42] = 42;
a3[42] = 42;
map.mem_block_count = 3;
map.arr[0] = a1;
map.arr[1] = a2;
map.arr[2] = a3;
printf("%d %f %c\n", ((int *)(map.arr[0]))[42],
((double *)(map.arr[1]))[42],
((char *)(map.arr[2]))[42]);
free(map.arr);
return 0;
}
I have an array of void-Pointers and want to access the elements (inititialize them), but it do not work:
void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);
int i=0;
for(i=0; i<10; i++)
*(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too
I guess, the reason why this won´t work is that on the left side is the result of element i. But i don´t have an idea how to do this
There are two ways to initialize arrays in C:
On the stack (which will handle memory for you since it will be cleaned up when your function ends)
In the heap (which will require you to handle allocation and freeing on your own).
If you would like to use the stack, you could initialize your array like this...
#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
You can similarly define your array in the heap as follows...
#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
free(arr);
It is important to remember that an array (besides arrays assigned in the stack, which have some additional attributes such as length) is essentially just a pointer to the first element, and the operation arr[i] is the same as moving i*sizeof(elem) bytes away from the first element, and accessing the memory there. If you would like to get a pointer to the ith index in the array, then you would use notations such as...
void *indexPtr = arr + i;
or
void *indexPtr = &( arr[i] );
In this fashion, an array of void*'s would be of type void **, since the variable is a pointer to the first member of the array, which is a pointer. This can be a bit confusing, but just always try to keep in mind what type the elements of the array are, and creating a pointer to them. So if the array is of type int, then the array would be of type int or int[], but if you are storing pointers to integers, you would initialize an array of type int * in either of these two forms...
int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];
Also note that you are storing pointers, so if you run the code...
int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = &i;
}
Although it may seem to be that the values pointed to in the array would be as follows- [0, 1, 2, 3], but in reality it would be [4, 4, 4, 4], since what you actually have is an array of pointers all pointing to the variable i in your function, so whenever you change that, the values pointed to in the array will all be changed.
I hope this helped
You need to change this line
void* arr = (void*)malloc(sizeof(void*)*10);
to this
void** arr = malloc(sizeof(void*)*10);
You can't dereference a void pointer. That's the whole point of void pointers.
Dereferencing a pointer provides you with access to the item that's found at the address the pointer points to. With a void pointer, however, you don't know how large the target object is (is it a 1B character or a 100B struct?). You have to cast it to a specific pointer type before dereferencing it.
Adding (or subtracting) an integer i to a pointer is then defined as adding i-times sizeof(*pointer) to the pointer's content. (You can only tell sizeof(*pointer) if your pointer has a specific type. Pointer arithmetic with void pointers makes no sense).
As for (arr+n)= anyptr;, arr+n is just an address. It's not a value you can assign something to (not an lvalue).
Suppose I have:
int (* arrPtr)[10] = NULL; // A pointer to an array of ten elements with type int.
int (*ptr)[3]= NULL;
int var[10] = {1,2,3,4,5,6,7,8,9,10};
int matrix[3][10];
Now if I do,
arrPtr = matrix; //.....This is fine...
Now can I do this:
ptr = var; //.....***This is working***
OR is it compulsory to do this:
ptr= (int (*)[10])var; //....I dont understand why this is necessary
Also,
printf("%d",(*ptr)[4]);
is working even though we declare
int (*ptr)[3]=NULL;
^^^
In some cases, Name of Array is Pointer to it's First Location.
So, when you do,
ptr = var;
You are assigning address of var[0] to ptr[0]
int var[10] declaration makes var as an int pointer
As both are int pointers, the operation is valid.
For Second Question,
When you declare a Pointer, It points to some address.
Say
int * ptr = 0x1234; //Some Random address
now when you write ptr[3], it's 0x1234 + (sizeof(int) * 3).
So Pointer works irrespective of it's declared array size.
So when ptr = NULL,
*ptr[4] will point to NULL + (sizeof(int) * 4)
i.e. A Valid Operation!
ptr and var aren't compatible pointers because ptr is a pointer to an array of 3 ints and var is an array of 10 ints, 3 ≠ 10.
(*ptr)[4] works likely because the compiler doesn't do rigorous boundary checks when indexing arrays. This probably has to do with the fact that a lot of existing C code uses variable-size structures defined something like this:
typedef struct
{
int type;
size_t size; // actual number of chars in data[]
unsigned char data[1];
} DATA_PACKET;
The code allocates more memory to a DATA_PACKET* pointer than sizeof(DATA_PACKET), here it would be sizeof(DATA_PACKET)-1+how many chars need to be in data[].
So, the compiler ignores index=4 when dereferencing (*ptr)[4] even though it's >= 3 in the declaration int (*ptr)[3].
Also, the compiler cannot always keep track of arrays and their sizes when accessing them through pointers. Code analysis is hard.
ptr is a pointer to array of 3 integers, so ptr[0] will point to the start of the first array, ptr[1] will point to the start of the second array and so on.
In your case:
printf("%d",(*ptr)[4]);
works as you print the element no 5 of the first array
and
printf("%d",(*ptr+1)[4]);
print the element no 5 of the second array ( which of course doesn't exists)
for example the following is the same as yours
printf("%d",ptr[0][4]);
but this doesn't mean that you depend on this as var is array of 10 integers, so ptr has to be decelared as
int *ptr = NULL
in this case to print the element no 5
printf("%d", ptr[4]);
#define STRMAX 50
struct Person {
char sName[STRMAX];
int iAge;
};
typedef struct Person PERSON;
int main() {
PERSON *personen[1];
personen[0]->sName = "Pieter";
personen[0]->iAge = 18;
return 0;
}
This code generates an error on personen[0]->sName = "Pieter"; saying incompatible types in assignment. Why?
You don't want an array of pointers. Try
PERSON personen[1];
And like others have said, use the strcpy function!
Don't try to assign arrays. Use strcpy to copy the string from one array to the other.
...sName is an array of chars while "Pieter" is a const char*. You cannot assign the latter to the former. The compiler is always right :)
Change
PERSON *personen[1];
to
PERSON personen[1];
and use strcpy to copy the string.
strcpy(personen[0]->sName,"Pieter");
I agree with the above but I figured it was also important to include the "why"
int a; // is an integer
int *b; // pointer to an integer must be malloced (to have an array)
int c[]; // pointer to an integer must also be malloced (to have an array)
int d[5]; // pointer to an integer bu now it is initialized to an array of integers
to get b and c from simple pointers and give them memory to match d use the following to give them memory space
b = (int *) malloc(sizeof(int)*5);
where it casts the pointer returned from malloc to an int pointer, and creates a memory block of 5 times the size of an integer (thus it will hold 5 integers like d)