web-dev-qa-db-fra.com

Quelle est la différence entre le vide statique en ligne et le vide?

Je travaille dans le langage C et modifie du code écrit auparavant par quelqu'un d'autre. Je me bats avec quelques problèmes et j'essaie de comprendre le plus possible ce qui se passe. Donc, comme ma question l’a dit, quelle est la différence entre static inline void et void lors de la création d’une fonction? Je m'excuse par avance pour le long post, mais je voulais que vous sachiez que j'ai fait des recherches, mais je ne comprends pas ce que j'ai trouvé.

J'ai trouvé une explication de static qui me confond:

Le spécificateur statique signifie que la fonction ne peut pas être référencée à partir d'autres fichiers. c'est-à-dire que le nom n'est pas exporté par l'éditeur de liens.

En lisant ceci, je suppose que référencer une fonction est différent de l'appel d'une fonction? Je suppose que parce que cette fonction est appelée depuis un autre fichier .c. Si tel est le cas, qu'est-ce que le référencement d'une fonction?

À travers le même site Web, ils expliquent les fonctions en ligne et je ne comprends pas ce que cela signifie.

Le mot clé __inline indique au compilateur de remplacer le code de la définition de fonction par chaque instance d'un appel de fonction. Cependant, la substitution se produit uniquement à la discrétion du compilateur. Par exemple, le compilateur n'inline pas une fonction si son adresse est prise ou si elle est trop grande pour être intégrée.

Hein ???

Toute aide est grandement appréciée et je m'excuse encore une fois pour ce très long message.

Ce qui suit se trouve dans fichier1.c (Utilisation de noms génériques, je ne pense pas que cela compte)

COMPLEX cNoiseSample;
CGauss( &cNoiseSample, loopbackRadio->pState );

Ce qui suit est situé dans file2.c

static inline void CGauss( COMPLEX * pcGauss, P_OS_UNIFORM_Rand_STATE pState )
{
    //code
}
15
TZPike05

static signifie qu'il ne peut pas être référencé depuis une autre unité de compilation (fichier source). "Référencé" signifie appelé, ou autrement désigné par son nom, par ex. assigné à un pointeur de fonction.

inline indique au compilateur que le code de la fonction doit être généré en ligne à l'endroit où il est appelé, plutôt que généré sous la forme d'une fonction distincte à laquelle être branchée. Ceci est normalement fait pour des raisons de performances. Pour traiter la citation de Microsoft:

le compilateur ne met pas en ligne une fonction si son adresse est prise ou si elle est trop grande pour être insérée.

Une fonction en ligne n'a pas d'adresse car elle n'existe pas en tant qu'entité séparée. Son code est simplement étroitement lié au code à partir duquel il a été appelé. Ainsi, si vous prenez l’adresse d’une fonction (par exemple, pour l’affecter à un pointeur), le compilateur doit alors la générer comme une fonction réelle et ne peut pas la mettre en ligne.

void signifie que la fonction ne renvoie pas de valeur.


Après avoir examiné votre exemple de code, je suppose qu’il existe quelque part une définition distincte de CGauss(), appelée à partir de file1.c , alors que file2.c appelle sa propre version privée. Ou bien, ou fichier1.c est #includeing fichier2.c . Ce qui serait méchant.

13
Graham Borland

static signifie seulement quelque chose quand vous avez plus d'un fichier source. Il spécifie qu'il est impossible d'accéder à la fonction ou à la variable static à partir de fonctions situées dans un autre fichier.

inline est une optimisation du compilateur qui accélère votre code dans certains cas. Chaque fois que vous appelez une fonction, elle est associée à une surcharge. Le compilateur peut donc se débarrasser de la fonction par copier-coller (presque) le code en ligne.

Voici un exemple d'inline:

int dotproduct(int x1, int y1, int x2, int y2) {
    return multiply(x1,x2)+multiply(y1,y2);
}

inline int multiply(int a, int b) {
    return a*b;
}

Le compilateur va transformer ceci en:

int dotproduct(int x1, int y1, int x2, int y2) {
    return x1*x2+y1*y2;
}

Si vous voulez être chic, vous pouvez également intégrer la fonction dotproduct;)

Notez que le mot clé inline est simplement un coup de pouce au compilateur pour intégrer certaines fonctions. Il peut ou ne peut pas réellement le faire en fonction de son propre jugement.

6
tskuzzy

Le mot clé static

