C programming address for 2d array - c

If I initialized a 2d array let’s say
Int a[2][3] = {
1, 2, 3,
4, 5, 6};
Is a[0] == &a[0]??
I know a[0] refers to the address for the first element of the array. So is &a[0] still the address?

First of all, the type of arrayNum[0] is Int[3] and the type of &arrayNum[0] is Int(*)[3] (I didn't change the OP's Int to the probable int).
Secondly, arrays can decay to a pointer to its first element, so arrayNum[0] can decay to &arrayNum[0][0] which is of type Int*.
Both those pointers, &arrayNum[0] and &arrayNum[0][0] will point to the same location, but their types are very different.

I'm not sure what you meant to comapre using the == in your question, but let me tell you these, they are not the same.
Data type:
Check the data type.
a[0] is the first element of the array of type int [3].
&a[0] is the pointer to the first element of the array of type int [3], so, it is essentially int (*) [3].
Usage: Now, based on the usage, in certain cases Note, an "array type", decays to a pointer to it's first element. Considering that case, a[0] and &a[0], both are equivalent to writing &(a[0][0]), so the pointer value will be same.
For better understanding of the difference, use both a[0] and &a[0] as the argument yo sizeof operator (where the decay does not happen) and print the value using %zu conversion specifier.
Typically, they will print
12, which is (sizeof (int) * 3) and
8, which is sizeof (int (*) [3])
on a platform where size of an int is 4 and size of a pointer is 8.
[Note]:
Quoting C11, chapter §6.3.2.1
Except when it is the operand of the sizeof operator, the _Alignof 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. [....]

There are two senses in which you might ask whether a[0] equals &a[0]:
Do a[0] and &a[0] point to the same place?
and:
Does a[0] == &a[0] evaluate to true?
It is not clear from your question which you mean. Your text asks “Is a[0] == &a[0]?” Since the “==” is not in code format, it is not clear whether you intended to exclude it.
The answer to the first question is yes (given that a[0] is automatically converted to an address), and the answer to the second question is not necessarily.
As other answers and comments have pointed out, a[0] and &a[0] are different things. a is an array of two arrays of three int. So a[0] is an array of three int, and, in most expressions, it is automatically converted to a pointer to its first element. So the result is a pointer to an int, effectively &a[0][0]. In contrast, &a[0] is the address of an array of three int.
So, these expressions point to two different objects, but the two objects start at the same location, so the pointers point to the same “place.” We can see this in:
(char *) a[0] == (char *) &a[0] // Evaluates to true.
When we convert a pointer to a pointer to char, the result points to the first (lowest addressed) byte of the object. Since the two pointers point to the same place, this expression will evaluate to true.
However, when you evaluate a[0] == &a[0], there is a problem. To conform to the C standard, a comparison of pointers must compare pointers to compatible types. But int and array of three int are not compatible types. So this comparison is not strictly conforming C, although some compilers may allow it, likely with a warning message. We can instead evaluate:
a[0] == (int *) &a[0] // Value is not specified.
By converting the pointer on the right to a pointer to int, we make the left and right sides have the same type, and we can compare them. However, the result of the comparison is not defined. This is because that, although the C standard allows us to convert a pointer to one type to a pointer to another type, it does not generally guarantee what the value that results from the conversion is, except that, if you convert it back to the original type, then it will compare equal to the original pointer. (Converting to a pointer to a character type is special; for those, the compiler does guarantee the result points to the first byte of the object.)
So, since we do not know what the value of (int *) &a[0] is, we do not know whether comparing it to a[0] will return true or false.
This might seem strange; if one address points to the same place as another address, why wouldn’t they compare equal? On some computers, there is more than one way of referring to the same place in memory. Addresses may actually be formed of comnbinations of parts, such as base addresses plus offsets. For example, the address (1000, 230), representing 1230, points to the same place as (1200, 30), also representing 1230. But clearly (1000, 230) is not the same as (1200, 30).
When you compare two pointers to the same type, the compiler automatically adjusts the representations of the addresses in whatever way it needs to to perform the comparison. But, when you convert a pointer to one type to a pointer to another (non-character) type, the change of types may prevent the compiler from having the information it needs to do this adjustment properly. So the C standard does not tell us what happens in this case.

