Here,I have some Doubt with the output.
Why the Output is same ?
int (*r)[10];
printf("r=%p *r=%p\n",r,*r);
return 0;
Platform- GCC UBUNTU 10.04
Because Name of the array decays to an pointer to its first element.
int (*r)[10];
Is an pointer to an array of 10 integers.
r gives you the pointer itself.
This pointer to the array must be dereferenced to access the value of each element.
So contrary to what you think **r and not *r gives you access to the first element in the array.
*r gives you address of the first element in the array of integers, which is same as r
Important to note here that:
Arrays are not pointers
But expressions involving array name sometimes behave as pointer when those being used as name of the array would not make sense.
You would better understand if you look at the following program.
#include <stdio.h>
int main()
{
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int (*r)[10] = &a;
printf("r=%p *r=%p *(r+0)=%p *(r+1)=%p\n", r, *r, *(r+0), *(r+1));
printf("sizeof(int)=%d \n", sizeof(int));
return 0;
}
The output is as follows:
r=0xbfeaa4b4 *r=0xbfeaa4b4 *(r+0)=0xbfeaa4b4 *(r+1)=0xbfeaa4dc
sizeof(int)=4
Observations / Point(s)-to-note:
_DO_NOT_ de-reference a pointer which has not yet made to point to an address. So in your program int (*r)[10]; was de-referenced without being assigned to a memory area. This is not acceptable.
If you see the output - *r is same as *(r+0) which is same as r (only w.r.t this case)
If you see the output for *(r+0) and *(r+1) it is 40 bytes (0xbfeaa4dc - 0xbfeaa4b4 = sizeof(int) * size of the array (which is 10 in this case). So when you increment a pointer to a particular type, it gets incremented to sizeof(type) bytes!
the other worth-notable points about a pointer-to-an-array-of-integers are explained here
Hope this helps!
Remember that when an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" and its value will be the address of the first element in the array. The exceptions to this rule are when the array expression is an operand of either the sizeof or unary & (address-of) operands, or if the array expression is a string literal being used as an initializer in an array declaration.
Your situation is a mirror image of the following:
int a[10] = {0};
printf("a = %p, &a = %p\n", (void *) a, (void *) &a);
In the printf call, the expression a has its type converted from "10-element array of int" to "pointer to int" based on the rule above, and its value will be the address of the first element (&a[0]). The expression &a has type "pointer to 10-element array of int", and its value will be the same as a (the address of the first element in the array is the same as the address of the array itself).
Your code has a bit of undefined behavior in that you're dereferencing r before it has been assigned to point anywhere meaningful, so you can't trust that the output is at all accurate. We can fix that like so:
int a[10] = {0};
int (*r)[10] = &a;
printf("r = %p, *r = %p\n", (void *) r, (void *) *r);
In this case, r == &a and *r == a.
The expression r has type "pointer to 10-element array of int", and its value is the address of a. The expression *r has type "10-element array of int, which is converted to "pointer to int", and its value is set to the address of the first element, which in this case is a[0]. Again, the values of the two expressions are the same.
Related
void pass_arr(int arr[]);
void pass_arr_test()
{
int arr[5] = {1,2,3,4,5};
printf( "arr = %p\n"
"&arr = %p\n\n", arr, &arr);
pass_arr(arr);
}
void pass_arr(int arr[])
{
printf( "passed arr = %p\n"
"passed &arr = %p\n\n", arr, &arr);
}
Output:
arr = 0x28ccd0
&arr = 0x28ccd0
passed arr = 0x28ccd0
passed &arr = 0x28ccc0
Can someone explain why the value and adress of arr points to the same adress when evaluated in the block where arr was created, but when passed the value and adress point to two different adresses?
That's because in the function arr is actually a pointer, not an array. Taking the address of a pointer does not yield the same address, the way it does for an array.
Except when it is the operand of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to type "pointer to T", and the value of the expression will be the address of the first element of the array1.
When you call
`pass_arr(arr)`;
the expression arr is converted from type "5-element array of int" to "pointer to int", or int *.
Note that the address of the first element of the array is the address of the array itself; that's why you get the same value when you print the results of arr and &arr int pass_arr_test, but remember that the types are different; the expression arr is converted to type int *, but &arr has type int (*)[5]; this matters for things like pointer arithmetic.
Secondly, in the context of a function prototype, declarations of the form T a[] and T a[N] are interpreted as T *a; a is actually declared as a pointer instead of an array.2
The important thing to remember is that arrays are not pointers. Rather, in most contexts, array expressions are converted to pointers as necessary.
1 - N1570, 6.3.2.1 Lvalues, arrays, and function designators, ¶ 3
2 - N1570, 6.7.6.3 Function declarators (including prototypes), ¶ 7
That is due to pass by value semantics where the arr in pass_arr method is a local pointer variable on the stack whose value is the location of the arr passed from pass_arr_test method. So, arr variable in both pass_arr and pass_arr_test are point to the same location and hence the value is same. Since they are two different pointers, their memory address is different. In case of array definition, arr is just an alias to the start of the array and hence it's location and it's value are the same.
could you tell my why the value of a referenced
array and the value of the array itself has the same value?
i know a is a type of int* but with &a it should be int** or am i wrong??
so the value should be a pointer to the a int pointer.
example code:
#include <stdio.h>
int main()
{
int a[10];
printf("a without ref.: 0x%x\n",a);
printf("a with ref.: 0x%x\n",&a);
return 0;
}
http://ideone.com/KClQJ
Name of the array decays to an pointer to its first element in this case.
Name of the array will implicit convert to a pointer ,except for two situation ,the one situations is "&array",the other is "sizeof(array)".In both cases,name of the array is a array ,not a pointer .
For example:
int a[10];
int *p;
p = a; //a is a pointer
p = &a; //a is a array,&a is a constant pointer
sizeof(a); //a is array
Given an array declaration T a[N], the expression &a has type "pointer to N-element array of T (T (*)[N]) and its value is the base address of the array. In that respect, the unary & operator behaves the same for arrays as it does for any other data type.
What's hinky is how C treats the array expression a. Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an array expression of type "N-element array of T" (T [N]) will be replaced with ("decay to") a pointer expression of type "pointer to T" (T *) and its value will be the address of the first element of the array. IOW, a == &a[0].
Since the address of the first element of the array is the same as the base address of the entire array, the expressions a and &a yield the same value, but the types are different (T * as opposed to T (*)[N]).
if there is int *p which point a, then,
a+0 == &a[0] == p+0 == &p[0] : address
*(a+0) == *(&a[0]) == *(p+0) == *(&p[0]) : data
a == &a == &a[0]
Does
int **p
and
int *p[1]
mean the same thing? as both can be passed to functions allowing the change the pointer object, also both can be accessed via p[0], *p ?
Update, thanks for your help, tough Memory management seems different. does the access mechanism remain the same
*eg: p[0] becomes *(p+0) & *p (both pointing to something)
Thanks
Not quite.
int **p;
declares a pointer p, which will be used to point at objects of type int *, ie, pointers to int. It doesn't allocate any storage, or point p at anything in particular yet.
int *p[1];
declares an array p of one pointer to int: p's type can decay to int ** when it's passed around, but unlike the first statement, p here has an initial value and some storage is set aside.
Re. the edited question on access syntax: yes, *p == p[0] == *(p+0) for all pointers and arrays.
Re. the comment asking about sizeof: it deals properly with arrays where it can see the declaration, so it gives the total storage size.
void foo()
{
int **ptr;
int *array[10];
sizeof(ptr); // just the size of the pointer
sizeof(array); // 10 * sizeof(int *)
// popular idiom for getting count of elements in array:
sizeof(array)/sizeof(array[0]);
}
// this would always discard the array size,
// because the argument always decays to a pointer
size_t my_sizeof(int *p) { return sizeof(p); }
To simplify things, you could factor out one level of pointers since it's not relevant to the question.
The question then becomes: what's the difference between T* t and T t[1], where T is some type.
There are several differences, but the most obvious one has to do with memory management: the latter allocates memory for a single value of type T, whereas the the former does not (but it does allocate memory for the pointer).
They are not the same thing, although in many cases they can appear to behave the same way.
To make the discussion below flow better, I'm going to take the liberty of renaming your variables:
int **pp; // pointer to pointer
int *ap[1]; // array of pointer
If an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" whose value is the address of the first element in the array (the exceptions to this rule are when the array expression is an operand of either the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration).
So, suppose you write something like
foo(ap);
The expression ap has type "1-element array of pointer to int", but by the rule above it will be converted to an expression of type "pointer to pointer to int"; thus, the function foo will receive an argument of type int **, not int *[1].
On the other side of the equation, subscripting is defined in terms of pointer arithmetic: E1[E2] is defined as *(E1 + E2) where one of the expressions is a pointer value and the other is an integral value. Thus you can use a subscript operator on pp as though it were an array. This is why we can treat dynamically-allocated buffers as though they were regular arrays:
pp = malloc(sizeof *pp * N); // allocate N pointers to int (type of *pp == int *)
if (pp)
{
size_t i;
for (i = 0; i < N; i++)
pp[i] = ...; // set pp[i] to point to some int value
}
Now for some major differences. First of all, array expressions may not be the target of an assignment; for example, you can't write something like
ap = some_new_pointer_value();
As mentioned above, array expressions will not be converted to pointer types if they are the operands of either the sizeof or unary & operators. Thus, sizeof ap tells you the number of bytes required to store a 1-element array of type int *, not a pointer to a pointer to int. Similarly, the expression &ap has type int *(*)[1] (pointer to 1-element array of pointer to int), rather than int *** (which would be the case for &pp).
No, they are not the same.
int **p is a pointer to a pointer to int.
int *p[1] is an array (of length 1) of pointers to int.
They are not same:
int **p
Is a pointer which points to another pointer whose type is int *
while,
int *p[1];
Is an array of size 1 to the type int *
They are different.
int **p
means a pointer to a pointer to an int.
int *p[1]
means an array containing one element, with that element being a pointer to an int.
The second form can be treated the same as the first in some situations, e.g. by passing it to a function.
My understanding was that arrays were simply constant pointers to a sequence of values, and when you declared an array in C, you were declaring a pointer and allocating space for the sequence it points to.
But this confuses me: the following code:
char y[20];
char *z = y;
printf("y size is %lu\n", sizeof(y));
printf("y is %p\n", y);
printf("z size is %lu\n", sizeof(z));
printf("z is %p\n", z);
when compiled with Apple GCC gives the following result:
y size is 20
y is 0x7fff5fbff930
z size is 8
z is 0x7fff5fbff930
(my machine is 64 bit, pointers are 8 bytes long).
If 'y' is a constant pointer, why does it have a size of 20, like the sequence of values it points to? Is the variable name 'y' replaced by a memory address during compilation time whenever it is appropiate? Are arrays, then, some sort of syntactic sugar in C that is just translated to pointer stuff when compiled?
Here's the exact language from the C standard (n1256):
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.
The important thing to remember here is that there is a difference between an object (in C terms, meaning something that takes up memory) and the expression used to refer to that object.
When you declare an array such as
int a[10];
the object designated by the expression a is an array (i.e., a contiguous block of memory large enough to hold 10 int values), and the type of the expression a is "10-element array of int", or int [10]. If the expression a appears in a context other than as the operand of the sizeof or & operators, then its type is implicitly converted to int *, and its value is the address of the first element.
In the case of the sizeof operator, if the operand is an expression of type T [N], then the result is the number of bytes in the array object, not in a pointer to that object: N * sizeof T.
In the case of the & operator, the value is the address of the array, which is the same as the address of the first element of the array, but the type of the expression is different: given the declaration T a[N];, the type of the expression &a is T (*)[N], or pointer to N-element array of T. The value is the same as a or &a[0] (the address of the array is the same as the address of the first element in the array), but the difference in types matters. For example, given the code
int a[10];
int *p = a;
int (*ap)[10] = &a;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
p++;
ap++;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
you'll see output on the order of
p = 0xbff11e58, ap = 0xbff11e58
p = 0xbff11e5c, ap = 0xbff11e80
IOW, advancing p adds sizeof int (4) to the original value, whereas advancing ap adds 10 * sizeof int (40).
More standard language:
6.5.2.1 Array subscripting
Constraints
1 One of the expressions shall have type ‘‘pointer to object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.
Semantics
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).
Thus, when you subscript an array expression, what happens under the hood is that the offset from the address of the first element in the array is computed and the result is dereferenced. The expression
a[i] = 10;
is equivalent to
*((a)+(i)) = 10;
which is equivalent to
*((i)+(a)) = 10;
which is equivalent to
i[a] = 10;
Yes, array subscripting in C is commutative; for the love of God, never do this in production code.
Since array subscripting is defined in terms of pointer operations, you can apply the subscript operator to expressions of pointer type as well as array type:
int *p = malloc(sizeof *p * 10);
int i;
for (i = 0; i < 10; i++)
p[i] = some_initial_value();
Here's a handy table to remember some of these concepts:
Declaration: T a[N];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N] T * Address of the first element in a;
identical to writing &a[0]
&a T (*)[N] Address of the array; value is the same
as above, but the type is different
sizeof a size_t Number of bytes contained in the array
object (N * sizeof T)
*a T Value at a[0]
a[i] T Value at a[i]
&a[i] T * Address of a[i]
Declaration: T a[N][M];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N][M] T (*)[M] Address of the first subarray (&a[0])
&a T (*)[N][M] Address of the array (same value as
above, but different type)
sizeof a size_t Number of bytes contained in the
array object (N * M * sizeof T)
*a T [M] T * Value of a[0], which is the address
of the first element of the first subarray
(same as &a[0][0])
a[i] T [M] T * Value of a[i], which is the address
of the first element of the i'th subarray
&a[i] T (*)[M] Address of the i-th subarray; same value as
above, but different type
sizeof a[i] size_t Number of bytes contained in the i'th subarray
object (M * sizeof T)
*a[i] T Value of the first element of the i'th
subarray (a[i][0])
a[i][j] T Value at a[i][j]
&a[i][j] T * Address of a[i][j]
Declaration: T a[N][M][O];
Expression Type Converts to
---------- ---- -----------
a T [N][M][O] T (*)[M][O]
&a T (*)[N][M][O]
*a T [M][O] T (*)[O]
a[i] T [M][O] T (*)[O]
&a[i] T (*)[M][O]
*a[i] T [O] T *
a[i][j] T [O] T *
&a[i][j] T (*)[O]
*a[i][j] T
a[i][j][k] T
From here, the pattern for higher-dimensional arrays should be clear.
So, in summary: arrays are not pointers. In most contexts, array expressions are converted to pointer types.
Arrays are not pointers, though in most expressions an array name evaluates to a pointer to the first element of the array. So it is very, very easy to use an array name as a pointer. You will often see the term 'decay' used to describe this, as in "the array decayed to a pointer".
One exception is as the operand to the sizeof operator, where the result is the size of the array (in bytes, not elements).
A couple additional of issues related to this:
An array parameter to a function is a fiction - the compiler really passes a plain pointer (this doesn't apply to reference-to-array parameters in C++), so you cannot determine the actual size of an array passed to a function - you must pass that information some other way (maybe using an explicit additional parameter, or using a sentinel element - like C strings do)
Also, a common idiom to get the number of elements in an array is to use a macro like:
#define ARRAY_SIZE(arr) ((sizeof(arr))/sizeof(arr[0]))
This has the problem of accepting either an array name, where it will work, or a pointer, where it will give a nonsense result without warning from the compiler. There exist safer versions of the macro (particularly for C++) that will generate a warning or error when it's used with a pointer instead of an array. See the following SO items:
C++ version
a better (though still not perfectly safe) C version
Note: C99 VLAs (variable length arrays) might not follow all of these rules (in particular, they can be passed as parameters with the array size known by the called function). I have little experience with VLAs, and as far as I know they're not widely used. However, I do want to point out that the above discussion might apply differently to VLAs.
sizeof is evaluated at compile-time, and the compiler knows whether the operand is an array or a pointer. For arrays it gives the number of bytes occupied by the array. Your array is a char[] (and sizeof(char) is 1), thus sizeof happens to give you the number of elements. To get the number of elements in the general case, a common idiom is (here for int):
int y[20];
printf("number of elements in y is %lu\n", sizeof(y) / sizeof(int));
For pointers sizeof gives the number of bytes occupied by the raw pointer type.
In
char hello[] = "hello there"
int i;
and
char* hello = "hello there";
int i;
In the first instance (discounting alignment) 12 bytes will be stored for hello with the allocated space initialised to hello there while in the second hello there is stored elsewhere (possibly static space) and hello is initialised to point to the given string.
hello[2] as well as *(hello + 2) will return 'e' in both instances however.
In addition to what the others said, perhaps this article helps: http://en.wikipedia.org/wiki/C_%28programming_language%29#Array-pointer_interchangeability
If 'y' is a constant pointer, why does it have a size of 20, like the sequence of values it points to?
Because z is the address of the variable, and will always return 8 for your machine. You need to use the dereference pointer (&) in order to get the contents of a variable.
EDIT: A good distinction between the two: http://www.cs.cf.ac.uk/Dave/C/node10.html
I have the following program. However, I can't understand why I have to pass the address of the array. When they are both pointing to the same address. Which is the address of the first element of the array of int's.
I get a warning when I try and do this "assignment from incompatible pointer type":
ptr = var;
Complete source code:
void print_values(int (*ptr)[5])
{
size_t i = 0;
for(i = 0; i < 5; i++) {
printf("%d: [ %d ]\n", i, (*ptr)[i]);
}
}
int main(void)
{
/* declare a pointer to an array integers */
int (*ptr)[5] = NULL;
/* array of integers */
int var[] = {1, 2, 3, 4, 5};
/* assign the address of where the array is pointing to (first element) */
ptr = &var;
/* Both are pointing to the exact same address */
printf("var [ %p ]\n",(void*)var);
printf("&var [ %p ]\n", (void*)&var);
print_values(ptr);
return 0;
}
I compile the code with gcc 4.4.4 c89 -Wall -Wextra -O0
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 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 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;
C is a strongly typed language. When a function expects a parameter of type int *, you have to pass an argument of type int *. Not double *, not char *, but int *. Even if the actual numerical address in those double * or char * is "the same" as the one you want to pass, it still doesn't change anything - you still have to pass an int *. The language prohibits you from passing the value of wrong type.
This is exactly what happens in your case. The function takes a parameter of type int (*)[5]. That means that you have to pass the argument of that type. Passing an int * instead is not allowed. Whether the address is the same makes no difference.
From what I can tell you are assigning an array pointer (var) to a pointer that points to an array pointer ((*ptr)[5]), so that's why you get that warning.
Instead, try using
int *ptr = NULL;