Nou Generator de prompt AI — scrie prompturi mai bune pentru ChatGPT, Claude și Gemini →

Atribute [[…]] în C

Atributele C23 dau compilatorului informații în plus: rezultat care nu trebuie ignorat, funcție învechită, variabilă poate nefolosită.

Sintaxă
[[nodiscard]] int salveaza(void);
[[maybe_unused]] int x;
[[deprecated("mesaj")]] void vechi(void);
[[fallthrough]];
[[noreturn]] void opreste(void);

Ce face Atribute [[...]]

Un atribut se scrie între paranteze pătrate duble, înaintea declarației: [[nodiscard]] int salveaza(void);. Atributele nu schimbă ce face programul; ele îi spun compilatorului ce intenționezi, ca să te avertizeze când codul nu respectă intenția. C23 a standardizat sintaxa (luată din C++), înlocuind extensiile vechi de tipul __attribute__((...)).

Atributele standard: [[nodiscard]] (avertisment dacă rezultatul funcției este ignorat), [[maybe_unused]] (fără avertisment dacă variabila sau parametrul nu este folosit), [[deprecated]] (avertisment la fiecare folosire, cu mesaj opțional), [[fallthrough]] (trecerea intenționată la următorul case), [[noreturn]] (funcția nu se mai întoarce, de exemplu apelează exit). Mai există [[unsequenced]] și [[reproducible]], pentru optimizarea funcțiilor fără efecte.

Disponibilitatea unui atribut se verifică cu __has_c_attribute(nume). Un compilator ignoră atributele pe care nu le cunoaște (cu un avertisment).

Exemple

Exemplul 1: maybe_unused și fallthrough

Cu -Wall -Wextra -Werror, un parametru nefolosit și o trecere neanunțată la alt case ar opri compilarea. Atributele spun că ambele sunt intenționate, așa că programul se compilează fără avertismente.

#include <stdio.h>

static void raport(int zi, [[maybe_unused]] const char *autor) {
    switch (zi) {
    case 5:
        printf("Vineri: trimite raportul săptămânal\n");
        [[fallthrough]];
    case 1:
    case 2:
    case 3:
    case 4:
        printf("Zi lucrătoare (%d)\n", zi);
        break;
    default:
        printf("Weekend (%d)\n", zi);
    }
}

int main(void) {
    raport(5, "Ana");
    raport(2, "Ana");
    raport(6, "Ana");
    return 0;
}

Rezultat

Vineri: trimite raportul săptămânal
Zi lucrătoare (5)
Zi lucrătoare (2)
Weekend (6)

Exemplul 2: noreturn și verificarea cu __has_c_attribute

opreste apelează exit și nu se mai întoarce; [[noreturn]] îi spune asta compilatorului. Aici funcția nu este apelată, ca programul să se termine normal. __has_c_attribute dă o valoare nenulă (data standardului) dacă atributul este cunoscut.

#include <stdio.h>
#include <stdlib.h>

[[noreturn]] static void opreste(const char *motiv) {
    fprintf(stderr, "Eroare: %s\n", motiv);
    exit(EXIT_FAILURE);
}

int main(void) {
    int stoc = 12;
    if (stoc < 0) {
        opreste("stoc negativ");
    }
    printf("Stoc: %d\n", stoc);
#if __has_c_attribute(nodiscard)
    printf("nodiscard este disponibil\n");
#endif
    return 0;
}

Rezultat

Stoc: 12
nodiscard este disponibil

Exemplul 3: nodiscard și deprecated în acțiune

Rezultatul lui salveaza este ignorat, iar scrie_vechi este marcată învechită. Compilatorul afișează două avertismente; cu -Werror ar fi erori.

#include <stdio.h>

[[nodiscard]] int salveaza(const char *nume) {
    printf("Salvez %s\n", nume);
    return 0;
}

[[deprecated("folosește salveaza()")]] void scrie_vechi(void) {}

int main(void) {
    salveaza("Ana");
    scrie_vechi();
    return 0;
}

Mesajele compilatorului (clang -std=c23 -Wall -Wextra)

exemplu.c:11:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
   11 |     salveaza("Ana");
      |     ^~~~~~~~ ~~~~~
exemplu.c:12:5: warning: 'scrie_vechi' is deprecated: folosește salveaza() [-Wdeprecated-declarations]
   12 |     scrie_vechi();
      |     ^
exemplu.c:8:3: note: 'scrie_vechi' has been explicitly marked deprecated here
    8 | [[deprecated("folosește salveaza()")]] void scrie_vechi(void) {}
      |   ^
2 warnings generated.

Greșeli frecvente

  • Pui [[fallthrough]] fără punct și virgulă sau în alt loc decât chiar înaintea următorului case. Este o instrucțiune: [[fallthrough]];, ultima înainte de eticheta următoare.
  • Folosești [[maybe_unused]] ca să ascunzi orice avertisment. Avertismentul despre o variabilă nefolosită indică des o greșeală reală; pune atributul doar când lipsa folosirii este intenționată.
  • Scrii _Noreturn în cod nou. Funcționează încă, dar în C23 este marcat ca învechit în favoarea lui [[noreturn]].

Comenzi înrudite

  • switch: Alege una din mai multe ramuri după valoarea unui întreg, cu etichete case; fără break, execuția continuă în ramura următoare.
  • Funcții și prototipuri: Cum definești și declari funcții în C: tipul rezultatului, parametrii, prototipul și transmiterea argumentelor prin valoare.
  • exit, atexit și EXIT_SUCCESS: Oprește programul din orice funcție, cu un cod de ieșire; atexit înregistrează funcții de rulat la final.
  • #if, #ifdef, #ifndef: Compilare condiționată: preprocesorul păstrează sau elimină bucăți de cod în funcție de macro definite sau de valoarea lor.
  • Compilarea cu gcc și clang: Cum transformi codul C într-un program executabil cu gcc sau clang și ce fac opțiunile folosite cel mai des.
Comunitate & Schimb de cunoștințe

Întrebări & Exemple de Cod: Atribute [[…]]

Ai o nelămurire despre utilizarea comenzii Atribute [[…]] sau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!

💬

Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!

Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.

Comunitate Adaugă o întrebare sau distribuie un cod

Moderare & Siguranță:

Pentru a menține calitatea și securitatea informațiilor, fiecare întrebare sau fragment de cod/prompt este analizat (manual sau prin moderare asistată de AI) înainte de publicare.