Failed to initialize a pointer array in C - 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 } };

Related

What is the difference between a regular array, and array of pointers

Can someone plz explain me what is the diffrence between those tow lines
and when we will want to use each one of then
int array[] = { 1, 2, 3 }; // init a regular array
int *numList = {1, 2, 3}; // init an array of pointers?
I am expecting that there are probably seenarios we will want to use the second over the first,
But when?
Thank You in Advance
You're conflating some concepts. As #ikegami noted, your second line:
int *numList = {1, 2, 3};
Gets treated as:
int *numList = 1;
Which not an array, nor a valid pointer.
If you want to create an array of pointers, you use the same syntax as normal arrays, with the type being a pointer:
int* numList[] = {
&array[0],
&array[1],
&array[2]
};
Will create an array of 3 int pointers, pointing to your original array's elements.

This is another example of my neverending confusion related to memory and pointers in C

I am a newbie in C, but I have already watched dozens of videos on YT about how to understand pointers... Unfortunately, it seems my stupid brain is not getting the point about pointers. Could anyone help me to understand why I am getting such values in the output?
The output is: 1-40 256-296 64-104
#include <stdio.h>
int main() {
int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int arr_size = sizeof(arr1) / sizeof(arr1[0]);
int arr2[arr_size];
int arr3[arr_size];
int *ptr1 = arr1;
int *ptr2 = arr2;
int *ptr3 = arr3;
printf("%u-%u %u-%u %u-%u\n", *ptr1, sizeof(arr1), *ptr2, *ptr2+sizeof(arr2), *ptr3, *ptr3+sizeof(arr3));
return 0;
}
Thanks for help!
The arrays arr2 and arr3 are not initialized. So their elements have indeterminate values. Outputting uninitialized elements invokes undefined behavior.
Also to output a value of the type size_t you need to use the conversion specifier zu instead of u in a call of printf.
So the only valid call of printf will look the following way
printf("%d-%zu\n", *ptr1, sizeof(arr1) );
This call outputs the value of the first element of the array arr1 by means of the pointer ptr1 that (value) is equal to 1 and the size of the array itself that can be equal to 40 provided that sizeof( int ) is equal to 4.

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.

Why *pointer_name behaves differently in 1D and 2D array

Why is it that when *q is used in 1D array it gives the value in the array whereas *p in 2D array gives an address instead. Isn't *pointer_name supposed to tell what is stored, so why is output an address instead of 40 (the value in array)?
#include<stdio.h>
int main(){
int a[3][4] = {
{40, 1, 2, 3} ,
{4, 5, 6, 7} ,
{8, 9, 10, 11}
};
int (*p)[4] = a;
int b[4] = {3,4,8,5};
int *q = b;
printf("%d, %d",*q, *p);// output- 3, 10485040
return 0;
}
Because p is a pointer to an array. When you dereference p the array will decay to a pointer to the first element. Doing *p and &(*p)[0] is equivalent (and also equivalent to &a[0][0]).
If you want to print the first element then you need to dereference both pointers, i.e. **p.
2D array means an array of arrays! so each slot of first row in the 2D array should have the address of another array.
for instance if you have an array a[2][3] , the a[0] value is the address of the first slot of an array with size 4. and a[1] like so etc .

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