Définir une fonction C statique signifie (comme l'indiquent les docs) que l'accès à cette fonction est possible uniquement à partir du fichier source dans lequel il est défini. Le terme "référence" dans ce contexte signifie soit appeler cette fonction, soit prendre par exemple un pointeur de fonction sur celle-ci. .

Inline

Normalement, lorsque vous écrivez une fonction en C, le compilateur génère le code machine pour cette fonction:

foo:
   /* some machine code */
   ret

Chaque fois que vous appelez cette fonction, le compilateur insère une instruction telle que

  call <foo>

dans le code machine de l'appelant, ce qui ne veut rien dire d'autre que "saute à foo, exécute ce que tu trouves là et quand tu rencontres une instruction ret, retourne à cet endroit".

En revanche, pour les fonctions inline, le compilateur ne génère pas une fonction séparée foo (), mais insère le code machine de la fonction foo dans chaque site d’appel. Lors de l'exécution de ce code, cela a le même effet.

Alors pourquoi faisons-nous cela? Le code en ligne présente l'avantage de vous éviter deux sauts (l'appel et le retrait respectif), ce qui accélère l'exécution de votre code. Inconvénient, votre code grossit parce que vous insérez le code machine sur chaque site d’appel au lieu d’avoir une seule copie d’une fonction appelable. C'est pourquoi vous n'utilisez habituellement que de petites fonctions en ligne.

En outre, vous ne pouvez pas amener les pointeurs de fonction aux fonctions en ligne, et le débogage devient plus difficile, car vous ne pouvez pas définir facilement un point d'arrêt sur une fonction en ligne.

Par conséquent, l'inline est laissée au compilateur en tant qu'option d'optimisation. En utilisant un mot clé tel que inline, la directive inline de C++ ou l'attribut __ de l'attribut GCC ((inline)) de GCC, vous indiquez simplement au compilateur que l'inline peut être vaut la peine d'essayer ici.

2
BjoernD

static signifie simplement que la fonction est à toutes fins utiles "invisible" en dehors du fichier source dans lequel elle est définie.

inline demande au compilateur de substituer essentiellement le code d'appel de fonction directement dans la source à chaque endroit où la fonction est appelée au moment de la compilation (comme si l'appel de fonction était remplacé par le code de la fonction). il suggère simplement à votre compilateur.

C'est plus technique que cela et vous obtiendrez probablement une bien meilleure réponse, mais en termes simples, c'est ce que les termes veulent dire.

0
mathematician1975

Je voudrais ajouter à tout ce qui précède, avant de lire ce qui précède, il est important de comprendre comment fonctionne la programmation c. Si vous écrivez simplement un code ouvert, comme

Setup(){
    int MainVar
}

MyRoutine(){
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

Chacun peut alors accéder à MyRoutine.myVar1 directement à partir d'un second programme. Ils pourraient changer la valeur de myVar2, (1. si elle n'est pas protégée, 2. s'ils savent qu'elle est là, 3. s'ils savent ce qu'elle fait) avant qu'elle ne soit utilisée dans MyRoutine // Do stuff, modifiant ainsi le programmeur original destiné.

Imaginez que vous écriviez un programme bancaire et que vous laissiez le code vulnérable afin que quelqu'un puisse modifier la valeur du DÉPÔT sans modifier le paramètre WITHDRAWL de l'autre banque de votre routine. Quelqu'un d'autre pourrait venir écrire un programme séparé pour modifier cette valeur de 2 ou 10 et créer de l'argent là où il n'en existait aucune. Mais si vous faites précéder le code, la routine, la méthode ou les variables avec STATIC, ces éléments ne sont pas accessibles, visualisables et surtout modifiés par un autre programme.

Vous pouvez utiliser statique à tout moment, en rendant des routines entières fermées, ou des variables individuelles uniquement fermées. Permettez ainsi à d’autres personnes d’apporter des modifications à certains aspects de votre code, tout en préservant les aspects à protéger.

Mettre Static sur MyRoutine empêcherait quelqu'un d'exécuter MyRoutine à partir d'un autre programme. Étant donné que MyVars sont déclarés dans MyRoutine, ils ne seraient pas accessibles depuis un autre programme. Mais s'il existait une variable appelée MainVar déclarée ailleurs dans le programme, elle serait accessible.

Setup(){
    int MainVar  // This can be accessed from outside this code
}

static MyRoutine(){  // Because of static these vars are not
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

Et ici, seules les variables avec static sont protégées. myVar3 pourrait être lu ailleurs en informant une autre routine que l'échange est terminé.

Setup(){
    int MainVar    // This can be accessed from outside this code
}

MyRoutine(){
   static int myVar1;  // This can NOT be accessed from outside this code
   static int myVar2;  // This can NOT be accessed from outside this code
   bool myVar3;        // This can be accessed from outside this code
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}
0
KeyWizard