C Initialize array to pointers from inside function - c

I need to understand how to initialize an array of pointers from inside the function in C, why I must initialize the array with (*object_array) not just object_array, **object_array or ***object_array what are ***pointer exactly mean? I do understand single pointer and its math but double+ pointers are really confusing me.
size_t array_size = 5;
Object **object_array;
function_init_array(&object_array, array_size);
void function_init_array(Object ***object_array, size_t array_size) {
(*object_array) = mnabil_memory_allocate(array_size * sizeof(Object*));
}

Related

array of pointers to ints? or pointer to an array of ints?

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));
^^^^^ ^^^^^

Passing dynamically allocated array as a parameter in C

So... I have a dynamically allocated array on my main:
int main()
{
int *array;
int len;
array = (int *) malloc(len * sizeof(int));
...
return EXIT_SUCCESS;
}
I also wanna build a function that does something with this dynamically allocated array.
So far my function is:
void myFunction(int array[], ...)
{
array[position] = value;
}
If I declare it as:
void myFunction(int *array, ...);
Will I still be able to do:
array[position] = value;
Or I will have to do:
*array[position] = value;
...?
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype:
void myFunction(int matrix[][], ...);
Or
void myFunction(int **matrix, ...);
...?
If I declare it as:
void myFunction(int *array, ...);
Will I still be able to do:
array[position] = value;
Yes - this is legal syntax.
Also, if I am working with a dynamically allocated matrix, which one
is correct to declare the function prototype:
void myFunction(int matrix[][], ...);
Or
void myFunction(int **matrix, ...);
...?
If you're working with more than one dimension, you'll have to declare the size of all but the first dimension in the function declaration, like so:
void myFunction(int matrix[][100], ...);
This syntax won't do what you think it does:
void myFunction(int **matrix, ...);
matrix[i][j] = ...
This declares a parameter named matrix that is a pointer to a pointer to int; attempting to dereference using matrix[i][j] will likely cause a segmentation fault.
This is one of the many difficulties of working with a multi-dimensional array in C.
Here is a helpful SO question addressing this topic:
Define a matrix and pass it to a function in C
Yes, please use array[position], even if the parameter type is int *array. The alternative you gave (*array[position]) is actually invalid in this case since the [] operator takes precedence over the * operator, making it equivalent to *(array[position]) which is trying to dereference the value of a[position], not it's address.
It gets a little more complicated for multi-dimensional arrays but you can do it:
int m = 10, n = 5;
int matrixOnStack[m][n];
matrixOnStack[0][0] = 0; // OK
matrixOnStack[m-1][n-1] = 0; // OK
// matrixOnStack[10][5] = 0; // Not OK. Compiler may not complain
// but nearby data structures might.
int (*matrixInHeap)[n] = malloc(sizeof(int[m][n]));
matrixInHeap[0][0] = 0; // OK
matrixInHeap[m-1][n-1] = 0; // OK
// matrixInHeap[10][5] = 0; // Not OK. coloring outside the lines again.
The way the matrixInHeap declaration should be interpreted is that the 'thing' pointed to by matrixInHeap is an array of n int values, so sizeof(*matrixInHeap) == n * sizeof(int), or the size of an entire row in the matrix. matrixInHeap[2][4] works because matrixInHeap[2] is advancing the address matrixInHeap by 2 * sizeof(*matrixInHeap), which skips two full rows of n integers, resulting in the address of the 3rd row, and then the final [4] selects the fifth element from the third row. (remember that array indices start at 0 and not 1)
You can use the same type when pointing to normal multidimensional c-arrays, (assuming you already know the size):
int (*matrixPointer)[n] = matrixOnStack || matrixInHeap;
Now lets say you want to have a function that takes one of these variably sized matrices as a parameter. When the variables were declared earlier the type had some information about the size (both dimensions in the stack example, and the last dimension n in the heap example). So the parameter type in the function definition is going to need that n value, which we can actually do, as long as we include it as a separate parameter, defining the function like this:
void fillWithZeros(int m, int n, int (*matrix)[n]) {
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
matrix[i][j] = 0;
}
If we don't need the m value inside the function, we could leave it out entirely, just as long as we keep n:
bool isZeroAtLocation(int n, int (*matrix)[n], int i, int j) {
return matrix[i][j] == 0;
}
And then we just include the size when calling the functions:
fillWithZeros(m, n, matrixPointer);
assert(isZeroAtLocation(n, matrixPointer, 0, 0));
It may feel a little like we're doing the compilers work for it, especially in cases where we don't use n inside the function body at all (or only as a parameter to similar functions), but at least it works.
One last point regarding readability: using malloc(sizeof(int[len])) is equivalent to malloc(len * sizeof(int)) (and anybody who tells you otherwise doesn't understand structure padding in c) but the first way of writing it makes it obvious to the reader that we are talking about an array. The same goes for malloc(sizeof(int[m][n])) and malloc(m * n * sizeof(int)).
Will I still be able to do:
array[position] = value;
Yes, because the index operator p[i] is 100% identical to *(ptr + i). You can in fact write 5[array] instead of array[5] and it will still work. In C arrays are actually just pointers. The only thing that makes an array definition different from a pointer is, that if you take a sizeof of a "true" array identifier, it gives you the actual storage size allocates, while taking the sizeof of a pointer will just give you the size of the pointer, which is usually the system's integer size (can be different though).
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype: (…)
Neither of them because those are arrays of pointers to arrays, which can be non-contigous. For performance reasons you want matrices to be contiguous. So you just write
void foo(int matrix[])
and internally calculate the right offset, like
matrix[width*j + i]
Note that writing this using the bracket syntax looks weird. Also take note that if you take the sizeof of an pointer or an "array of unspecified length" function parameter you'll get the size of a pointer.
No, you'd just keep using array[position] = value.
In the end, there's no real difference whether you're declaring a parameter as int *something or int something[]. Both will work, because an array definition is just some hidden pointer math.
However, there's is one difference regarding how code can be understood:
int array[] always denotes an array (it might be just one element long though).
int *pointer however could be a pointer to a single integer or a whole array of integers.
As far as addressing/representation goes: pointer == array == &array[0]
If you're working with multiple dimensions, things are a little bit different, because C forces you declare the last dimension, if you're defining multidimensional arrays explicitly:
int **myStuff1; // valid
int *myStuff2[]; // valid
int myStuff3[][]; // invalid
int myStuff4[][5]; // valid

What does the declaration void** mean in the C language?

I'm beginning to learn C and read following code:
public void** list_to_array(List* thiz){
int size = list_size(thiz);
void **array = malloc2(sizeof(void *) * size);
int i=0;
list_rewind(thiz);
for(i=0; i<size; i++){
array[i] = list_next(thiz);
}
list_rewind(thiz);
return array;
}
I don't understand the meaning of void**. Could someone explain it with some examples?
void** is a pointer to a pointer to void (unspecified type). It means that the variable (memory location) contains an address to a memory location, that contains an address to another memory location, and what is stored there is not specified. In this question's case it is a pointer to an array of void* pointers.
Sidenote: A void pointer can't be dereferenced, but a void** can.
void *a[100];
void **aa = a;
By doing this one should be able to do e.g. aa[17] to get at the 18th element of the array a.
To understand such declarations you can use this tool and might as well check a related question or two.
void** is a pointer to void*, or a pointer to a void pointer if you prefer!
This notation is traditionally used in C to implement a matrix, for example. So, in the matrix case, that would be a pointer to an array of pointers.
Normally void * pointers are used to denote a pointer to an unknown data type. In this case your function returns an array of such pointers thus the double star.
In C, a pointer is often used to reference an array. Eg the following assignment is perfectly legal:
char str1[10];
char *str2 = str1;
Now when void is used, it means that instead of char you have a variable of unknown type.
Pointers to an unknown data type are useful for writing generic algorithms. Eg. the qsort function in standard C library is defined as:
void qsort ( void * base,
size_t num,
size_t size,
int ( * comparator )
( const void *, const void * ) );
The sorting algorithm itself is generic, but has no knowledge of the contents of the data. Thus the user has to provide an implementation of a comparator that can deal with it. The algorithm will call the comparator with two pointers to the elements to be compared. These pointers are of void * type, because there is now information about the type of data being sorted.
Take a look at this thread for more examples
http://forums.fedoraforum.org/showthread.php?t=138213
void pointers are used to hold address of any data type. void** means pointer to void pointer. Void pointers are used in a place where we want a function should receive different types of data as function argument. Please check the below example
void func_for_int(void *int_arg)
{
int *ptr = (int *)int_arg;
//some code
}
void func_for_char(void *char_arg)
{
char *ptr = (char *)char_arg;
//some code
}
int common_func(void * arg, void (*func)(void *arg))
{
func(arg);
}
int main()
{
int a = 10;
char b = 5;
common_func((void *)&a, func_for_int);
common_func((void *)&b, func_for_char);
return 0;
}

passing a pointer to 2D array of pointers in C

I have seen some of the other answers on this topic but dont really understand them enough to fit them to my problem. I have a 2D array of pointers to char that I want to pass to a function.
If the array is declared: char *params[50][50]; (50 is just picked arbitrarily)
and the function prototype is: void test (char ***results);
How would I call the function? everything I try ends up with an incompatible pointer warning
Also what is the most correct way to then refer to the members of the array while inside the function? is it simply: results[x][y]; ?
Thanks
you can't, pointers to pointers and pointers to arrays are different things.
void test (char *results[50][50]);
void test (char *results[][50]);
void test (char *(*results)[50]);
are all equivalent prototypes for the function that you are looking for.
Suplement: If you want to use the same function for arrays with varying lenght for the dimension you'd have to use VLA (variable length array) as function arguments:
void test (size_t n, char *results[n][n]);
void test (size_t n, char *results[][n]);
void test (size_t n, char *(*results)[n]);
This only works if you have a compiler that is conforming to C99.
Observe that the parameter for the size comes before the array, such that it is known there.
Also you don't have to declare the arrays themselves with variable length to use this feature for the function parameters. But if you do be careful that you don't allocate large matrices on the stack, otherwise you may easily have a stackoverflow.
If you declare an array as
char *array[N][M];
and pass it to a function as
test(array)
then the prototype to the function will need to be either
void test(char *(*arr)[M])
or
void test(char *arr[][M])
In either case, arr has type "pointer to M-element array of pointer to char". This is not the same type as char ***, and there's no really good or clean way to convert between the two.
Had you allocated dynamcally allocated array in the following manner, then the prototype would be correct:
char ***array = malloc(sizeof *array * N);
if (array)
{
size_t i;
for (i = 0; i < N; i++)
{
array[i] = malloc(sizeof *array[i] * M);
if (array[i])
{
size_t j;
for (j = 0; j < M; j++)
{
array[i][j] = some_initial_pointer_value();
}
}
}
}
Note that in this case, the type of array is char ***.
If you're working with arrays declared as T a[M][N], and you want to write a function that will accept arrays of different sizes, then you can either use the VLA syntax as suggested by Jens, or you could do something like this:
void test(char **a, size_t rows, size_t cols)
{
size_t i, j;
...
some_pointer_value = a[i * rows + j];
...
a[i * rows + j] = some_pointer_value;
}
...
test(&array[0][0], 50, 50);
In this case, we explicitly pass the address of the first element of the array and the array dimensions as separate parameters. Within the body of test we treat the array as having 1 dimension (char *a[rows * cols]) and compute the offset manually. Note that this only works for arrays that are contiguously allocated; this won't work with the version that does piecemeal allocation for each row in the array above.
My C is a little rusty but:
char *params[][];
is a 2D array of char * pointer, not char. If you wanted a 2D char array it is defined as:
char params[valuex][valuey];
Iit will be static memory allocation, only available in definition scope, i mean you leave the scope you loose the array if it is not the behaviour you are looking for try dynamic allocation).
You can then pass this array to a function by defining the function prototype as:
void foo(char param[valuex][valuey] );
Regards

