pointer to a array of initialized integers - c

I am trying to declare a pointer to a array of initialized ints at once(gcc 5.2.0, gnu99)
This is working
int a1[] = {1, 2, 3, 4, 5};
int (*a)[] = &a1;
I tried this and it isn't
int *why = (int p[2]) {1,2};
../src/gps/gps.c:399:18: error: expected ')' before 'p'
int *why = (int p[2]) {1,2};
^
int (*b)[5]= (int(*)[5])&({11,2,3,5,6});
../src/gps/gps.c:400:31: warning: left-hand operand of comma expression has no effect [-Wunused-value]
int (*b)[5]= (int(*)[5])&({11,2,3,5,6});
^
int (*cc)[] = &{1, 2, 3, 4, 5}
../src/gps/gps.c:402:17: error: expected expression before '{' token
int (*cc)[] = &{1, 2, 3, 4, 5}
^
What I miss here?

Here's the proper way to define these:
int *why = (int [2]) {1,2};
int (*a)[5]= &((int []){11,2,3,5,6});
When you create a compound literal, you prefix it with what looks like a typecast.
The first line didn't work because you attempted to put a variable name inside of the cast, and the second line didn't work because you didn't put the cast immediately before the part in curly braces.

Related

Initialize an array using the pointer to an existing array

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.

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 } };

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] = ...

1D and 2D array initialization with braces

The following code gives an "invalid initializer" error:
int a[]=(1,2,3);
But the following compiles successfully although it considers ',' as comma OPERATOR and not SEPARATOR:
int a[][2]={(1,2),(3,4)};
So why is () invalid for a 1D array and not for a 2D array?
In the first example:
int a[]=(1,2,3);
the initializer is a (rather odd) expression of type int. (It contains two comma operators, and yields the value 3.) The object is an array. The initialization is invalid because it's a type mismatch.
The second:
int a[][2]={(1,2),(3,4)};
is equivalent to:
int a[][2] = { 2, 4 };
which is valid because it's permissible to omit nested curly braces in an initializer; elements are used to initialize successive elements of the object. The first and third commas are comma operators; the second is a delimiter.
The outermost curly braces are optional if the initializer is simply an expression of the target type, whether it's a scalar, struct, or union. For example, you can write:
int x = 42;
int y = { 42 };
The outermost curly braces are required for an initializer that specifies element values (for an array, struct, or union object).
For example:
struct foo {
int x;
int y;
};
struct foo arr[2] = { 1, 2, 3, 4 };
is valid -- but it's more clearly written as:
struct foo arr[2] = { { 1, 2 }, { 3, 4 } };
Apart from the first example being invalid, both are poor style. The first may have been intended to be:
int a[] = { 1, 2, 3 };
and the second either:
int a[][2] = { 2, 4 };
or
int a[][2] = {{1, 2}, {3, 4}};
depending on the intent.
You forgot the curly braces in the first example. The accolades (curly braces) denote the initialisation of the contents of the array, the contents are then handled by your declarations within those accolades. Basically you're not initialisating the array in the first example. The parenthesis denote the order of evaluation, not arguments as they do with functions.

pointer to array and 2D array representation

I have doubt in syntax of pointer to array and 2D array
#include<stdio.h>
#include<stdlib.h>
void show ( int q[][4], int row )
{
int i, j ;
for ( i = 0 ; i < row ; i++ )
{
for ( j = 0 ; j < 4 ; j++ )
printf ( "%d ", q[i][j] ) ;
printf ( "\n" ) ;
}
printf ( "\n" ) ;
}
int main( )
{
int a[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 6}
} ;
show ( a, 3, 4 ) ;
return 0;
}
The above code works with all the below notations
void show ( int q[][4], int row )
void show ( int q[3][4], int row )
void show ( int ( *q )[4], int row, int col )
int q[][4] == int q[3][4]==int ( *q )[4] // represents pointer to 1D array with size 4
I have read this
int q[ ][4];
This is same as int ( *q )[4], where q is a pointer to an array of 4
integers. The only advantage is that we can now use the more
familiar expression q[i][j] to access array elements.
Question:
The show() function works with both of these, int q[][4] and int q[3][4] to receive 2D array's address.
But these are representation for 2D array right?
we can't allocate 2D like the following
int (*a)[4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 6}
} ;
But 2D can be allocated via this statement
int a[][4]={
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 6}
} ;
int (*a)[4] is not the same as int a[][4], then how come both 'pointer to array' and '2D array notation' can be used in show function?
Arrays are not pointers, but in many situations, arrays decay into pointers, for example when passed as function arguments. So when you pass an int q[][4] to a function, the function receives an int (*q)[4], a pointer to arrays of four int. That's why both forms work as arguments to show(). But for the declaration and initialization, the real type matters, so you can't initialize a pointer with an array-initializer.
Functions have special rules regarding array parameters, the basic rule is if you speak the function's prototype, and your first word is array, you change it to "pointer to", so that
(int foo[5]) ==> array[5] of int ==> pointer to int
(int foo[][4]) ==> array[] of array[4] of int ==> pointer to array[4] of int
(int (*foo)[4]) ==> pointer to array[4] of int ==> pointer to array[4] of int
(int *argv[]) ==> array of pointer to int ==> pointer to pointer to int
Within a function, that conversion doesn't happen, and there is a big difference between array and pointer types.
int a[] = {5, 3, 2};
Is legal, but
int *a = {5, 3, 2};
is not. As a rule, you can't assign a pointer from an array initializer. Instead, c99 provides compound literals:
int *a = (int[]){5, 3, 2};
int (*a)[4] = (int [][4]){
{2, 2, 3, 1},
{2, 3, 5, 3},
};
First, some language from the C standard:
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
In the call to the show function, the expression a has type "3-element array of 4-element array of int". By the rule above, this expression is replaced with an expression of type "pointer to 4-element array of int" before the call is made; thus, show receives a pointer value of type int (*)[4], not an array.
More standard language:
6.7.5.3 Function declarators (including prototypes)
...
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
Thus, in the context of a function parameter declaration, T a[n], T a[], and T *a are all equivalent. If T is an array type, such as "4-element array of int", then int a[3][4], int a[][4], and int (*a)[4] are all equivalent.
Note that this is only true for function parameter declarations. When you're declaring an array object, the following language comes into play:
6.7.8 Initialization
...
22 If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. At the end of its initializer list, the array no longer has incomplete type.
So when you write
int a[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 6}
} ;
you are declaring an Nx4 array of int, not a pointer to an array of int -- the inner dimension 3 is inferred from the number of 4-element arrays in the initializer.

Resources