array indexing anecdote

H

Helmut Tessarek

Came across this old exampe how C (or better said the compiler) doesn't really
understand array indexing...

#include <stdio.h>
#include <stdlib.h>
#define ARSZ 20
main(){
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++;
printf("ar[%d] now = %d\n", i, ar);
}

printf("15[ar] = %d\n", 15[ar]);
exit(EXIT_SUCCESS);
}

After over 2 decades of programming in C, I totally forgot about it.

Just an interesting thing I had to share.

--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
K

Kaz Kylheku

Just an interesting thing I had to share.

Everyone around here kind of knows about the commutativity of a and i[a].

:)

This is because the E1[E2] syntax is essentially syntactic sugar which
corresponds to *(E1 + E2), and so inherits the commutativity from +.
At least this is conceptually so, even if not implemented that way.
Functionally, the two have to be identical.

(Where, by the way, I'm assuming that E1 and E2 are parenthesized expressions
that have no precedence interactions with [ or +.)

Compilers *can* treat the two forms differently in so far as it doesn't affect
the translation of correct programs. If *(E1 + E2) invokes undefined behavior,
then E1[E2] does also, but the specific manifestation could be different. If
there is some diagnosable issue, the diagnostic could be different for E1[E2]
versus *(E1 + E2) (or present for one but not the other).

a is not interchangeable for i[a] in declarations, however. If you write
code like i[a], then that breaks "declaration follows use" because you cannot
declare the array as int 20[a]; to match the use.
 
H

Helmut Tessarek

Everyone around here kind of knows about the commutativity of a and i[a].


I assumed as much, but I noticed that also C newbies post here and I just
thought it might be interesting to them.

--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
J

Jorgen Grahn

.
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++; ....

After over 2 decades of programming in C, I totally forgot about it.


Because it's not something you encounter in the wild. People pull all
kinds of crazy stunts, but for some reason not this one.

(And that is IMHO the only interesting thing about it.)

/Jorgen
 
K

Keith Thompson

Jorgen Grahn said:
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++; ...

After over 2 decades of programming in C, I totally forgot about it.


Because it's not something you encounter in the wild. People pull all
kinds of crazy stunts, but for some reason not this one.


Yes, this one too. See, for example, David Korn's entry in the 1987
International Obfuscated C Code Contest (ioccc.org):

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

(It depends on the compiler to predefine the macro "unix" to 1.
The output is "unix", but for reasons having nothing to do with
the spelling of the macro name.)
 
J

Joe Pfeiffer

Helmut Tessarek said:
Came across this old exampe how C (or better said the compiler) doesn't really
understand array indexing...

#include <stdio.h>
#include <stdlib.h>
#define ARSZ 20
main(){
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++;
printf("ar[%d] now = %d\n", i, ar);
}

printf("15[ar] = %d\n", 15[ar]);
exit(EXIT_SUCCESS);
}

After over 2 decades of programming in C, I totally forgot about it.

Just an interesting thing I had to share.


How does this demonstrate C doesn't "understand" array indexing? Yes,
it treats it as a syntax for pointer arithmetic, but that's got nothing
to do with "understanding".
 
J

James Kuyper

Jorgen Grahn said:
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++; ...

After over 2 decades of programming in C, I totally forgot about it.


Because it's not something you encounter in the wild. People pull all
kinds of crazy stunts, but for some reason not this one.


Yes, this one too. See, for example, David Korn's entry in the 1987
International Obfuscated C Code Contest (ioccc.org):

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

(It depends on the compiler to predefine the macro "unix" to 1.
The output is "unix", but for reasons having nothing to do with
the spelling of the macro name.)


In terms of that metaphor, the IOCCC is a zoo, not "in the wild".
 
J

Joe Pfeiffer

Keith Thompson said:
Jorgen Grahn said:
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++; ...

After over 2 decades of programming in C, I totally forgot about it.


Because it's not something you encounter in the wild. People pull all
kinds of crazy stunts, but for some reason not this one.


