Table of Contents

C/SO Tips

Good practice

Verificare cod eroare

Structura unui fișier header

Limbaj

Omiterea parantezelor în cazul folosiri macrodefinițiilor

Nume de variabile/funcții/macrouri care încep cu underscore

Greșit (neadecvat)

test.h
#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

test.h
#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

Includere fișiere C

NU includeți fișiere C în alte fișiere C sau headere. Directiva #include se folosește doar pentru headere.

Greșit (neadecvat)

test.c
int test_fun1(int a, int b)
{
     ...
}
 
int test_fun2(char *c, size_t d)
{
     ...
}
main.c
#include "test.c"
 
int main(void)
{
    ...
    test_fun1(t, u);
    ...
    test_fun2(v, w);
    ...
 
}

Corect

test.c
/* definiții de funcții */
 
int test_fun1(int a, int b)
{
     ...
}
 
int test_fun2(char *c, size_t d)
{
     ...
}
test.h
#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
main.c
#include "test.h"
 
int main(void)
{
    ...
    test_fun1(t, u);
    ...
    test_fun2(v, w);
    ...
}

Alocare dinamică a unui caracter sau întreg

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

Testare condiţie în if sau while

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.

Typecast la / de la void *

Î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;

Utilizare API

Utilizare open

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, ...);

Sfaturi

~~DISCUSSION:off~~