passing an array of string to a function

My program is
#define ARRLEN 10
#define SIZEALCO 128
#define MAX_STRING_LENGTH 12
in main function,
char TYPEDATA_XML_FN[ARRLEN][SIZEALCO];
char TYPEDATA_MD5_FN[ARRLEN][SIZEALCO];
char identifier[ARRLEN][MAX_STRING_LENGTH];
char Temppath[SIZEALCO];
int arraynum;
// ...
arraynum = 0;
for(arraynum = 0; arraynum <ARRLEN; arraynum++)
{
/* Create the file name with the path*/
strcpy(Temppath,"/fw/TYPEDATA/");
nameFil(Temppath,identifier[arraynum],TYPEDATA_XML_FN[arraynum],TYPEDATA_MD5_FN[arraynum]);
}
subfunction is :
void nameFil(char *SourPath,char *InPinName,char *FilePathNameXml,char *FilePathNameMd5)
{
sprintf(FilePathNameXml, "%s\\%s_TYPEDATA.XML",SourPath,InPinName);
sprintf(FilePathNameMd5, "%s\\%s_TYPEDATA.MD5",SourPath,InPinName);
}
I checked with your example. I used (trial)
char** a = calloc(ARRLEN, sizeof(char *));
for(i = 0; i < ARRLEN ; ++i)
a[i] = ucmalloc(MAX_STRING_LENGTH);
pase(a);
subfunction :
void pase(char b[ARRLEN][MAX_STRING_LENGTH])
{
// ...
}
Now I got the warning message as "warning: passing arg 1 of `pase' from incompatible pointer type".
Actually, I would like to pass the full string array identifier,TYPEDATA_XML_FN,TYPEDATA_MD5_FN. Now I am passing single string to the subfunction. Kindly guide me. Thank you
The prototype void pase(char b[ARRLEN][MAX_STRING_LENGTH]) is rather mis-leading,
void pase(char b[][MAX_STRING_LENGTH])
would be better, since otherwise there is the implication of bounds checking (the first array dimension is ignored).
The reason why you get "incompatible pointer type" is because a is an array of pointers. If a was incremented (as a pointer itself) then the address would increase by the size of a pointer. However, b is an array of arrays of size MAX_STRING_LENGTH, so if b was incremented then the value would increase by MAX_STRING_LENGTH.
The way you have allocated the array a will (probably) not give you contiguous memory, which is what is required here. You could achieve what you want using an array of pointers, but you really must decide what you want to do. If you want to use [][] notation then you need to
calloc(MAX_STRING_LENGTH,ARRLEN);
You are getting confused because although an one dimensional array char[] behaves like a pointer char *, in two dimensions a char[][N] is not convertible to a char **, being actually more like a (*char)[N] (pointer to arrays of length n of char).
So if you want to make a function that receives a two dimensional array, you have two choices:
Use pointers to pointers:
void f(char ** array, int nrows, int ncols);
To create a char**, do like you are already doing now: create an array for pointers and call malloc for each one of them.
Use two dimensional arrays:
void f(char array[][NCOLS], int nrows);
//note: NCOLS is a compile time constant now
//NROWS is the first dimension and can be omited from array[NROWS][NCOLS]
The tricky bit is malloc-ing a two dimensional array:
char (*my_array)[NCOLS];
//my_identifiers is a pointer to arrays of length NCOLS
// it can be passed to any function expecting a car[][NCOLS]
my_array = malloc(number_of_rows*(sizeof *my_array));
You can also make it easier to understand all of this with a good choice of typedefs:
typedef char MY_STRING[MAX_STR_LENGTH];
//define my strings as arrays of MAX_STRING_LENGTH
void f(MY_STRING array[]);
...
MY_STRING *arr = malloc(nstrings*sizeof(MY_STRING));
f(arr);

Resources