Yes, this one too. See, for example, David Korn's entry in the 1987
International Obfuscated C Code Contest (ioccc.org):

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

(It depends on the compiler to predefine the macro "unix" to 1.
The output is "unix", but for reasons having nothing to do with
the spelling of the macro name.)


I would not regard something appearing in the obfuscated C competition
as being "in the wild" in any normal sense of the term....
 
E

Eric Sosman

Jorgen Grahn said:
int ar[ARSZ], i;
for(i = 0; i < ARSZ; i++){
ar = i;
i[ar]++; ...

After over 2 decades of programming in C, I totally forgot about it.


Because it's not something you encounter in the wild. People pull all
kinds of crazy stunts, but for some reason not this one.


Yes, this one too. See, for example, David Korn's entry in the 1987
International Obfuscated C Code Contest (ioccc.org):

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}


That's not "in the wild," that's "in a Godzilla movie."
 
S

Stefan Ram

Helmut Tessarek said:
Came across this old exampe how C (or better said the compiler) doesn't really
understand array indexing...

My C compiler translates programs with arrays just fine,
exactly as it is supposed to do this according to C.
 
H

Helmut Tessarek

My C compiler translates programs with arrays just fine,
exactly as it is supposed to do this according to C.

I didn't say the compiler didn't compile the program. It does, which is the
example.

As far as the compiler is concerned, an expression like x[n] is translated
into *(x+n) and use made of the fact that an array name is converted into a
pointer to the array's first element whenever the name occurs in an
expression. That's why, amongst other things, array elements count from zero:
if x is an array name, then in an expression, x is equivalent to &x[0], i.e. a
pointer to the first element of the array. So, since *(&x[0]) uses the pointer
to get to x[0], *(&x[0] + 5) is the same as *(x + 5) which is the same as
x[5]. A curiosity springs out of all this. If x[5] is translated into *(x +
5), and the expression x + 5 gives the same result as 5 + x (it does), then
5[x] should give the identical result to x[5]!


--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
H

Helmut Tessarek

How does this demonstrate C doesn't "understand" array indexing? Yes,
it treats it as a syntax for pointer arithmetic, but that's got nothing
to do with "understanding".

IMO, if something treats something as something else, which allows the
something else to become the something, understanding is at fault.

Thus understanding -> "understanding".

--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
H

Helmut Tessarek

My C compiler translates programs with arrays just fine,
exactly as it is supposed to do this according to C.

I didn't say the compiler didn't compile the program. It does, which is the
example.

Update: Forgot to mention that the following is not my explanation, but a
correct one.

As far as the compiler is concerned, an expression like x[n] is translated
into *(x+n) and use made of the fact that an array name is converted into a
pointer to the array's first element whenever the name occurs in an
expression. That's why, amongst other things, array elements count from zero:
if x is an array name, then in an expression, x is equivalent to &x[0], i.e. a
pointer to the first element of the array. So, since *(&x[0]) uses the pointer
to get to x[0], *(&x[0] + 5) is the same as *(x + 5) which is the same as
x[5]. A curiosity springs out of all this. If x[5] is translated into *(x +
5), and the expression x + 5 gives the same result as 5 + x (it does), then
5[x] should give the identical result to x[5]!


--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
S

Stefan Ram

Helmut Tessarek said:
As far as the compiler is concerned, an expression like x[n] is translated
into *(x+n)

Nice target language you have! Here, it was translated into

movl -4(%rbp), %eax
cltq
movl -4(%rbp,%rax,4), %eax
and use made of the fact that an array name is converted into a
pointer to the array's first element whenever the name occurs in an
expression.

So, when »a« is an array name, you do not deem

sizeof a

to be an occurence in an expression?
That's why, amongst other things, array elements count from zero:

It is consistent with this assertion. But the /reason/ is
that C was designed this way. For a possible reason why it
was designed this way, see also:

http://www.purl.org/stefan_ram/pub/zero
 
E

Eric Sosman

My C compiler translates programs with arrays just fine,
exactly as it is supposed to do this according to C.

I didn't say the compiler didn't compile the program. It does, which is the
example.

