Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

For example consider:

int index = 3;
int array[4] = {0, 1, 2, 3};

then both index[array] and array[index] are valid expressions, much like *(index + array) and *(array + index).

In C arrays why is this true? array[5] == 5[array] explains how it works. My question is: Why did the language designers choose to allow this? Why not just enforce that index[array] is invalid, for clarity's sake?

share|improve this question
    
Note that prohibiting index[array] would likely introduce another page or two to the spec. The current syntax can be described in a line. –  Pubby May 3 '12 at 15:16
add comment

6 Answers

up vote 10 down vote accepted

First of all, it would help to read dmr's Development of the C Language to get some insights into some of C's quirks, particularly when it comes to array semantics (basically, blame BCPL and B for most of it).

As for the question "[w]hy not just enforce that index[array] is invalid, for clarity's sake," what would such a check buy you in exchange for the cost of performing it? The form almost never appears outside of the IOCCC, so it's not like it's a major problem in production code (compared to the use of, say, gets, or unchecked array accesses (which disallowing i[a] won't help with), or <fill in the blank>). It's not a bug; it doesn't introduce any undefined behavior; it doesn't introduce any security holes not already present with a[i]; the only complaints against it are stylistic in nature.

It's like asking why both T *p and T* p are valid; there is no "why" beyond it being an accident of the language syntax. There's nothing deliberate behind allowing both, it's just a function of how the grammar works. Same with a[i] and i[a]. Professional programmers are (usually) grown-ups, and don't deliberately introduce confusion where it isn't warranted, so most will naturally use a[i].

You're basically trying to guard against a problem that doesn't really exist.

share|improve this answer
add comment

The choice to use array[index] was probably made to follow mathematical convention and the precedent set for arrays by other languages like ALGOL, FORTRAN, and BASIC (the latter two use parentheses instead of brackets). That decision does make the operator an odd duck because it's binary operator but requires that you throw in an additional token after the right-hand expression.

The operator could just as easily have been a single character (@ isn't spoken for in C, so let's call that the "pointer addition operator"). Because, as David Thornley's answer in the aforementioned SO question points out, pointer addition is commutative, a @ 5 and 5 @ a make equal sense. (C forerunner BCPL used ! for this.)

In some ways it's natural to look at the array operator as behaving like a function, which makes sense in the context of languages that do f(x) to call a function and a(i) to access an array. Since operators in C don't work that way, you have to think of it as a commutative, binary operator with baggage.

share|improve this answer
    
I like the explanation, a slightly more formal one might include that arrays are merely a syntactical sugar of pointers which further reinforces your commutative argument. –  sdg May 2 '12 at 20:26
add comment

According to James Curran the reason for this was that when C was developed, computers were slower + had less memory, so such checks and optimizations were not worth the cost.

http://stackoverflow.com/a/381554/277800

share|improve this answer
    
It would be a compile-time check (is the left operand of a pointer type?), so it wouldn't have mattered much. It wouldn't have ruined the one-pass guarantee either. Of course, a half-assed 70's compiler might even ignore that, but the 70s were very early in C's evolution -- plenty of time to deprecate it or to teach compilers to shun it. –  delnan May 2 '12 at 17:49
4  
@delnan: Compile time was still a big thing back in the beginning of C so I would say it did matter (though personally I would not go as far as to say that was the reason). –  Loki Astari May 2 '12 at 19:34
add comment

We may never know for certain why the feature was allowed in the first place, but it stands to reason that it remains in the language today for backward compatibility with older versions of the language. There's no obvious and compelling reason to remove it, so it doesn't make sense to gratuitously break existing code.

share|improve this answer
add comment

It's sort of like asking why people would design cars that can hit pedestrians. They don't. They design cars to do what their drivers tell them to do. C was designed with the crazy, arcane notion that programmers are in charge of their own programs, and if they write something stupid in a programming language, it's their own responsibility. Design decisions erred on the side of removing programmer restrictions.

share|improve this answer
1  
Your approach is an argument for why it doesn't need to be changed, but it doesn't answer the question of how it got that way. index[array] isn't an unintended, emergent behavior. It was deliberately put into the language, so it's reasonable to ask why. –  octern May 3 '12 at 0:41
    
@octern - see my answer above. It is an emergent behavior that falls out of the array subscripting semantics (i.e., E1[E2] == *((E1)+(E2))); the only constraint is that one of E1 or E2 be a pointer expression, and the other be an integral expression. There's no constraint that E1 always be the pointer expression and E2 always be the integer expression. Such a constraint could be added, but since almost nobody uses the second form outside of the IOCCC, there's little to no benefit for the cost of performing the check. –  John Bode May 3 '12 at 14:53
add comment

Because, like several other features of C, it just wasn't thought through. I doubt anyone was really thinking about the mathematical logic behind array fetching in memory. As it turns out, though, both operations result in the same math (basically).

And Mr. Curran might say that, but I'd guess it didn't have a lot to do with computation cost. I could be wrong though.

share|improve this answer
1  
-1 for random editorializing on the motivations of the C designers –  sdg May 2 '12 at 20:24
    
I'll randomly editorialize on whatever I feel like, thank you. Especially when I'm correct. –  Phillip Schmidt May 2 '12 at 21:01
3  
You're correct: you could be wrong. –  Blrfl May 3 '12 at 0:28
    
Yeah, that comment was pretty constructive, right? –  Phillip Schmidt May 4 '12 at 14:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.