Is pointer arithmetic associative?

F

Francois Grieu

Are these programs correct ?

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a-1+j ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+(j-1) ));
return 0; }

rot-13 spoiler: bayl gur svefg bar vf pbeerpg.


One compiler I use generates correct and tight code for the
second form; but it fails for *(-1+a+j) [not due to an
architectural restriction, but due to a plain compiler bug].

Isn't it a shame C programming is so complex ? Given that on
most platforms, pointer arithmetic is associative, and so many
programs out there assume it blindly, is not it time for a
future C standard to waive these restrictions on pointer
associativity in at least a branch of the standard, say with
a predefined constant __ASSOCIATIVE_POINTERS__ ?


Francois Grieu
 
R

Richard Bos

Francois Grieu said:
Are these programs correct ?

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a-1+j ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+(j-1) ));
return 0; }

rot-13 spoiler: bayl gur svefg bar vf pbeerpg.

What's wrong with the third? The error in the second is clear; but the
third generates a+(1-1) and a+(2-1), that is, a+0 and a+1, neither of
which is a problem.

Richard
 
F

Francois Grieu

Francois Grieu said:
Are these programs correct ?

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a-1+j ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+(j-1) ));
return 0; }

rot-13 spoiler: bayl gur svefg bar vf pbeerpg.

What's wrong with the third?

Nothing. The spoiler was wrong..
The error in the second is clear;

Yes. The first is wrong too, because a+2 is undefined.

Francois Grieu
 
R

Richard Bos

Francois Grieu said:
Francois Grieu said:
Are these programs correct ?

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a-1+j ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+(j-1) ));
return 0; }

rot-13 spoiler: bayl gur svefg bar vf pbeerpg.

What's wrong with the third?

Nothing. The spoiler was wrong..
The error in the second is clear;

Yes. The first is wrong too, because a+2 is undefined.

No. The first is correct. You are allowed to _calculate_ the address one
past the end of an array. What you can't do is a. dereference said
one-past array or b. calculate any addresses beyond that.

This can be useful for the termination condition of loops over arrays.

Richard
 
P

pete

Richard said:
Francois Grieu said:
Are these programs correct ?

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }

#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a-1+j ));
return 0; }


#include <stdio.h>
unsigned char a[2] = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+(j-1) ));
return 0; }

rot-13 spoiler: bayl gur svefg bar vf pbeerpg.

What's wrong with the third?

Nothing. The spoiler was wrong..
The error in the second is clear;

Yes. The first is wrong too, because a+2 is undefined.

No. The first is correct.
You are allowed to _calculate_ the address one
past the end of an array. What you can't do is a. dereference said
one-past array or b. calculate any addresses beyond that.

This can be useful for the termination condition of loops over arrays.

The third one would have been wrong if the initial value
of j was zero. On systems where unsigned char promotes to unsigned,
(j-1) would have been UINT_MAX.
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top