Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: formatting

...

This does not apply to the character argument in putc(), which is guaranteed to be evaluated exactly once.

Noncompliant Code Example (getc())

This code calls the getc() function with an expression as the stream argument. If getc() is implemented as a macro, the file may be opened several times. (See FIO31-C. Do not open a file that is already open.)

...

This noncompliant code example also violates FIO33-C. Detect and handle input output errors resulting in undefined behavior because the value returned by fopen() is not checked for errors.

Compliant Solution (getc())

In this compliant solution, getc() is no longer called with an expression as its argument, and the value returned by fopen() is checked for errors:

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
void func(const char *file_name) {
  int c;
  FILE *fptr;

  fptr = fopen(file_name, "r");
  if (fptr == NULL) {
    /* Handle error */
  }

  c = getc(fptr);
  if (c == EOF) {
    /* Handle error */
  }

  fclose(fptr);
}

Noncompliant Code Example (putc())

In this noncompliant example, putc() is called with an expression as the stream argument. If putc() is implemented as a macro, the expression can be evaluated several times within the macro expansion of putc() with unintended results.

...

If the putc() macro evaluates its stream argument multiple times, this might still seem safe, as the ternary conditional expression ostensibly prevents multiple calls to fopen(). However, there is no guarantee that these calls would happen in distinct sequence points. Consequently, this code also violates EXP30-C. Do not depend on order of evaluation for side effects.

Compliant Solution (putc())

In the compliant solution, the stream argument to putc() no longer has side effects:

...