42

Just about everyone reading this is probably familiar with these three key facts about C:

  1. When you mention the name of an array in an expression, it evaluates (most of the time) to a pointer to the array's first element.
  2. The "array subscripting" operator [] works just as well for pointers as it does for arrays.
  3. A function parameter that seems to be an array actually declares a pointer.

These three facts are absolutely central to array and pointer handling in C. They're not even three separate facts; they're interlinked facets of one central concept. It is not possible to do even fairly basic C programming properly without a decent understanding of this concept.

My question today is simply, What is the name for this concept?

I supposed I'm old-fashioned, but I've always called it "The equivalence between arrays and pointers in C", or "array/pointer equivalence" for short. But I've learned that you almost can't say those words on SO; they're pretty much taboo.

This may seem like an abstract or philosophical question, so to frame it more concretely, what I'm looking for is is a simple noun or noun phrase I could use in the sentence "Yes, due to _____, array subscripting can be thought of as syntactic sugar for pointer arithmetic", in answer to, say, this question.

(But please note that I am not looking for answers to that question, or for answers to the question "What's wrong with the word 'equivalence'?". Yes, I know, it can mislead learners into imagining that arrays and pointers are somehow the same. I did have that confusion in mind when I wrote this FAQ list entry.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 22
    Perhaps "array decay"? – byxor Feb 19 '18 at 14:35
  • 4
    The equivalence is about *expressions*, using either the `[]` or the (unary) `*` operators. Most people nowadays appear to think in terms of array and pointer *objects*, causing the confusion. (because these objects are not equivalent) IMHO, IANALL. – joop Feb 19 '18 at 14:43
  • If the phrase "implicit integer promotion" is anything to go by, I think the phrase "implicit array conversion" should be understandable by most. – Mark Benningfield Feb 19 '18 at 15:28
  • 1
    I know the most common expression is "array decay", but I'm not a big fan as "decay" sounds involuntary whereas the behavior is intentional in the language design. Personally I would prefer if it was called "array erasure" (borrowed from Java's "type erasure"). – Simon Berthiaume Feb 19 '18 at 16:15
  • I don't think there can be a punctual definition to something that comes from a practical side accident for the language. An array is a stream of coherent values that lays adjacently in memory. To access them you need the address where the stream begins, so a pointer. But a pointer is a variable (a memory location) that **can hold a memory address**, but not the array storage memory. So the 2 are different and we have a problem. To handle this in the language has been used many 'special cases' the chaos. Maybe the more appropriate definition could have been **constant, not modifiable pointer** – Frankie_C Feb 19 '18 at 16:18
  • 'Implicit reference by address'? – Martin James Feb 19 '18 at 18:29
  • 'inconsistent fudge to generate confusion'? – Martin James Feb 19 '18 at 18:29
  • 1
    'Tequila Sunrise syntax'? – Martin James Feb 19 '18 at 18:30
  • If arrays and pointers were equivalent then `char *a = "hi";` and `char a[] = "hi";` would mean exactly the same thing – user253751 Feb 20 '18 at 00:59
  • Yeah, “array decay” sounds more like something that produces a lepton and a quark or some such, not a pointer... – rickster Feb 20 '18 at 08:12
  • 1
    Thanks for all the thoughtful comments and answers. I have summarized them in my own "answer" below. – Steve Summit Feb 20 '18 at 14:08
  • I'm surprised this good question didn't get 'storm closed'. Stackoverflow doesn't generally like questions that can't be answered with "your problem is here..." even if it's the billionth time someone has asked about floating point precision problems. – Michael Burr Feb 20 '18 at 15:47

11 Answers11

33
  1. The "array subscripting" operator [] works just as well for pointers as it does for arrays.

No, in fact it only works for pointers. Whenever you type [] in an expression, you always get a pointer to the first element. This is guaranteed to happen since arr[i] must be equivalent to *(arr + i). The former is "syntactic sugar" for the latter.

  1. A function parameter that seems to be an array actually declares a pointer.

