Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to post-modify a C pointer?

Tags:

c

pointers

gcc

In modern processors it is possible to load a register from memory and then post-modify the indexing pointer by a desired value. For example, in our embedded processor, this will be done by:

ldr r0, [r1], +12

which means - load the value pointed to by r1 into r0 and then increment r1 by 12:

r0 = [r1]
r1 = r1 + 12

In the C language, using pointer arithmetics, one can assign a value using a pointer and then advance the pointer by 1:

char i, *p, a[3]={10, 20, 30};

p = &(a[0]);
i = *p++;
// now i==10 and p==&(a[1]).

I am looking for a way to dereference a pointer while post-modifying it by an offset other than 1. Is this possible in C, so it maps nicely to the similar asm instruction?

Note that:

i = *p+=2;

increases the value in a[0] w/o modifying the pointer, and:

i = *(p+=2);

pre-modifies the pointer, so in this case i==30.

like image 794
ysap Avatar asked Jun 26 '12 10:06

ysap


People also ask

Can a pointer be modified?

Modifying the value of a pointerWe can change the pointer's value in a code, but the downside is that the changes made also cause a change in the original variable.

Can you change a pointer in C?

You can't change the address of a pointer (or of any variable). Once you declare the variable, it's address is firmly set, once and forever. You can, however, change the value of a pointer, just as easily as you can change the value of an int: x = 10 or p = &t.

Can a pointer be changed within function?

Can a pointer be changed within function? If you modify the pointer inside the called function, you only modify the copy of the pointer, but the original pointer remains unmodified and still points to the original variable.


1 Answers

  1. Yes this is possible.

  2. You shouldn't be doing weird pointer math to make it happen.

  3. Not only is it about optimization settings, your GCC back-end needs to tell GCC that it has such a feature (i.e. when GCC itself is being compiled). Based on this knowledge, GCC automatically combines the relevant sequence into a single instruction.

i.e. if your back-end is written right, even something like:

 a = *ptr;
 ptr += SOME_CONST;

should become a single post-modify instruction.

How to correctly set this up when writing a back-end? (ask your friendly neighbourhood GCC back-end developer to do it for you):

If your GCC back-end is called foo:

  1. In the GCC source tree, the back-end description and hooks will be located at gcc/config/foo/.
  2. Among the files there (which get compiled along with GCC), there is usually a header foo.h which contains a lot of #defines describing machine features.
  3. GCC expects that a back-end which supports post-increment define the macro HAVE_POST_INCREMENT to evaluate to true, and if it supports post-modify, then define the macro HAVE_POST_MODIFY_DISP to true. (post-increment => ptr++, post-modify => ptr += CONST). Maybe there are a few other things to be handled as well.

Assuming that your processor's back-end has got this right, lets move to what happens when you compile your code containing said post-modify sequence:

There is a specific GCC optimization pass that goes through instruction pairs that fall into this category and combines them. The source for that pass is here, and has a rather clear description of what GCC will do and how to get it to do it.

But this, in the end, is not in your control as a GCC user. It is in the control of the developer who wrote your GCC back-end. All you should be doing, like the most upvoted comment says, is:

 a = *ptr;
 ptr += SOME_CONST;
like image 100
ArjunShankar Avatar answered Sep 21 '22 18:09

ArjunShankar