Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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 rule FIO31-C. Do not open a file that is already open.)

Code Block
bgColor#ffcccc
langc
char *file_name;
FILE *fptr;

/* Initialize file_name */

int c = getc(fptr = fopen(file_name, "r"));
if (c == EOF) {
  /* Handle error */
}

...

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
int c;
char *file_name;
FILE *fptr;

/* Initialize file_name */

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

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

...

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.

Code Block
bgColor#ffcccc
langc
char *file_name;
FILE *fptr = NULL;

/* Initialize file_name */

int c = 'a';
while (c <= 'z') {
  if (putc(c++, fptr ? fptr :
       (fptr = fopen(file_name, "w")) == EOF) {
    /* Handle error */
  }
}

...

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

Code Block
bgColor#ccccff
langc
char *file_name;

/* Initialize file_name */

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

int c = 'a';

while (c <= 'z') {
  if (putc(c++, fptr) == EOF) {
    /* Handle error */
  }
}

...