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

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.

Related

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.

C: How to get the last element value of an arrary or an two-dimensional arrary through function call

As we known that the last element value of an array or an two-dimensional array can be obtained by below code:
For an array:
int a[] = {1, 2, 3, 4};
printf("%d", *((int *)(&a + 1) - 1));
For an two dimensional array:
int a[2][2] = {1, 2, 3, 4};
printf("%d", *((int *)(&a + 1) - 1));
Both of those code can output the correct value: 4. But when I changed the code like below:
int foo(int a[][2]) {
return *((int *)(&a + 1) - 1);
}
void main() {
int a[2][2] = {1, 2, 3, 4};
printf("%d", foo(a));
}
Then I cannot get the right value. Is there anything wrong with this code? The main purpose of this code is try to get the last element value without knowing the number of elements. Is this possible?
Thanks in advance.
Yes. In your first two cases, a is an array. However in the last case, a is a pointer. You are forgetting that in a function parameter, an array declarator is adjusted to a pointer declarator. Your function is actually:
int foo(int (*a)[2])
{
where a is a pointer to the first element of the array you called the function with. There is no way for the function to get the dimension of the array (or do anything that requires that information).
Related question
When you pass an array to a function, it decays to a pointer. So when doing e.g. &a in the function, you don't get a pointer to an array of arrays of 2 integers, you get a pointer to a pointer to an array of 2 integers.
I don't know anything about C, but every language has / should have a function to check the length of array and mostly it's called length or simly count.
So, if i would want to get the last element say in php i would:
Var elmt = array[array.count-1]
I hope understood correctly what you wanted.

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

Assigning an array to a struct member in C [duplicate]

This question already has answers here:
Why can't I assign arrays as &a = &b?
(2 answers)
Closed 9 years ago.
I wrote this piece of code
#include <stdio.h>
struct foo
{
int foo1[3];
};
int main(void)
{
int a[] = {1, 2, 3};
struct foo test;
test.foo1 = a;
printf("%d\n", test.foo1[0]);
return 0;
}
It gives compile error saying that it cannot convert int * to int[3].
I know that array names will decay into pointers in expressions, but is there a way of suppressing that since I do need an array here?
As the others said, there is not direct assignment operators that will copy an array. You have to use memcpy() instead
memcpy(test.foo1, a, sizeof(a));
This is one source of errors in C because the sizeof() needs to be large enough to copy all the data but not too large so as not to overwrite data at tests.foo1. The best practice, I would imagine, is to test that both arrays are the same size before doing the memcpy().
This is one of the basics of C, arrays cannot be assigned.
In C and in C++ there is no way to assign a value to an whole array. It is also not possible to assign an array the values of an other array (even if the dimension would match).
You cannot assign arrays in C. However, you can assign objects of user-defined type, even if those contain an array. So peraps rewrite it like this:
struct foo a = { { 1, 2, 3 } };
struct foo test;
test = a;
Or of course just initialize the object correctly immediately:
struct foo test = { { 1, 2, 3 } };
Arrays are not first class objects in C. You can't copy (assign), compare, pass, or return an array. You copy an array into another array element by element. You also compare two arrays element by element. You pass a pointer to a first element of the array and similarly return a pointer to the first element of a dynamically allocated array. Therefore test.foo1 = a; is wrong. You have two choices here.
#include <stdio.h>
struct foo {
int foo1[3];
};
int main(void) {
int a[] = {1, 2, 3};
struct foo test;
int len = *(&(test.foo1) + 1) - test.foo1; // length of the array test.foo1
int i = 0;
for(i = 0; i < len; i++)
test.foo1[i] = a[i]; // copy the array element-wise
printf("%d\n", test.foo1[0]);
return 0;
}
You can also directly copy all the bytes from the array a in main to the array test.foo1 using memcpy.
memcpy(test.foo1, a, sizeof a);
This copies all the bytes of the array a into the array test.foo1. Therefore the array test.foo1 must be large enough else it will lead to undefined behaviour or even segfault.

Why can't I dereference a pointer to multidimensional array?

Basic question.. had to ask. Any help will be appreciated.
Q: Why can't I dereference the pointer to a multidimensional array like this:
int arr [2][2] = { {1, 2} , {3, 4} };
printf("%d ", *arr);
You can dereference it, it is just that the result is not going to be what you'd expect: *arr is not an int, it's a pointer to an int (OK, a one-dimensional array). If you want to see 1 printed, add another star:
printf("%d ", **arr);
If a is int[][] then *a is int[]. You need another level of redirection to access an array element. That is, **a is int.
Try:
int arr [2][2] = { {1, 2} , {3, 4} };
printf("%d ", **arr);
You need two levels of dereferencing, as your array is two-dimensional.
Remember if we define a as int[][], then it means it is a two dimensional array and it can be dereferenced by **a. If array is one dimensional then we should use *a to dereference it...
Try it..

Resources