C/SO Tips

Good practice

Verificare cod eroare

  • Verificați codul de eroare întors de apelurile de sistem.
    • Exemplu:
      fd = open(FILENAME, O_RDONLY);
      if (fd < 0) {
          perror("open");
          exit(EXIT_FAILURE);   /* sau alta actiune */
      }
       
      if (ReadFile(fHandle,
              &buffer,
              bytesToRead,
              &bytesRead,
              NULL) == FALSE) {
                     fprintf(stderr, "Error reading file %d\n", GetLastError());
                     exit(EXIT_FAILURE);
      }

Structura unui fișier header

  • TODO

Limbaj

Omiterea parantezelor în cazul folosiri macrodefinițiilor

  • TODO

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

  • Numele de variabile/funcții/macrouri care încep cu underscore _ sunt rezervate de biblioteca standard C. Se recomandă să nu folosiți astfel de nume în codul vostru.
    • Mai multe detalii găsiți aici.

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

  • În cazul de faţă nu este nevoie alocarea dinamică a variabilei x, se poate utiliza operatorul de referenţiere & care află adresa unei variabile.
  • În cazul variabilei 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.

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

  • Fiți consecvenţi în indentare!
  • Folosiți denumiri relevante pentru funcții și variabile.
so/laboratoare-2013/resurse/c_tips.txt · Last modified: 2014/03/05 22:19 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0