3

I am reading K&R The C Programming Language, and in Chapter 2.10 it states:

"If expr1 and expr2 are expressions, then

expr1 op= expr2

is equivalent to

expr1 = (expr1) op (expr2)

except that expr1 is computed only once."

op= is referring to the binary operators you can use with assignment like +=, -= etc. (and in the 2nd line op just means a binary operator like +)

My first minor confusion is that expr1 must be only a variable (an "lvalue")? Or else how can we assign a result to a larger expression? But my main question is what is meant by "expr1 is computed only once"? Would something have been computed twice if we wrote:

expr1 = (expr1) op (expr2)

instead of

expr1 op= expr2 
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Azi muth
  • 59
  • 6
  • 1
    There are probably simpler examples, but consider the case where `f()` returns an `int *`. Then in `*f() += 1`, `f` is only called once. – William Pursell Oct 22 '22 at 00:21
  • 2
    The K&R book is not representative of modern C. – Dai Oct 22 '22 at 00:23
  • Nevermind, I think I understand now. Even though expr1 must be an assignment, there could be an expression somewhere inside the argument to an array or something. And then it's only called once, because it doesn't appear twice anymore. I think i'll close the question. – Azi muth Oct 22 '22 at 00:26
  • @Dai any other textbook you would recommend? It's not bad for getting the basics in. – Azi muth Oct 22 '22 at 00:27
  • 1
    @Azimuth https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list – Dai Oct 22 '22 at 00:28
  • @Dai yeah but which one do you like? :) – Azi muth Oct 22 '22 at 00:30
  • 1
    @Azimuth At risk of being a hypocrite: I cut my teeth on the K&R C book too, but that was before _modern C_ became a thing. If I was learning C today I'd go with one of the books from that page, though leaning towards books from reputable technical publishers (e.g. Addison-Wesley or O'Reilly). – Dai Oct 22 '22 at 00:31

1 Answers1

5

This feels contrived, but consider:

#include <stdio.h>

int x = 0;

int *f(void) { printf("f is called\n"); return &x; }

int
main(int argc, char **argv)
{
    printf(" x = %d\n", x);
    *f() += 1;  /* Calls f once */
    printf(" x = %d\n", x);
    *f() = *f() + 1;  /* Calls f twice */
    printf(" x = %d\n", x);
    return 0;
}

A less contrived example would be something like:

a[i++] += 1;
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • 1
    On this line: `*f() += 1; /* Calls f once */` - while `f` is only invoked once, won't the returned `int*` be dereferenced at least twice? – Dai Oct 22 '22 at 00:27
  • @William Pursell thank you William for taking the time to answer! A function is a good example of something you might only want called once. – Azi muth Oct 22 '22 at 00:35
  • 1
    @Dai That's no different from directly modifying a variable that happens to be kept in memory. `*f()` is an lvalue, just as `x` is in `x += 1`, where the value stored in `x` is both read and written. – Thomas Jager Oct 22 '22 at 00:48