...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char *file_name;) { FILE *fptr; /* Initialize file_name */ int c = getc(fptr = fopen(file_name, "r")); if (c == EOF) { /* Handle error */ } fclose(fptr); } |
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.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
int c; #include <stdio.h> void func(const char *file_name) { int c; FILE *fptr; /* Initialize file_name */ fptr = fopen(file_name, "r"); if (fptr == NULL) { /* Handle error */ } c = getc(fptr); if (c == EOF) { /* Handle error */ } fclose(fptr); } |
Noncompliant Code Example (putc)
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> void func(const 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 */ } } fclose(fptr); } |
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 between sequence pointsfor side-effects.
Compliant Solution (putc)
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char *file_name; /* Initialize file_name */ ) { int c = 'a'; FILE *fptr = fopen(file_name, "w"); if (fptr == NULL) { /* Handle error */ } int c = 'a'; while (c <= 'z') { if (putc(c++, fptr) == EOF) { /* Handle error */ } } fclose(fptr); } |
The c++ is perfectly safe because putc() guarantees to evaluate its character argument exactly once.
...
...