As far as the compiler is concerned, an expression like x[n] is translated
into *(x+n) and use made of the fact that an array name is converted into a
pointer to the array's first element whenever the name occurs in an
expression. That's why, amongst other things, array elements count from zero:
if x is an array name, then in an expression, x is equivalent to &x[0], i.e. a
pointer to the first element of the array. So, since *(&x[0]) uses the pointer
to get to x[0], *(&x[0] + 5) is the same as *(x + 5) which is the same as
x[5]. A curiosity springs out of all this. If x[5] is translated into *(x +
5), and the expression x + 5 gives the same result as 5 + x (it does), then
5[x] should give the identical result to x[5]!

Yes, yes, we know this. We've known it for years and years.
Thirty-six years, to be precise: You'll find it on page 94 of the
"The C Programming Language" by Brian Kernighan and Dennis Ritchie,
published in 1978.

It's even a FAQ: Question 6.11 on the comp.lang.c Frequently
Asked Questions page at <http://www.c-faq.com/>. (The reason for
a FAQ page is to forestall endless bringing up of The Same Old
Thing over and over again, but since the bringers-up don't read
the FAQ ...)

IMHO, this oddity of C is the first thing people fasten on,
finding it (for no obvious reason) endlessly amusing. It's on a
par with FORTRAN's "DO 10 I = 1 100" non-loop, and just about
as interesting.

Can we put it to rest now, please?
 
H

Helmut Tessarek

Can we put it to rest now, please?

That's why I said in my original post that I came across this again after a
long, long time and that I have forgotten about it.

It was not meant to be the reason for an endless discussion.

Also the last word in the subject "anecdote" should have made this clear.

--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
J

Joe Pfeiffer

Helmut Tessarek said:
IMO, if something treats something as something else, which allows the
something else to become the something, understanding is at fault.

Thus understanding -> "understanding".

As you can see from the responses to your post, your use of the term
appears to be decidedly idiosyncratic.
 
H

Helmut Tessarek

As you can see from the responses to your post, your use of the term
appears to be decidedly idiosyncratic.

Ok, I give up. Tell me a better word then.

Also, did you notice the quotes around the word? They can be interpreted as:
sort of <word-in-quotes> or for the lack of a better word. I forgot the quotes
in the original post, which I tried to correct with: understanding ->
"understanding".

Sorry for this misunderstanding.

--
Helmut K. C. Tessarek

/*
Thou shalt not follow the NULL pointer for chaos and madness
await thee at its end.
*/
 
G

glen herrmannsfeldt

(snip)
Yes, this one too. See, for example, David Korn's entry in the 1987
International Obfuscated C Code Contest (ioccc.org):
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
(It depends on the compiler to predefine the macro "unix" to 1.
The output is "unix", but for reasons having nothing to do with
the spelling of the macro name.)

But it does depend on ASCII code for characters.

I do remember when I first learned about the commutative subscript
operator, I tried it out on some systems, including on 2D arrays.
(That is, the associativity of it.)

As I remember (it is a long time) the VAX/VMS C compiler didn't
like them, but I don't remember what it did to them.

-- glen
 
G

glen herrmannsfeldt

(snip)
As far as the compiler is concerned, an expression like x[n] is
translated into *(x+n) and use made of the fact that an array name
is converted into a pointer to the array's first element whenever
the name occurs in an expression. That's why, amongst other
things, array elements count from zero:

Hmm. If you converted x[n] into *(x+n-1) then arrays would count
from 1, like some other languages. Those who like arrays from zere
could always write *(x+n) instead...

Is C the first language that only allows for array indexing
starting at zero? (PL/I allows one to specify the lower bound,
and that was earlier than C. Not counting assembler programs where
the user computes the indexing.)
if x is an array name, then in an expression, x is equivalent
to &x[0], i.e. a pointer to the first element of the array.
So, since *(&x[0]) uses the pointer to get to x[0], *(&x[0] + 5)
is the same as *(x + 5) which is the same as x[5].

(snip)

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top