-3

So I almost went all hurr durr on my classmates when they wrote that

&array gives you address of the first element

But turns out they are right. This sounds like inconsistency to me. We're talking about array defined like this:

int numbers[] = {1,2,3,4};

The variable numbers is (I think) then of type int* const. I'd think that pointer to that would be int** const. But apparently this expression evaluates as true:

if(&numbers == numbers) {
    printf("Pointer to array is still the same array!\n");
}

And of course, this then also is true:

int* first_elm_ptr = &numbers;
if(*first_elm_ptr == *numbers)
    printf("%d == %d\n", *first_elm_ptr, *numbers);

So apparently you cannot get a pointer to the variable holding address of that array. Expression &numbers is essentially meaningless. Maybe it is even removed by compiler.

How's that possible? I am very confused right now! How does standard explain this behaviour? I made an ideone test code to verify this: http://ideone.com/pYffYx

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 2
    "`&array` gives you address of the first element" is very wrong! And the rest of your claims don't look better. It might be aq good idea to read a C book and not listen to your classmates, who seem to be quite clueless. Hint: an array is not a pointer! – too honest for this site Jan 10 '17 at 18:39
  • 2
    @Olaf Those are not *claims*, since this is a question, not an answer. – Tomáš Zato Jan 10 '17 at 18:41
  • 1
    `int numbers = {1,2,3,4};` is a syntax error; I think you *meant* `int numbers[] = {1,2,3,4};`. The type of the expression `numbers` is `int [4]`; unless that expression is the operand of the `sizeof` or unary `&` operators, it "decays" to an expression of type `int *`, and its value is the same as `&numbers[0]`. The type of the expression `&numbers` is `int (*)[4]` (pointer to 4-element array of int). It's value is the same as `numbers` (modulo any type conversions), but the *type* is different. – John Bode Jan 10 '17 at 18:45
  • 2
    "But turns out they are right." - that's a claim, maybe a prerequsite of your question, but not a question as such. And there are many more false assumptions (one of them was just corrected by you). – too honest for this site Jan 10 '17 at 18:51
  • 2
    @Olaf Strictly speaking `&array` returns the address of the array; is this not necessarily also the address of the first element of said array? (even if the resulting pointer has a different type) – davmac Jan 10 '17 at 18:56
  • `&array` and `&array[0]` are pointers (of different types) that compare equal to each other. They need not have the same bit pattern. – chux - Reinstate Monica Jan 10 '17 at 19:08
  • @davmac: An object has not only a value, but also a type. C is already weakly typed, we should avoid weakening it further. Both are relevant. Try `sizeof("Hello World") == sizeof(&"Hello World")`. Interestingly there were CPU designs in the 70ies and 80ies which were aware of object types. They did not make it to larger production (among other reasons) because of required logic gates and because back them type-safe programming was just starting in the larger field. Maybe once we hav AVX4096, etc. CPU designers come back to type-safe CPUs. This couldenhance security much more than another VM. – too honest for this site Jan 10 '17 at 19:08
  • 1
    @Olaf yes, an array has a type and its first element has a different type; my point is that they necessarily have the same address. In that sense at least, `&a` _does_ return the address of the first element of `a`. – davmac Jan 10 '17 at 19:16
  • @davmac: They do not have the same address! I tried to make clear that the address is not only the value, but also the type. What is unclear about that? Write type-correct code and don't use invalid hacks. There is no need for that assumption. If you enable recommended warnings, the compiler will correctly complain about such code. – too honest for this site Jan 10 '17 at 19:20
  • @Olaf an _address_ does not have a type; you said that an _object_ has a type, and that is correct. An _address_ describes a location in storage. An array is sequence of contiguous elements, and necessarily those elements are within the region of storage used by the array itself. It does not make sense to argue that the array object and its elements do no not overlap; therefore their address ranges must overlap. Please do not confuse "address" with "pointer value". – davmac Jan 10 '17 at 21:31
  • @davmac: Please provide a reference to the standard where it requires two objects of different type to have the same representation! The address of an object is bound to its type. But this discussion is pointless, you just confuse beginners and seem to propose bad practice. Finally: read 6.5.3.2p3 in the standard: "The unary & operator **yields the address** of its operand. If the operand has type ''type'', **the result has type** ''pointer to type'''." This implies addresses according to the standard very well have a type! – too honest for this site Jan 10 '17 at 21:55
  • It **is** not the same. See my edited comment above and read the standard. Btw: The array name as such is not the address of its first element, but is **converted** to it! That's an important difference. – too honest for this site Jan 10 '17 at 22:01
  • @Olaf I did not claim that two objects of different type have the same representation. Your quotation from the standard is seemingly relevant but I believe simply stems from an inconsistency in the standard; the term "address" is used mostly to denote something akin to an address within storage, which is clearly not typed; what they mean in 6.5.3.2p3 is that it yields a *pointer* to its operand. See eg 6.2.8 in C11 for a more regular usage of "address" which implies no type. If we take "address" to mean "location in storage" then clearly the address of an array and its first element match. – davmac Jan 10 '17 at 22:11
  • _sigh_ you claimed they have the same _address_. Which the cited part of the standard proves wrong. If that still is not clear, I can't help you. I give up. – too honest for this site Jan 10 '17 at 22:14
  • 3
    @Olaf, sigh indeed. I have already clearly stated the problem with taking that particular citation as gospel regarding the meaning of "address". See for another example 6.7.2.1p15: _Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared_ - this is clearly not meant to imply that pointers to different members of the same structure all have the same type, implying that the type is not part of the _address_. – davmac Jan 10 '17 at 22:26
  • 2
    @Olaf "address" is not a term defined by the standard, so insisting that it must have a *specific* definition involving types is silly. However, its use in the context of alignment descriptions implies that an "address" is a property primarily of *bytes*, i.e. the actual value (not representation) of their location, i.e. type is irrelevant as it's too high-level a concept. – Alex Celeste Jan 11 '17 at 12:43
  • @Leushenko: As this is about the unary `&` operator, we can asume the most relevant part here is the semantics of that operator. And the standard is quite clear here. Another aspect is that "the array and the first element have the same address" implies they compare equal, which is not guaranteed by the standard. Actually they may not even be compared, as they point to objects of different type. – too honest for this site Jan 11 '17 at 12:50
  • 1
    @Olaf 6.2.5 _An array type describes a contiguously allocated nonempty set of objects_ - strongly implies, at least, that the elements are allocated in order; since the array object necessarily overlaps its element objects, this in turn implies that the location of the first element coincides with the location of the array itself. 6.5.6 _For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type._ - proves it for array size == 1. – davmac Jan 12 '17 at 12:38
  • 1
    @Olaf furthermore the paragraph you cite does _not_ actually say that an address has a type (though I see why you think it does). By "yields the address of the operand" it means that the value component of the result is the address; the second part, about the type, is distinct. This is similar to other operators, eg addition: _The result of the binary + operator is the sum of the operands_ - although other paragraphs describe the type of the result, this does not mean that eg the number 8 from `4 + 4` has an intrinsic type; the type of the expression is distinct from its value. – davmac Jan 12 '17 at 13:11
  • @davmac: You completely missed the point! Read about compiler optimisations, the abstract machine, observable behaviour and what undefined behaviour implies. Then take a long holiday , come back and read that again. Then meditate 1-2 years about what all these mean and have to do with what I wrote (they have!). Then we can start a **true** discussion. – too honest for this site Jan 12 '17 at 13:27
  • 1
    @Olaf I did not miss the point, and I understand the concepts of the abstract machine and observable behaviour perfectly well, thank you. Being arrogant and condescending will not help you to understand what I am saying; you need to read it carefully and consider it with care. Although I believe you are incorrect, I have at least replied with courtesy to your remarks; you should do the same. That is all. – davmac Jan 12 '17 at 13:41

1 Answers1

1

The address of an array and the address of the first element of the array are essentially same value (same address location). They differ in type.

Expression &numbers is essentially meaningless

No, it is not.

In your case,

  • &numbers is of type int (*) [4]
  • numbers is of type int [4], and in some casesNote, it decays to int *.

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 [....]

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 4
    "in some cases" -> interesting note: per [defect report](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1930.htm), it's not currently adequately specified which exactly all of these cases are; the C11 standard appears to contradict itself. – Alex Celeste Jan 10 '17 at 18:40
  • As `_Generic` is not an operator, I'd interpret it as if 6.3.2.1 does apply. But I'm not sure if it _should_. So you have a point indeed, thanks for the info, very interesting. – too honest for this site Jan 10 '17 at 18:47