No they are not the same.
a[0] is an element of type int[3], while &a[0] is a pointer (of type int*[3]) to a[0].
But both of them points to the same address (the first element of a[0]), but are not the same.

Related

C - what is array name when not converted to pointer of its type?

So for a while I was confused about array names and pointers.
We declare int a[10];
And somewhere down the road also have a and &a.
So I get how the syntax works. a is the array name. When it is not used as an operand for sizeof &, etc., it will be converted or "decayed" so it returns a pointer to integer holding the address of the first element of the array.
If the array name is used as an operand for sizeof or &, its type is int (*)[10]. So I guess the type is different because that "decay" does not happen.
But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?
In comparison, if we declare int *p;
and later have &p and p somewhere in the code...
In this case the pointer to integer p is given a separate pointer cell with its address and the value at that address will be whatever address we assign to it (or the garbage value at that address pre-assignment).
a does not get assigned a separate pointer cell in memory when it is declared int a[10]. I heard it is identified with an offset on the register %ebp. Then what is happening with the compiler when it evaluates &a? The "decay" to a pointer to integer is not happening, there was no separate "pointer" in the first place. Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand?
Given:
int a[10];
the object a is of type int[10]. The expression a, in most but not all contexts, "decays" to a pointer expression; the expression yields a value of type int*, equivalent to &a[0].
But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?
That's not quite correct. In &a, the decay doesn't happen at all. a is of type "array of 10 int" (int[10]), so &a is of type "pointer to array of 10 int" (int(*)[10]).
There's nothing special about this. For any name foo of type some_type, the expression &foo is of type "pointer to some_type". (What's confusing about it is that this is one of the rare cases where an array name doesn't behave strangely.)
It's best to think of the words "array" and "pointer" as adjectives rather than nouns. Thus we can have an array object, an array expression, an array type, and so forth -- but just "an array" is ambiguous.
This:
int a[10];
defines an array object named a (and allocates 4 * sizeof (int) bytes to hold it). No pointer object is created. You can create a pointer value by taking the address of the object, or of any element of it. This is no different than objects of any other type. Defining an object of type some_type doesn't create an object of type some_type*, but you can create a value of type some_type* by computing the address of the object.
Then what does the compiler identify a as and what does it do when it
sees that unary & operator is using the array name as an operand?
The compiler identifies a as a 10-element integer array, and when it sees the & operator, it returns the address of that array.
Just like it would see int i = 3; as an integer, and &i as the address of that integer.
Concerning taking the address of an array: an array is an object in and of itself, so it has both a size and an address (though taking its address is seldom useful).
The conversion of an array to a pointer to its first element is a form of type coercion. It only happens if the alternative would be a compile error.
For instance, you can't compare an array to a pointer, so the array (implicitly) is coerced (cast) to an int* (to its first element) and then the pointer types are compared. In C you can compare any pointer types. C just doesn't care (though it will likely emit a warning).
This is actually comparing int* to int(*)[10] as far as types are concerned, as you said. These will necessary have the same address (regardless of typing) because arrays hold their data directly. So the address of an array will always be the address of its first element.
However, it's not an error to get the size of an array, so sizeof(a) gets the size of the entire array, as no coercion is needed to make this legal. So this is the same as sizeof(int[10]).
Your other case sizeof(&a) is really sizeof(int(*)[10]) as you said.

division during pointer subtraction in C

