Statico e non statico? (con funzioni non OOP)

5

Sebbene questa domanda sia già emersa, la mia è diversa perché non dovrebbe coprire nulla OOP ma solo plain (ANSI) C .

Soprattutto nei software open source, di solito trovo una miriade di funzioni (per favore non chiamarle metodi poiché siamo non in OOP) con la parola chiave static che precede il tipo di dati .

Ma che effetto ha effettivamente con C normale? Nei miei progetti, non ho mai avuto un'occasione in cui fosse effettivamente necessaria la parola chiave static . (Anche se un cosiddetto programmatore esperto mi avrebbe probabilmente dato il consiglio, "Questa funzione dovrebbe essere dichiarata statica" e probabilmente avrei risposto nel mio modo sarcastico: "Uh-huh. Beh, funziona così com'è, dopo tutti". :)).

Dalla lettura del codice OSS, ho pensato che avrebbe potuto generare meno overhead durante la compilazione del progetto. Tuttavia, le prestazioni della CPU sono state così elevate che mi sono chiesto molte volte perché c'è un interesse continuo a dichiarare le funzioni statiche anche se potrebbe essere necessario uno strumento di benchmark per misurare le differenze nella velocità di esecuzione.

    
posta syntaxerror 16.07.2014 - 19:37
fonte

4 risposte

18

"Statico" è sovraccarico per indicare due cose in C:

  • A livello di file, limita l'ambito al file corrente. (Penso che questo sia quello che stai vedendo.)

  • All'interno di una funzione, trasforma le variabili in modo tale che i loro valori siano conservati tra le chiamate.

"Statico" ha poco a che fare con le prestazioni in C. Nel contesto in cui l'hai visto, si riferisce all'ambito di accesso. In questo uso, "statico" in realtà finisce per essere simile nella funzione di accedere ai modificatori in un linguaggio OOP che con la parola chiave "statica" come si applica ai metodi C ++.

    
risposta data 16.07.2014 - 20:07
fonte
6

Statico, quando applicato a una funzione, significa che la funzione ha un ambito locale o un ambito di file, che impedirà a qualcuno di dichiarare un prototipo a tale funzione in un file di intestazione e di utilizzarlo altrove rispetto a dove è stato dichiarato.

Questo non ha implicazioni sul rendimento, ma è comunque una buona pratica. Perché? Perché riduce l'ambito. Quando il programmatore individua una funzione static , è un'indicazione che la funzione non verrà utilizzata in qualche altro posto sconosciuto, quindi, se si interrompe tale funzione, almeno si sa che il danno deve essere limitato al file sorgente in questione .

Nota che static non è una garanzia che la funzione non possa essere chiamata al di fuori del file in cui è stata dichiarata, dal momento che qualcuno può ancora afferrare un puntatore alla funzione ed esternalizzare quel puntatore.

    
risposta data 16.07.2014 - 21:20
fonte
4

Ogni funzione o variabile in un programma C che non è dichiarato static è necessaria per avere un nome univoco. Se due o più programmatori che scrivono parti diverse di un sistema scrivono ciascuna una funzione chiamata "fred", ed entrambe le funzioni sono dichiarate statiche, allora il fatto che ci siano due funzioni "fred" sarà completamente irrilevante (e quindi non pone problemi) . Se tutte le funzioni tranne una sono statiche, è probabile che le cose stiano ancora bene, ma potrebbero esserci ancora problemi se un programmatore aggiunge una dichiarazione extern da qualche parte intendendo di fare riferimento a una funzione, ma la funzione desiderata è statica e la dichiarazione in realtà si lega a una funzione non statica dichiarata altrove. Se ci sono due o più funzioni "fred" che non sono statiche, i problemi sono quasi garantiti. Nella maggior parte dei casi, il linker rifiuterà il programma; in alcuni casi (ad esempio se uno dei metodi è contrassegnato con un attributo "debole") il linker non squawk, ma il codice che si supponeva fosse destinato a richiamare un metodo potrebbe invocare l'altro. Se entrambi i metodi si comportano in modo identico, ciò potrebbe non rappresentare un problema, ma se i metodi sono diversi, è probabile che tale sostituzione sia disastrosa.

Se i programmatori hanno l'abitudine di rendere i loro metodi non statici, è probabile che si verifichino collisioni di nomi. Rendere le cose statiche di default evita questo problema.

    
risposta data 17.07.2014 - 00:27
fonte
2

Se applicato a una definizione di funzione, la parola chiave static impedisce l'esportazione del nome della funzione nel linker; il codice in altre unità di traduzione (file) non può chiamare tale funzione per nome.

Per abusare della terminologia, stai rendendo la definizione della funzione "privata" a quel file sorgente.

Ad esempio, supponiamo di avere un file come

static int a_helper_function( /* some arguments here */ )
{
  ...
}

int public_function( /* some arguments here */ )
{
  ...
  if ( a_helper_function( /* arguments */ ))
    /* do something interesting */
  ...
}

Quando costruisco il mio progetto, solo le funzioni definite all'interno dello stesso file sorgente possono chiamare direttamente a_helper_function ; non è visibile per codificare in altre unità di traduzione.

Questo non è un problema di prestazioni tanto quanto un problema di manutenzione e progettazione. Riduce le collisioni nello spazio dei nomi (potresti avere più versioni di a_helper_function con diverse firme in file diversi) e ti consente di incapsulare alcune operazioni all'interno di ciascun file.

Ora, tutto ciò non impedisce che il nome della funzione venga esportato nel linker; altre unità di traduzione possono ancora chiamare questa funzione, solo non per nome. Potrei avere un'altra funzione nello stesso file che restituisce un puntatore a a_helper_function :

int (*get_helper(/* args for get_helper */))(/* args for a_helper_function */)
{
  return a_helper_function;
}

La funzione get_helper restituisce un puntatore a a_helper_function , quindi una funzione in un'altra unità di traduzione potrebbe utilizzare quel puntatore a funzione per chiamare a_helper_function .

    
risposta data 18.07.2014 - 22:35
fonte

Leggi altre domande sui tag