Greșit (neadecvat)
#ifndef _TEST_H #define _TEST_H 1 ... #ifndef __TEST_H #define __TEST_H 1 ... #ifndef _TEST_H_ #define _TEST_H_ 1 ... #ifndef __TEST_H__ #define __TEST_H__ 1 ...
Corect
#ifndef TEST_H #define TEST_H 1 /* unele șanse de conflict */ ... #ifndef TEST_H_ #define TEST_H_ 1 ... #define TEST_H__ 1 #define TEST_H__ 1
NU includeți fișiere C în alte fișiere C sau headere. Directiva #include
se folosește doar pentru headere.
Greșit (neadecvat)
int test_fun1(int a, int b) { ... } int test_fun2(char *c, size_t d) { ... }
#include "test.c" int main(void) { ... test_fun1(t, u); ... test_fun2(v, w); ... }
Corect
/* definiții de funcții */ int test_fun1(int a, int b) { ... } int test_fun2(char *c, size_t d) { ... }
#ifndef TEST_H_ #define TEST_H_ 1 /* declarații (antete) de funcții */ int test_fun1(int a, int b); int test_fun2(char *c, size_t d); #endif
#include "test.h" int main(void) { ... test_fun1(t, u); ... test_fun2(v, w); ... }
Greşit(neadecvat)
#define BUFFER_SIZE 128 char *x = malloc(1); char *buffer = malloc(BUFFER_SIZE); if (read(STDIN_FILENO, x, 1) < 0) { ... if (read(STDIN_FILENO, buffer, BUFFER_SIZE) < 0) { ...
Corect
#define BUFFER_SIZE 128 char x; char buffer[BUFFER_SIZE]; if (read(STDIN_FILENO, &x, 1) < 0) { ... if (read(STDIN_FILENO, buffer, BUFFER_SIZE) < 0) { ...
Explicație
x
, se poate utiliza operatorul de referenţiere &
care află adresa unei variabile.buffer
, întrucât se cunoaște din momentul compilării valoarea acesteia, se poate folosi alocarea statică. Alocarea statică este realizată de compilator. Alocarea dinamică presupune gestiunea acesteia de utilizator (gestiunea pointerului, eliberarea zonei, evitarea leak-urilor) însemnând un risc mai ridicat.Greşit
if (fd = open("file", O_RDONLY) < 0) { perror("open"); } else { /* use fd */ }
Corect
if ((fd = open("file", O_RDONLY)) < 0) { perror("open"); } else { /* use fd */ }
Explicaţia
Operatorul <
are prioritate mai mare decât operatorul de atribuire =
. Aceaşi greşeală este şi dacă testăm condiţia fără paranteze într-un while
.
Și mai corect
fd = open("file", O_RDONLY); if (fd < 0) perror("open"); else { /* Use fd. */ }
Formularea cu apelul funcției în condiția if
este error-prone și face codul mai greu de citit.
În C (nu și în C++), nu sunt necesare typecast-uri într-o atribuire atunci când unul dintre termeni este de tip void *
.
Greșit
int *a = (int *) malloc(N * sizeof *a); void *p = (void *) a;
Corect
int *a = malloc(N * sizeof *a); void *p = a;
Greşit
if ((fd = open("file_name", O_WRONLY | O_CREAT)) < 0) {
Corect
if ((fd = open("file_name", O_WRONLY | O_CREAT, 0644)) < 0) {
Explicaţia
În cazul în care folosim flagul O_CREAT, trebuie să specificăm drepturile cu care se creează fişierul.
Compilează pentru că funcţia open
este declarată
int open (char *file, int oflag, ...);
~~DISCUSSION:off~~