0

I am trying to understand a line of C-code which includes using a pointer to struct value (which is a pointer to something as well).

Example C-code:

// Given
typedef struct {
    uint8 *output
    uint32 bottom
} myType;
myType *e; 

// Then at some point:
*e->output++ = (uint8) (e->bottom >> 24);

Source: https://www.rfc-editor.org/rfc/rfc6386#page-22

My question is:

  • What exactly does that line of C-code do?
Community
  • 1
  • 1
Etienne Bruines
  • 2,848
  • 3
  • 17
  • 25
  • @JimB the alternative meaning didn't make much sense either - can you perhaps elaborate on what it does do? (that way I can fix the title) – Etienne Bruines Dec 03 '14 at 21:28
  • @Deduplicator thank you for pointing that out, I was usure whether or not it was too broad. Updated the question. – Etienne Bruines Dec 03 '14 at 21:34
  • @Deduplicator just to be sure, this means that writing `*e.output = (uint8) (e -> bottom >> 24) + 1` does just the same? – Etienne Bruines Dec 03 '14 at 21:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/66162/discussion-between-etienne-bruines-and-deduplicator). – Etienne Bruines Dec 03 '14 at 21:41
  • all three operators, '*' '->' and '++' have the same precedence is C and have an associativity of left to right, so the line in question can be read from left to right, applying each operator in turn. I.E. deref p, update address by offset to the output field, set the value being assigned. and finally increment. However, it is much better to NOT make use of 'side effects' (in this case, the '++' is a side effect) in expressions – user3629249 Dec 04 '14 at 02:40

3 Answers3

3

"What exactly does that line of C-code do?"

Waste a lot of time having to carefully read it instead just knowing at a glance. If I was doing code review of that, I'd throw it back to the author and say break it up into two lines.

The two things it does is save something at e->output, then advance e->output to the next byte. I think if you need to describe code with two pieces though, it should be on two lines with two separate statements.

Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • Unless there is a dramatic and dire need for optimization, the line of code does something that could be much more clearly expressed. Code is written once, read many times -- pity the reader and make it easy to read. – Art Swri Dec 04 '14 at 02:01
1

As pointed out by Deduplicator in the comments above, looking at an operator precedence table might help.

  • *e->output++ = ... means "assign value ... to the location e->output is pointing to, and let e->output point to a new location 8 bits further afterwards (because output is of type uint8).
  • (uint8) (e->bottom >> 24) is then evaluated to get a value for ...
Etienne Bruines
  • 2,848
  • 3
  • 17
  • 25
1

The line

*e->output++ = (uint8) (e->bottom >> 24);

does the following:

  1. Find the field bottom of the structure pointed to by the pointer e.
  2. Fetch the 32-bit value from that field.
  3. Shift that value right 24 bits.
  4. Re-interpret that value as a uint8_t, which now contains the high order byte.
  5. Find the field output of the structure. It's a pointer to uint8_t.
  6. Store the uint8_t we computed earlier into the address pointed to by output.
  7. And finally, add 1 to output, causing it to point to the next uint8_t.

The order of some of those things might be rearranged a bit as long as the result behaves as if they had been done in that order. Operator precedence is a completely separate question from order in which operations are performed, and not really relevant here.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55