Initialize an array using the pointer to an existing array - c

I have already understood that one can't assign arrays to arrays in c. A statement like:
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int array2[10];
int * array3 = array;
Is valid, but a consecutive statement:
array2 = array1;
Is not, because arrays do decay to pointers. I find this not satisfying, since in case I have a function that creates an array:
int * arrcreate() {
static int funcarray[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
return funcarray
}
And I call it in my main routine, I'd like to handle an array, not a pointer.
Of course I could in my main program create an array and fill it by hand:
int main() {
int array[10];
int i;
int * p = arrcreate();
for(i = 0; i<10, i++) {
array[i] = p[i];
}
}
But since I KNOW that when initializing an array it is possible to do kind of an assignment:
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
I wanted to ask if it is possible to assign an array with the pointer to an array as well.
An equivalent question would be: Given a pointer to an array, and knowing the size of the array the pointer is pointing to, is it possible to create and initialize on the fly a new array, which is in every matter a copy of the old one?

As Bathsheba said, an array cannot be on the left hand side of an assignment like the one you put in your question. But if you will always know both the pointer to the array you would like to copy, as well as the array size, you could write a function along the lines of:
void copy_array(const int *a, const int arraySize, int **b) {
*b = malloc(arraySize * sizeof(*a));
for (int indx = 0; indx < arraySize; indx++) {
(*b)[indx] = a[indx];
}
}
int main() {
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *array2;
copy_array(array1, &array2);
// do stuff
free(array2);
}
Is that an option?

Unfortunately the answer is not. The draft n1570 for C11 says in 6.7.9 Initialization:
...16 Otherwise, the initializer for an object that has aggregate or union type shall be a brace enclosed
list of initializers for the elements or named members.
(the previous items concern struct, union or character type array)
That means that an int array can only be initialized with a brace enclosed list of integer values. And a pointer to an array does not follow that definition.

Informally speaking, an array cannot be an lvalue. This means that an array cannot be on the left hand side of an assignment.
Note secondly that int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; is not an assignment but is array initialisation.
If you're careless regarding terminology, the two sentences appear to be in contradiction. But they are not; furthermore you can see that it is not possible to initialise an array using the values pointed at by a particular pointer. You need to use something on the lines of memcpy.

Related

why I am not able to initialize array of pointers providing 2d array

int *p = ( int[] ){ 1, 2, 3, 4 };
Doing this I am able to initialize a anonymous array to a pointer p.
In a similar way I want to assign arrays of array (i.e. probably 2D array) in
array of pointers. And so I have tried the following code:
int *p[]= (int [][3]) { {1,2,3},{10,20,30} };
But it goes wrong, anyway if I assign it to a pointer to whole Array( as int (*p)[]= (int [][3]) { {1,2,3},{10,20,30} }; ) it works fine.
I am in confused that if a pointer can get assigned a anonymous array why the array of pointers could not get assigned to 2d array?
The compound literal
(int [][3]) { {1,2,3},{10,20,30} };
has the type
int [2][3]
i.e. array of 2 elements, each consisting of 3 int elements.
When used in the line
int *p[]= (int [][3]) { {1,2,3},{10,20,30} };
the array will decay to a pointer to the first element. This pointer will therefore have the type "pointer to array of 3 int elements`.
However, you cannot assign this data type to p, because the types are different. You declared p as an array of pointers. That is why your code is not working.
If you want p to be an array of pointers in which every pointer points to its array of int elements, then you will need to use several compound literals, one for each of these arrays:
int *p[] = {
( int[] ){ 1, 2, 3, 4 },
( int[] ){ 5, 6, 7, 8 },
( int[] ){ 9, 10, 11, 12 }
};
Here is a small test program:
#include <stdio.h>
int main( void )
{
int *p[] = {
( int[] ){ 1, 2, 3, 4 },
( int[] ){ 5, 6, 7, 8 },
( int[] ){ 9, 10, 11, 12 }
};
printf( "%d\n", p[1][2] );
}
This program has the output 7.
EDIT:
According to your remarks in the comments section of this answer, it seems that you have several 2D arrays and want to create an array of pointers to these arrays. In that case, you can do the following:
#include <stdio.h>
int main( void )
{
//define first 2D array
int arr1[][4] = {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9, 10, 11, 12}
};
//define second 2D array
int arr2[][4] = {
{ 13, 14, 15, 16},
{ 17, 18, 19, 20},
{ 21, 22, 23, 24}
};
//define array of 2 pointers that point to the first
//rows of arr1 and arr2
int (*p[])[4] = { arr1, arr2 };
//use pointer array to get the 4th element in the
//3rd row of the second 2D array
printf( "%d\n", p[1][2][3] );
}
This program will give you the correct output 24.
If you find the declaration int (*p[])[4] hard to understand, then you may want to read this page on how these declarations are to be interpreted. Also, this site may be useful.
You can also simplify your declarations by using a typedef, so that the type arrow_row represents an array of 4 int elements (i.e. a row of a 2D array) like this:
typedef int array_row[4];
Now, you can simplify the declaration
int (*p[])[4] = { arr1, arr2 };
to:
array_row *p[] = { arr1, arr2 };
int *p[] is an array of pointers, not a pointer to an array.
You'll need to do:
int (*p)[3]= (int [][3]) { {1,2,3},{10,20,30} };
The reason why is that an array, whenever used in an expression, decays into a pointer to the first element. So no matter the array type, your pointer will need to correspond to the pointer to the first element.
In case of an int[], the element type is int and a pointer to it would be int*.
In case of an int[][3], the element type is int[3] and a pointer to it would be int (*p)[3].