Consider below code snippet :
int *p;
/* Lets say p points to address 100
and sizeof(int) is 4 bytes. */
int *q = p+1;
unsigned long r = q-p;
/* r results in 1, hence for r = q-p
something is happening similar to r=(104-100)/4 */
Is there a real division by sizeof(datatype) going on during runtime when two pointers of same type are subtracted, or there is some other mechanism through which pointer subtraction works.
The C standard states the following regarding pointer subtraction (section 6.5.6p9):
When two pointers are subtracted, both shall point to elements of the
same array object, or one past the last element of the array
object; the result is the difference of the subscripts of the
two array elements. The size of the result is
implementation-defined, and its type (a signed integer type) is
ptrdiff_t defined in the header. If the result is not
representable in an object of that type, the behavior is
undefined. In other words, if the expressions P and Q point to,
respectively, the i
-th and j
-th elements of an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t . Moreover,
if the expression P points either to an element of an array object or
one past the last element of an array object, and the expression Q
points to the last element of the same array object, the expression
((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as
-((P)-((Q)+1)) , and has the value zero if the expression P points one past the last element of the array object, even
though the expression (Q)+1 does not point to an element of the array
object. 106)
Footnote 106 states:
Another way to approach pointer arithmetic is first to convert the
pointer(s) to character pointer(s): In this scheme the integer
expression added to or subtracted from the converted pointer is first
multiplied by the size of the object originally pointed to,
and the resulting pointer is converted back to the original
type. For pointer subtraction, the result of the difference
between the character pointers is similarly divided by the size of
the object originally pointed to. When viewed in this way, an
implementation need only provide one extra byte (which may
overlap another object in the program) just after the end of the
object in order to satisfy the "one past the last element"
requirements.
So the footnote states that pointer subtraction may be implemented by subtracting the raw pointer values and dividing by the size of the pointed-to object. It doesn't have to be implemented this way, however.
Note also that the standard requires that pointer subtraction is performed between pointers pointing to elements of the same array object (or one element past the end). If they don't then the behavior is undefined. In practice, if you're working on a system with a flat memory model you'll probably still get the "expected" values but you can't depend on that.
See #dbush answer for the explanation on how pointer substraction works.
If, instead, you are programming something low-level, say a kernel, driver, debugger or similar and you need to have actual subtraction of addresses, cast the pointers to char *:
(char *)q - (char *)p
The result will be of ptrdiff_t type, an implementation defined signed integer.
Of course, this is not defined/portable C, but will work on most architectures/environments.

Head First C: Erratum? Pointer Syntax

I am teaching myself C programming, using "Head First C", published by O'Reilly. (And a couple of other texts, besides.)
I got very hung-up during the book's introduction to pointers, by the example program on p.58. What threw me was a little call-out in the text, pointing to the line:
int *choice = contestants;
The call-out reads:
“choice” is now the address of the “contestants” array.
And, as far as I can tell, that's wrong. That line assigns *choice to the value stored as the contestants array, is that not so?
Disclaimer: I don't have access to the book / chapter right now.
Considering contestants is of array type, quoting C11, chapter §6.3.2.1 (emphasis mine)
Except when it is the operand of the sizeof operator, the _Alignof 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. [...]
In your case, the array variable is used as the RHS of the assignment operator, so in that case contestants is the same as &(contestants[0]).
This is the exact same type of int * which is the same of the variable to be assigned (LHS).
So you have four answers already, but none of them mention the difference between assignment and initialization syntaxes.
int *choice = contestants; // initialization
The above is equivalent to this:
int *choice; // declaration
choice = contestants; // assignment to pointer
but completely different from this (which can't be done in an initialization):
int *choice; // declaration
*choice = contestants; // assignment to target (not valid unless choice is initialized)
The second version is incorrect as written because it tries to store the value of contestants at the address pointed to by choice -- but choice does not contain an address, unless you initialize it. Dereferencing a possibly-uninitialized pointer is always a mistake.
The book is correct. Pointers work differently from variables, and * works differently in different circumstances.
To start, you probably know that a pointer is just a variable containing the address to the location in memory of another item
When we use
int *choice
we create a pointer to an integer, which stores the address of the integer
In this case, I'm assuming contestants is an array. We'll assume it's an array of ints
int contestants[5] = [0,1,2,3,4];
Collections, such as arrays, are always stored as a pointer to the first element. The second element is therefore addressof_first_item + sizeof(element_stored).
Let's assume the address is 0x12345, it's like this int contestants = 0x12345
And now we store that address in choice:
int *choice = contestants
In other words, it's a pointer to an integer, which happens to be the first element in the contestants array.
As a side note, we could also write it as:
int* choice = &contestants[0];
The other use case for the * operator with regards to pointers, is dereferencing. Dereferencing involves getting the value at the address pointed to by a pointer.
int value = *choice;
will give us an integer with a value of 0, because the address stored points to the first element
What you maybe don't know is that the name of an array is a pointer on the first element of this array. example
int contestants[] = {1, 2, 3};
means that &contestants[0] has the same value as contestants
This is explained earlier in the chapter, in the BULLET POINTS list.
An array variable can be used as a pointer.
The array variable points to the first element in the array.
And also further down in the box labeled POINTER DECAY:
Because array variables are slightly different from pointer variables, you need to be careful when you assign arrays to pointers. If you assign an array to a pointer variable, then the pointer variable will only contain the address of the array.
Strictly speaking, the book is not correct, but your reasoning is also incorrect.
Assuming contestants is an array of int, the initialisation
int *choice = contestants;
is equivalent to
int *choice = &contestants[0];
In other words, the value of choice is the address of the first element of contestants. This conversion of contestants (the name of an array) to &contestants[0] (a pointer) commonly known as an "array to pointer" conversion.
However, this differs from the address of the contestants array, since the type is wrong. The address of the contestants array is &contestants, which has type int (*)[4] (i.e. address of an array of four int).
If you try to initialise
int *choice = &contestants;
the result will be a compilation error (since an int(*)[4] cannot be implicitly converted to an int *).
Your reasoning
And, as far as I can tell, that's wrong. That line assigns *choice to the value stored as the contestants array, is that not so?
is flawed, since the contestants does not have a stored value. It is a set of values.
It is true that &contestants[0] and &contestants have the same value, but they also have different type. So a comparison of &contestant[0] == &contestants will not compile. However, if the values are converted to a common type, such as (void *)(&contestants[0]) == (void *)(&contestants), the code will compile, and the converted values will compare equal.

Accesing a 2D array using a single pointer

There are tons of code like this one:
#include <stdio.h>
int main(void)
{
int a[2][2] = {{0, 1}, {2, -1}};
int *p = &a[0][0];
while (*p != -1) {
printf("%d\n", *p);
p++;
}
return 0;
}
But based on this answer, the behavior is undefined.
N1570. 6.5.6 p8:
When an expression that has integer type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If the
pointer operand points to an element of an array object, and the array
is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integer expression.
In other words, if the expression P points to the i-th element of an
array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
(where N has the value n) point to, respectively, the i+n-th and
i−n-th elements of the array object, provided they exist. Moreover,
if the expression P points to the last element of an array object, the
expression (P)+1 points one past the last element of the array object,
and if the expression Q points one past the last element of an array
object, the expression (Q)-1 points to the last element of the array
object. If both the pointer operand and the result point to elements
of the same array object, or one past the last element of the array
object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element
of the array object, it shall not be used as the operand of a unary
* operator that is evaluated.
Can someone explain this in detail?
The array who's base address (pointer to first element) p is assigned is of type int[2]. This means the address in p can legally be dereferenced only at locations *p and *(p+1), or if you prefer subscript notation, p[0] and p[1]. Furthermore, p+2 is guaranteed to be a legally evaluated as an address, and comparable to other addresses in that sequence, but can not be dereferenced. This is the one-past address.
The code you posted violates the one-past rule by dereferencing p once it passes the last element in the array in which it is homed. That the array in which it is homed is buttressed up against another array of similar dimension is not relevant to the formal definition cited.
That said, in practice it works, but as is often said. observed behavior is not, and should never be considered, defined behavior. Just because it works doesn't make it right.
The object representation of pointers is opaque, in C. There is no prohibition against pointers having bounds information encoded. That's one possibility to keep in mind.
More practically, implementations are also able to achieve certain optimizations based on assumptions which are asserted by rules like these: Aliasing.
Then there's the protection of programmers from accidents.
Consider the following code, inside a function body:
struct {
char c;
int i;
} foo;
char * cp1 = (char *) &foo;
char * cp2 = &foo.c;
Given this, cp1 and cp2 will compare as equal, but their bounds are nonetheless different. cp1 can point to any byte of foo and even to "one past" foo, but cp2 can only point to "one past" foo.c, at most, if we wish to maintain defined behaviour.
In this example, there might be padding between the foo.c and foo.i members. While the first byte of that padding co-incides with "one past" the foo.c member, cp2 + 2 might point into the other padding. The implementation can notice this during translation and instead of producing a program, it can advise you that you might be doing something you didn't think you were doing.
By contrast, if you read the initializer for the cp1 pointer, it intuitively suggests that it can access any byte of the foo structure, including padding.
In summary, this can produce undefined behaviour during translation (a warning or error) or during program execution (by encoding bounds information); there's no difference, standard-wise: The behaviour is undefined.
You can cast your pointer into a pointer to a pointer to array to ensure the correct array semantics.
This code is indeed not defined but provided as a C extension in every compiler in common usage today.
However the correct way of doing it would be to cast the pointer into a pointer to array as so:
((int (*)[2])p)[0][0]
to get the zeroth element or say:
((int (*)[2])p)[1][1]
to get the last.
To be strict, he reason I think this is illegal is that you are breaking strict aliasing, pointers to different types may not point to the same address (variable).
In this case you are creating a pointer to an array of ints and a pointer to an int and pointing them to the same value, this is not allowed by the standard as the only type that may alias another pointer is a char * and even this is rarely used properly.

If a is array(such as int a[4];),then what is &a? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C: How come an array’s address is equal to its value?
I test in GCC 4.4.1 and I find &a=a. I can't understand it. I think &a should be the address where stores the address of the array, it can't be the same. Could someone give me a good explanation? Thanks very much.
An array is an object in memory. It has an address and a size. It's also true that in certain contexts, an array decays into a pointer to its first element. So numerically, if both a and &a are compared as pointer values, they compare as equal, since they both point to the same address in memory. But they have different data types: a has type int[4] ("array 4 of int"), or int* ("pointer to int") in certain contexts, whereas &a always has type int (*)[4] ("pointer to array 4 of int").
&a points here
|
V
+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] | sizeof(a) == 16
+------+------+------+------+
^
|
&a[0] also points here
In certain contexts, 'a' means &a[0]
Hence, (void *)a == (void *)&a.
Also note that because a and &a point to different data types (and in particular, the pointed-to types have different sizes), doing pointer arithmetic will yield different results. a+1 will point to &a[1] (advances by one int value), whereas &a+1 will point to just past the end of the array at &a[4], since it advances by one "array 4 of int" unit:
&a+1 points here
|
V
+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] |
+------+------+------+------+
^
|
a+1 points here
If a is declared as int a[4], then &a is a pointer with the type int *[4]( poointer to an array of 4 int).
When used in most expression contexts, a evaluates to a pointer to the first element of a, and has the type int*. The expression is exactly equivalent to &a[0]. This is required by the C99 standard in 6.3.2.1/3 "Lvalues, arrays, and function designators":
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.
This is commonly known as decaying to a pointer; you'll hear it talked about as "a decays to a pointer".
So, the first element of an array has the same address as the array itself, by definition. So while &a and a have different types, they have the same pointer value.
&a points to the address of the first element in the array(i.e a[0]).
a holds the address of the array.
And the address of the array(i.e a) is equal to the address of the first item in the array(i.e&a).
a is the array.
&a is the address of the array.
In most contexts, a used in an expression evaluates to the address of the first element of the array. Which of course is the same address as the address of the array, but with a different type. &a is not one of those contexts, but the a on the RHS of your comparison is.
For another example of two things that have the same value but with different type, consider that (int)1 == (char)1 and for that matter (int)1 == (float)1. Same numeric values, so they compare equal, but different types, so they don't behave the same for all purposes.
"It" doesn't store the address of the array anywhere that you're entitled to worry about. If a is an automatic variable, the compiler "knows" what offset a is at from the stack pointer, it doesn't necessarily store the address of a anywhere unless you tell it to. If it's a global variable, then its address may be stored in some symbol table somewhere, but your program doesn't directly access that location in the symbol table.
int a[4];
a is an array 4 of int. Its type name is int [4].
&a is a pointer to array 4 of int. Its type name is int (*)[4].
Note that the expression &a = a is invalid in C: the left operand of the assignment operator has to be a modifiable lvalue but the result of the & operator is never a lvalue.
The address of the array is equal to the address of the first item in the array.
from wikipedia:
Array-pointer interchangeability
The "subscript" notation x[i] (where
x designates a pointer) is a syntactic sugar for *(x+i).
so x = *(x+0)
wikipedia page

Resources