It's purely a type issue.
In most expression contexts the name of an array (such as var) decays to a pointer to the initial element of the array, not a pointer to the array. [Note that this doesn't imply that var is a pointer - it very much is not a pointer - it just behaves like a pointer to the first element of the array in most expressions.]
This means that in an expression var normally decays to a pointer to an int, not a pointer to an array of int.
As the operand of the address-of operator (&) is one context where this decay rule doesn't apply (the other one being as operand of the sizeof operator). In this case the type of &var is derived directly from the type of var so the type is pointer to array of 5 int.
Yes, the pointers have the same address value (the address of an arrays first element is the address of the array itself), but they have different types (int* vs int(*)[5]) so aren't compatible in the assignment.
ISO/IEC 9899:1999 6.3.2.1/4:
Answer from Lara Bailey on Stack OverflowExcept when it is the operand of the
sizeofoperator 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 of type "pointer to type" that points to the initial element of the array object and is not an lvalue. ...
It's purely a type issue.
In most expression contexts the name of an array (such as var) decays to a pointer to the initial element of the array, not a pointer to the array. [Note that this doesn't imply that var is a pointer - it very much is not a pointer - it just behaves like a pointer to the first element of the array in most expressions.]
This means that in an expression var normally decays to a pointer to an int, not a pointer to an array of int.
As the operand of the address-of operator (&) is one context where this decay rule doesn't apply (the other one being as operand of the sizeof operator). In this case the type of &var is derived directly from the type of var so the type is pointer to array of 5 int.
Yes, the pointers have the same address value (the address of an arrays first element is the address of the array itself), but they have different types (int* vs int(*)[5]) so aren't compatible in the assignment.
ISO/IEC 9899:1999 6.3.2.1/4:
Except when it is the operand of the
sizeofoperator 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 of type "pointer to type" that points to the initial element of the array object and is not an lvalue. ...
var itself is a (*int) pointing to the first element in your array. Pointers and arrays in C extremely similar. Change int (*ptr)[5] = NULL; to int* ptr = NULL; and ptr = &var; to ptr = var;
Is it possible in C to assign pointer to an array or change to address of array to the pointer address? - Stack Overflow
Array Declaration and pointer assignment in C - Stack Overflow
How should I assign a pointer to an array to a structure?
c - How can I assign an array to pointer? - Stack Overflow
Videos
No, you cannot reassign an array as you do here:
int q[3];
q = *(int [3]) arrayReturn(z);
If you want to copy the contents of z to q, you can do that with the memcpy library function:
memcpy( q, z, sizeof z );
but the = operator isn't defined to copy array contents.
Otherwise, the best you can do is declare q as a pointer and have it point to the first element of z:
int *q = z; // equivalent to &z[0]
Unless it is the operand of the sizeof or unary * operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted, or "decay", to an expression of type "pointer to T" and the value of the expression will be the address of the first element of the array - that's why the above assignment works.
Arrays in C are simple sequences of elements - there's no metadata indicating their size or type, and there's no separate pointer to the first element. As declared, the arrays are
+---+
z: | 1 | z[0]
+---+
| 2 | z[1]
+---+
| 3 | z[2]
+---+
...
+---+
q: | ? | q[0]
+---+
| ? | q[1]
+---+
| ? | q[2]
+---+
There's no separate object q to assign to.
A pointer is a variable which contains an address of memory. Array is just a place in the memory that occupies so many bytes. As a result, they are very different objects and cannot be assigned to each other.
However, a pointer can be used to point to an array and as a result can be used in copying data from one array to another, for example, using memcpy.
int c[3];
memcpy(c, arrayReturn(z), sizeof(c));
Of course, there is no checking of array sizes done and it is assumed that the size of an array to which points the return of the arrayReturn() is big enough to be copied to c. Neither there is a way to find out about the size of the array which it points to.
1. Bidimensional array:
int a[2][3]= { {1,2,3},{4,5,6}};
With this statement in memory you have 2x3 integers, all adjacent in memory.I suppose that you know how to access them, but in the case you don't I'll clarify it:
a[0][0] : 1
a[0][1] : 2
a[0][2] : 3
a[1][0] : 4
a[1][1] : 5
a[1][2] : 6
2. Pointer to array:
int (*ptr)[3] = &a[0];
ptr points to a int[3] block of memory.So you can assign it only to an int[3] type:
ptr= &a[0];
ptr= &a[1];
The difference is that this pointer does not have it's own memory, and you have to assign it to an int[3] variable or allocate it:
ptr= malloc (2*sizeof(int[3]);
This way you can use the memory pointed by ptr, if you initialize ptr this way:
for(int j=0; j<2; j++)
for(int i=0; i<3;i++)
ptr[j][i]=i+j*3+1;
This case you'll have the same memory representation of int a[2][3], except that this memory is in the heap and not in the stack.You can always choose to realloc/free the memory and this memory is not deleted once your function terminates.
You should know operator precedence rules in C: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedencehttp://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
int (*ptr)[3] as opposed to int * ptr [3]
The first one is a pointer (notice * is closer to the var name) to arrays of int of size 3
The second one is equal to int (*(ptr [3])) which is an array of size 3 on int pointers.
You can also use this site: http://cdecl.org/ if you have doubts on how to interpret an expression.
I'm working on a project, and would like to assign a pointer to an array to a struct, which I've managed to do, but I keep getting a warning, here is an example:
struct sample {
char *string;
}
int main() {
char arr[8] = "Hello";
struct sample test;
test.string = &arr;
hkprint(test.string);
}
This actually does work, but I compiling it produces the following warning warning: assignment to ‘char *’ from incompatible pointer type ‘char (*)[8]’ [-Wincompatible-pointer-types]
I try to do thing is as "solid" a way as possible, so I want to know if this is the proper way to do this, and I should just ignore the warning, or if there's a better way
I would also like to better understand why the warning is happening in the first place, since it seems to me that the types are the same, but the compiler clearly views them as incompatible
ptr is a pointer to an int array(int[2]), but you malloc the wrong size, and then, leaking the memory by assigning to the same variable, thus overriding the malloc memory address. I assume you want to do that:
int (**ptr)[2];
ptr = malloc (2*sizeof(int(*)[2]));
ptr[0] = &a;
ptr[1] = &b;
You need to use an array of pointers, not a pointer to an array:
int main()
{
int a[] = {1,2};
int b[] = {3,4};
int *ptr[2] = { a, b };
printf("%3d %3d", ptr[0][1], ptr[1][1]) ;
return 0;
}
Arrays are non-assignable and non-copyable, so you'd have to copy each element by hand (in a loop), or using std::copy.
If you're using C++, then use C++ arrays rather than C style arrays and pointers. Here's an example
#include <array>
#include <iostream>
template<size_t N>
std::array<int, N> generateArrayOfSize(void)
{
std::array<int, N> a;
for (int n=0; n<N; ++n)
a[n] = n;
return a;
}
template<size_t N>
void print(std::array<int, N> const &a)
{
for (auto num : a)
std::cout << num << " ";
}
int main() {
std::array<int, 10> a;
std::array<int, 10> d = generateArrayOfSize<10>();
a = d;
print(a); // Prints the first 10 elements of array.
}
which outputs 0 1 2 3 4 5 6 7 8 9