How static initialize a 2D array to a pointer to pointers?

I have a structure, say foo that looks like this,
struct foo {
size_t n;
size_t **point;
};
There are other members in the structure they are not important to the question. Now, I want to static initialize the structure.
int main(void)
{
struct foo *bar = &(struct foo){
.n=4,
/* ERROR HERE */ .point=(size_t[][n]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
};
return 0;
}
There are two problem in the line indicated. First, understandably the compiler doesn't recognise n and is there any way I can do something similar without creating a variable before? Secondly, and most importantly, I realized that I have no idea how to create a 2D array and assign it to a pointer to pointers statically. Please help. I tried the following variations but nothing worked.
/* Variation 1 */ .point=(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
/* Variation 2 */ .point=(size_t**)(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
/* Variation 3 */ .point=&(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
Note that this isn't technically 2D array, but a pointer-to-pointer array. But since compound literals cannot have variable length array type, and it doesn't seem that you want to use hardcoded dimensions, this may be the only way to go.
You'll need to split your arrays to 1D arrays of unknown size and use separate compound literals for them:
struct foo * bar = &(struct foo){
.n = 4,
.point = (size_t*[]){
(size_t[]){1, 2, 3, 4},
(size_t[]){5, 6, 7, 8}
}
};
First of all size_t **point only makes sense if you intend to point at an array of size_t*. That doesn't seem to be the case here, so you need to change the type to a 2D array, or an array pointer.
Next problem is that C is rather cumbersome here - bluntly put, you can't have a "static dynamic" array, it must be either. You can either have this:
#define N 4
struct foo {
size_t n;
size_t (*point)[N]; // pointer to first array of an array of size_t[4]
};
struct foo bar =
{
.n=N,
.point= (size_t[][N]){ {1, 2, 3, 4}, {5, 6, 7, 8} }
};
...
bar.point[x][y] = ...; // access element of the 2D array
or alternatively perhaps a flexible array member in the form of an array of pointers, like this:
struct foo {
size_t n;
size_t* point[];
};
const size_t n = 4;
struct foo* bar = malloc ( sizeof(*bar) + sizeof (size_t*[n]) );
bar->n = n;
bar->point[0] = (size_t []) { 1, 2, ... /* any number of elements*/ };
bar->point[1] = ...
...
bar->point[0][0] = 0; // access element in the lookup-table
...
free(bar);
None of these are particularly good alternatives, the syntax is messy and error prone. The language is simply severely lacking here.
In order to initialize a pointer statically, the entities you are pointing to need to have been declared. Only in rare cases, like maybe an embedded system where you know the address of something at compile time, would you know the actual value of the pointer to be initialized statically.
I see a couple problems with what you're doing:
1) The compiler can't resolve what the value of n is at the time you are trying to use it to declare the size of your array. Arrays need to have a size supplied in their declaration, unlike C#.
2) The "point" member of the struct is a pointer to pointers, but you're trying to initialize it with an array of arrays. If you want to point to an array of arrays, you only need the address of the [0][0] element, so *point not **point. From there you can use array notation to access the elements.
You need to do something like this:
struct foo
{
size_t n;
size_t *point;
};
size_t values[2][4] = {{1,2,3,4}, {5,6,7,8}};
struct foo bar =
{
4,
&values
}
Then you can access the array by:
size_t kk;
kk = bar.point[ii][jj];
If you truly need pointers to pointers, then the initialization values will have to either be address references (&name) or values that are being cast as pointers, but I don't suggest doing that.
If you truly need a variable size for your array, then you'll need to allocate memory dynamically and then initialize the pointer in the struct with the address returned from that.

Failed to initialize a pointer array in C

int array[2] = {1, 1};
int (*pointer_array)[2] = {NULL, NULL};
The first line can be correctly compiled but not the second one? Why?
GCC compiler will pop up a warning, excess elements in scalar initializer.
How to initialize a pointer array in C?
EDITED
I declared a pointer array in a wrong way.
It should be like this:
int *pointer_array[2] = {NULL, NULL};
It should be
int (*pointer_array)[2]=(int[]){1,2};
This is pointer to array of int .I don't know you want pointer to array of int or array of pointers.
To declare as array of pointer you need to do this -
int *pointer_array[2];
Suppose you have an array of int of length 5 e.g.
int x[5];
Then you can do a = &x;
int x[5] = {1};
int (*a)[5] = &x;
To access elements of array you: (*a)[i] (== (*(&x))[i]== (*&x)[i] == x[i]) parenthesis needed because precedence of [] operator is higher then *. (one common mistake can be doing *a[i] to access elements of array).
Understand what you asked in question is a compilation time error:
int (*a)[3] = {11, 2, 3, 5, 6};
It is not correct and a type mismatch too, because {11,2,3,5,6} can be assigned to int a[5]; and you are assigning to int (*a)[3].
Additionally,
You can do something like for one dimensional:
int *why = (int[2]) {1,2};
Similarly, for two dimensional try this(thanks #caf):
int (*a)[5] = (int [][5]){ { 1, 2, 3, 4, 5 } , { 6, 7, 8, 9, 10 } };

Using initializers to set all bounds of a multidimensional array

Why doesn't this compile? I don't want to put 2 in the last pair of brackets. Is there another way to do it?
int ary[][] = {{2, 3}, {5, 7}, {11, 13}};
There is a way to do it without specifying the dimensions, using compound literals:
int* ary[] = {( int[] ){2, 3}, ( int[] ){5, 7}, ( int[] ){11, 13} };
And the usage stays the same!:
ary[2][1] = 55 ;
printf("%d %d\n" , ary[2][0] , ary[2][1] ) ;
Compound literals have the same scope and lifetime as the array ary, so this is very similar as using a two dimensional array.
Another way to do it:
int ary[] = {2, 3, 5, 7, 11, 13};
Now it is up to you to index the array appropriately. You must know somewhere that the number of elements per "row" is 2, so just do this:
int* get_cell(int* arr, size_t N, size_t x, size_t y)
{
return &arr[x + N * y];
}

Initializing "a pointer to an array of integers"

int (*a)[5];
How can we Initialize a pointer to an array of 5 integers shown above.
Is the below expression correct ?
int (*a)[3]={11,2,3,5,6};
Suppose you have an array of int of length 5 e.g.
int x[5];
Then you can do a = &x;
int x[5] = {1};
int (*a)[5] = &x;
To access elements of array you: (*a)[i] (== (*(&x))[i]== (*&x)[i] == x[i]) parenthesis needed because precedence of [] operator is higher then *. (one common mistake can be doing *a[i] to access elements of array).
Understand what you asked in question is an compilation time error:
int (*a)[3] = {11, 2, 3, 5, 6};
It is not correct and a type mismatch too, because {11,2,3,5,6} can be assigned to int a[5]; and you are assigning to int (*a)[3].
Additionally,
You can do something like for one dimensional:
int *why = (int p[2]) {1,2};
Similarly, for two dimensional try this(thanks #caf):
int (*a)[5] = (int p[][5]){ { 1, 2, 3, 4, 5 } , { 6, 7, 8, 9, 10 } };
{11,2,3,5,6} is an initializer list, it is not an array, so you can't point at it. An array pointer needs to point at an array, that has a valid memory location. If the array is a named variable or just a chunk of allocated memory doesn't matter.
It all boils down to the type of array you need. There are various ways to declare arrays in C, depending on purpose:
// plain array, fixed size, can be allocated in any scope
int array[5] = {11,2,3,5,6};
int (*a)[5] = &array;
// compound literal, fixed size, can be allocated in any scope
int (*b)[5] = &(int[5]){11,2,3,5,6};
// dynamically allocated array, variable size possible
int (*c)[n] = malloc( sizeof(int[n]) );
// variable-length array, variable size
int n = 5;
int vla[n];
memcpy( vla, something, sizeof(int[n]) ); // always initialized in run-time
int (*d)[n] = &vla;
int a1[5] = {1, 2, 3, 4, 5};
int (*a)[5] = &a1;
int vals[] = {1, 2};
int (*arr)[sizeof(vals)/sizeof(vals[0])] = &vals;
and then you access the content of the array as in:
(*arr)[0] = ...

Resources