This is actually a special case, referred to as "array adjustment", where the compiler implicitly changes the declaration of a function parameter of array type into a pointer to the first element. The rationale is surely to make functions compatible with the "array decay" of expressions, but the C standard keeps the terms separate.

Both cases, expressions and function parameters, are often referred to informally as "array decay". Though sometimes this is only used for expressions and not for function parameters. I don't think there exists a single, consistent use of the term. "Array decay" is the best one I think, although the C standard does not use that term anywhere.


(I dislike the term "equivalence", because an array can turn into a pointer, but not the other way around. Indeed there's always countless beginners coming up with confused beliefs such as "arrays and pointers are the same thing". Calling them "equivalent" doesn't exactly help.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    "*Whenever you type [] in an expression, you always get a pointer to the first element*" is, I think, badly worded. The result of using `[]` on a `T*` is not a `T*`, it's a `T`. Not sure how it could be worded better, though. – Nic Feb 20 '18 at 03:49
  • 1
    @NicHartley The result of using `[i]` on a `T*` is a `*(T + i)`. The result of the expression will indeed be a lvalue of type `T`. – Lundin Feb 20 '18 at 07:29
  • 1
    I should have said something like "The 'array subscripting' operator `[]` works just as well for pointers as it (seems to) work for arrays." No, `[]` never sees an array, always a pointer, but I think it's safe to say that for most programmers, most of the time, `[]` is at least *imagined* to be an array subscripting operator, acting on an array if that's what the operand is declared as. – Steve Summit Feb 20 '18 at 14:03
  • All in all I think I agree with the upvoters that this was the best answer to a difficult question without one, so I'm accepting it; see my "answer" below for more explanation. – Steve Summit Feb 20 '18 at 14:03
14

The C standard doesn't have a single word for this. It uses the word "conversion" when defining behavior (1) in 6.3.2.1p3, "equivalent" when defining behavior (2) in 6.5.2.1p2, and "adjustment" when defining behavior (3) in 6.7.6.3p7.

I am old-fashioned, and don't think there's anything wrong with calling this "array/pointer equivalence", provided it is clear in context that you are talking about expressions where (1) happens or function declarations where (3) happens. However, a more palatable term for the people who don't like "equivalence" would perhaps be "array-to-pointer conversion", since this confuses people most often when it's (1), I think.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • I don't think there's much wrong with calling it "array/pointer equivalence", either, but seriously, don't try saying that in an answer on SO! Last time I tried it I got downvoted into oblivion, and had to delete the (otherwise fine, IMO) answer just to stop the carnage. – Steve Summit Feb 20 '18 at 14:04
9

I would go with the term of array decay. This term goes well with what it suggests. The C standard doesn't say about it in this context and yes the first day I heard the term I went for searching it in the standard but I couldn't find it (So it's a bit confusing regarding who coined the term etc). Also alternatively one can write due to "most scenarios array is converted into pointer"... - No this is not a single Noun. But this is not letting any misinterpretation to take place. Standard itself says it the "conversion".

Most of the time I try to say it the long way and then put the word ("array decaying") in bracket. In fact there are answers where I didn't even mention it and just went with the standard's words of conversion into pointer.

user2736738
  • 30,591
  • 5
  • 42
  • 56
  • 1
    @bolov.: Ah yes...but *array decay*..who coined this term? C standard uses decay in 1 place and that is really out of context of what we are being asked. I am sure none of the standard uses decay to denote this thing. – user2736738 Feb 19 '18 at 15:07
  • 3
    I did a quick search and it looks like "decay" wasn't used in "The C programming Language" by Kernighan and Ritchie either. So it is an interesting question where the term comes from. – bolov Feb 19 '18 at 15:14
  • 1
    @bolov.: And bolov you commented and it's good - but did you see that it is in C tag - that's why I didnt mention that I was talking about C standard. :) I am looking for the origin of the term. – user2736738 Feb 19 '18 at 15:15
  • 2
    I don't remember exactly where "decay" came from either, but it was the term always used on comp.lang.c, back in the day. See my "answer" below for why I'm not accepting it, but it's a nice try, so +1. – Steve Summit Feb 20 '18 at 14:04
5

I suggest "array-to-pointer decay" is a reasonable shorthand, since "decay" is commonplace jargon in referring to the type conversion, with precedent elsewhere in the C FAQ: Question 6.12:

Q: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?

An extended technical meaning of "decay" that includes this one has been adopted into C++ Standard Library nomenclature since C++11: std::decay

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
5

There is no single name given to the three concepts mentioned, but I think describing them as implying any sort of "equivalence" is counter-productive, at least when describing "modern" C. While the results of array decay generally behave like pointers, C99 specifies that the pointers yielded by array decay are not required to be behave in the same way as pointers achieved via other means. Given:

char fetch_byte_at(void *p, int x) { return ((char*)p)[x]; }

struct {char arr[5][7];} s;
char test1(int x) { return s.arr[0][x]; }
char test2(int x) { return fetch_byte_at(&s, x); }

the Standard doesn't directly specify any reason why pointer value s.arr[0] used in test1 should not be equivalent to the pointer value ((char*)(void*)s) used when fetch_byte_at is called from test2. It does, however, simultaneously imply that test2 should be able to read out all the bytes of s [implying that it should work predictably with values of x up to at least 34] while saying that s.arr[0][x] is only meaningful for values of x up to 6.

While nothing in the Standard would contradict either of your first two points individually, it's not possible for both to hold. Either the result of an array decay is something other than an "ordinary" pointer to the array's first element, or applying the [] operator to an array has different semantics from applying it to a pointer. While it's unclear which of #1 and #2 has been invalidated by C99, they no longer together form any kind of "equivalence" in modern C.

If you recognize a distinction between traditional C and "modern" C, it might be useful to establish terms for the things that make the former useful. Such things go beyond the points you mention, however. Unfortunately, I don't know of any standard terms for such things, and would not look for the Standard to supply such terminology when it no longer supports the concepts involved.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Your example is somewhat perplexing to me; its introduction of 2-D arrays and a wrapping structure, and `fetch_byte_at`'s use of `void *` to scrape off most type information, rather confuses things. – Steve Summit Feb 20 '18 at 14:05
  • If we stick to simple, single arrays and pointers, I don't think there's any disagreement that for `arr` of type array-of-T, the expression `arr` has type pointer-to-T, and that `[]` applies equally. (I don't think this has changed at any point over the years, either. There's more clarity in terms of what you can and can't get away with when you try to "flatten" a multidimensional array or pun pointers, but those are different questions.) – Steve Summit Feb 20 '18 at 14:05
  • @SteveSummit: I thought the use of `&` on an lvalue of array type might confuse people. I thought that wrapping an array in a structure and taking the address of the structure would make clear that code was dealing with the address of the aggregate. – supercat Feb 20 '18 at 16:41
4

Thanks, everybody. I'm using this "answer" to summarize the answers people gave and my assessment of them, not as a proper answer I expect anyone to upvote or anything.

A lot of people put serious thought into this question, and I appreciate that. But at this point the only thing I can conclude is that there is no answer, today at least, to the question I had in mind.

Quite a few people suggested "array decay", and that's a very nice shot, but it doesn't work for me. It refers mostly to fact 1 and maybe fact 3 as listed in the original question, but not really fact 2. You can't say "Yes, due to array decay, array subscripting can be thought of as syntactic sugar for pointer arithmetic." (Or at least, you can't say that if your intent is to be clear and instructive.) You'd have to say something like "Yes, due to array decay and the way pointer arithmetic is defined so as to be consistent with it, array subscripting can be thought of as syntactic sugar for pointer arithmetic", which is, well, a different kettle of fish entirely.

Although I didn't say so explicitly, I was looking for a term in common, widespread, accepted use, although there was no requirement that it involve words actually used in the Standard. And given that no one coughed up such a term, given that everyone engaged in a certain amount of speculation and "What about ...?", I conclude that there is no single term in widespread use for the concept behind the trio of related facts. (Other than "equivalence", which is ruled out.)

A number of answerers and commentators said this (that there is no one answer) in various ways. I'm going to go ahead and accept Lundin's answer on that basis, and because others seem to have liked it the best.

Me, going forward I might try using "The correspondence between arrays and pointers in C" and see if it catches on. Arrays and pointers are as different as men and women, and they're actually pretty far apart, but they do exchange letters frequently. :-)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
2

This is a subtle question. Upon browsing an English thesaurus and dictionary, I came to find that the term similitude might be appropriate for your context.

By Oxford's Online Dictionary definition, the word Similar is defined as:

having a resemblance in appearance, character, or quantity, without being identical.

and the word Similitude as:

the quality or state of being similar to something.

Since arrays and pointers are not identical, but are sometimes treated similarly, we might say:

Yes, due to Array/Pointer similitude, array subscripting can be thought of as syntactic sugar for pointer arithmetic"

machine_1
  • 4,266
  • 2
  • 21
  • 42
  • 2
    Oh, cute! It'll never catch on, but very cute! (As rickster observed, "'array decay' sounds more like something that produces a lepton and a quark or some such". And, similarly, "similitude" sounds like, oh, something by J.R.R. Tolkien. But still, a valiant attempt.) – Steve Summit Feb 20 '18 at 14:07
1

This may seem like an abstract or philosophical question, so to frame it more concretely, what I'm looking for is is a simple noun or noun phrase I could use the sentence "Yes, due to _____, array subscription can be thought of as syntactic sugar for pointer arithmetic", in answer to, say, this question.

The Phrase you are looking for is "Yes, due to array subscribing being pointer arithmetic under the hood, array subscribing can be thought of as syntactic sugar for pointer arithmetic."

Which is of course, silly, because the reason for saying that array subscribing is syntactic sugar for pointer arithmetic is because that is exactly what it is, it does not require further explanation unless the person you are saying this to either does not know what 'array subscribing', 'pointer arithmetics' or 'syntactic sugar' mean. This is not to say the compiler does not know the difference of the two (it does because it is the one who is responsible for all the syntactic sugar you're getting as a result of that).

This same question could be raised about everything that any language does for us which we could do ourselves by using a higher number of lower level instructions and as such being able to refer to it using multiple terms that only change the amount of syntactic sugar used. The whole point is not to pretend like they are different (they always are in way, but that's not the point), but to make programming easier (just think about writing code without having the [] operator as syntactic sugar for pointer arithmetics, and you quickly realize the reason for its existence - it's not because it's different, it's because it's easier to write, read and manage).

(But please note that I am not looking for answers to that question, or for answers to the question "What's wrong with the word 'equivalence'?". Yes, I know, it can mislead learners into imagining that arrays and pointers are somehow the same. I did have that in mind when I wrote this FAQ list entry.)

Your question seems to be "What's a modern term for array pointer equivalence in the sense that array subscription is just syntactic sugar for pointer arithmetics?"

The answer is:

  1. "Array subscription" when you are using the [] operator to index an array.
  2. "Pointer arithmetics" when you are manually moving a pointer around (as opposed to using the [] operator). You might also feel like using this term for whatever math you are doing to the value you feed to the [] operator, but you are not really doing pointer arithmetics there, but rather "calculating an index", which is the term for the syntactic sugar of having the size of the objects in memory taken into account automatically for you (which again, is not different, just easier to write, read and manage, thus: syntactic sugar).
Farzad Karimi
  • 770
  • 1
  • 12
  • 31
pie
  • 73
  • 1
  • 4
  • Thanks for your thoughtful reply. Your points are well taken. I still think there's one unifying concept here that deserves one name, but perhaps I'm just being stubborn. – Steve Summit Feb 20 '18 at 14:06
  • Well, I feel that the 'equivalence' that they share is the same as one where one thing is a feature implemented using lower level instructions, and one where the same thing is implemented using a higher level construct, which does all of the lower level instructions in one go. As such, I am not sure how they could be called the same in such a way that it would not be confusing. You could always just call it "Data Indexing", which is what both of them are in the end. – pie Feb 20 '18 at 14:18
  • Well, when I say I want one term, I do not insist that it be the word "equivalence", or any term that implies it! – Steve Summit Feb 20 '18 at 14:45
0

Standard uses the term converted to. Array and pointer equivalence still holds better over array decay to pointers. Standard mention this term no where but it's just a mutual understanding between programmers that when it comes in the context of arrays and pointers it is thought as array and pointer equivalence. And what pointer and array equivalence means is: pointer arithmetic and array indexing [that] are equivalent in C, pointers and arrays are different..

haccks
  • 104,019
  • 25
  • 176
  • 264
-1

I agree that terms like "pointer/array equivalence" or "array decay" (into a pointer) are inaccurate and can be very misleading.

I'd propose the following:

Access into an array using the [] operator with an index has an equivalent pointer arithmetic expression. However, there is no equivalence between a pointer and an array: I can happily change a pointer's value (content), maybe to save a separate iteration counter, but I cannot do that with the "decayed" array; it is immutable, and in some respects, exhibits similar behaviour to C++ references.

Both verbs "to decay" and "to convert" in English invariably convey that the original is changed in the process. Using an array's name or using the unary '&' operator don't change their operand.

Therefore, an expression like "yields a pointer" or "creates a pointer" would be more accurate That is reflected in the fact that in both cases the resulting pointer is a temporary thing, (usually) sitting in a GP-register of the CPU, and cannot be assigned to.

At least that is my understanding, looking at disassemblies seems to confirm that.

E_net4
  • 27,810
  • 13
  • 101
  • 139
GermanNerd
  • 643
  • 5
  • 12
-2

If you are referring to a type conversion, why not use the term 'casting'? It already is commonly understood to imply that the compiler is being coerced into treating two related but not-the-same types as if they were a desired type. Yes, there is an equivalence here but 'casting' is used as a way to indicate that the types aren't literally the same but that the compiler should treat a type as a different type and that the procedure is acceptable to the compiler, like up-casting for byte->long

2nd choice: "Synonym"

Kelly S. French
  • 12,198
  • 10
  • 63
  • 93
  • Related but not the same? But they are the same, just different ways of expressing the same thing. – jamesqf Feb 19 '18 at 21:33
  • The reason I said not the same is because the parser recognizes each separately even if the semantics are equivalent. That is the problem, syntactically it is a separate type but semantically it might as well be an alias for the same underlying type. In English, we would refer to this arrangement as 'synonyms', maybe that is the term we should use? – Kelly S. French Feb 19 '18 at 22:07
  • I'll go with synonym. But I disagree that it's a problem: to me it's a very useful feature :-) Of course I'm looking from the programmer's perspective, not that of the compiler writer. And of course at the machine level, they're both just ways of looking at memory. – jamesqf Feb 20 '18 at 00:12
  • 3
    Well, no. A cast is an explicit construct used to request a conversion, and to cast is to use such a construct to explicitly request a conversion. But here, we're talking about entirely *implicit* conversions. – Steve Summit Feb 20 '18 at 14:06
  • I'll agree with you about casting but is synonym a better choice? – Kelly S. French Feb 20 '18 at 17:02
  • @KellyS.French Sorry, I'm not clear if you're suggesting "Arrays are a synonym for pointers" (or "Pointers are a synonym for arrays"), or if you're suggesting finding a synonym for the word "equivalence" to go in sentences like "Due to the ___ between arrays and pointers, ...". – Steve Summit Feb 20 '18 at 17:22
  • The first one. Using that phrasing would be difficult so let me create a new answer where I will modify the "Due to the ___" example to better fit the syntax of the word synonym, then I'll leave it for discussion. Maybe I can use that wording as is with the phrase "synonymous nature" . – Kelly S. French Feb 20 '18 at 17:26