Efficacité de la déclaration de variable C

Combien de temps faut-il pour déclarer une variable en C, par exemple int x ou unsigned long long var ? Je me demande si cela rendrait mon code plus rapide dans quelque chose comme ça.

 for (conditions) { int var = 0; // code } 

Est-ce que ce serait plus rapide ou est-ce plus facile de ne pas le faire?

 int var; for (conditions) { var = 0; // code } 

Merci pour l’aide.

Chaque fois que vous avez une question sur les performances, la meilleure chose à faire est de boucler la boucle (des millions d’itérations) et de la chronométrer. Mais dans ce cas, vous constaterez probablement que cela ne fait aucune différence.

Il est plus important d’exprimer correctement les intentions de votre code. Si vous avez besoin de la variable en dehors de votre boucle, effacez-la en dehors. Si vous n’avez besoin que de la variable à l’intérieur de la boucle, déclarez-la à l’intérieur.

Vous devez toujours déclarer et initialiser les variables dans le champ le plus étroit possible.

De toute façon, vous ne devriez pas vous soucier de ces types de micro-optimisations (sauf dans les cas les plus rares, les plus rares ). Si vous avez réellement besoin de vous inquiéter des améliorations potentielles des performances en nanosecondes, mesurez la différence. Il est très peu probable que vos déclarations de variable constituent le plus gros goulot d’étranglement de votre application.

Un conseil: arrêtez de vous soucier des constructions de langage qui sont microscopiquement plus rapides ou plus lentes que d’autres, et concentrez-vous plutôt sur celles qui vous permettent de vous exprimer le mieux.

De plus, pour savoir où passe votre code, utilisez un profileur.

Et comme d’autres l’ont souligné, les déclarations sont purement compilables, elles n’affectent pas le temps d’exécution.

Cela ne fait aucune différence. Dans une implémentation traditionnelle, la déclaration elle-même (à l’exclusion de l’initialisation) ne génère aucune instruction machine. Le code de prolog de fonction alloue généralement de l’espace dans la stack pour toutes les variables locales en même temps, quel que soit le lieu où elles sont déclarées.

Cependant, le lieu où vous déclarez que vos variables locales peut affecter les performances de votre code indirectement, du moins en théorie. Lorsque vous déclarez les variables aussi localement que possible (votre première variante), il en résulte généralement une taille plus petite du cadre de stack empilé par la fonction pour ses variables locales (puisqu’un même emplacement dans la stack peut être partagé par différentes variables locales. à différents moments). Avoir un cadre de stack plus petit réduit la consommation générale de mémoire de la stack, c’est-à-dire que les appels de fonction nesteds sont exécutés, la taille de la stack ne croît pas aussi vite (surtout avec les fonctions récursives). Cela améliore généralement les performances car les nouvelles allocations de pages de stack sont moins fréquentes et la localisation de la mémoire de stack devient meilleure.

Ces dernières considérations dépendent bien entendu de la plate-forme. Cela pourrait avoir très peu d’effet, voire aucun, sur votre plate-forme et / ou sur vos applications.

Cela ne prend pas de temps du tout. La mémoire des variables globales est allouée au démarrage, et la “déclaration” de variables sur la stack implique simplement la distance “ascendante” du pointeur de la stack lorsque la fonction est appelée.

les déclarations sont purement compilables, elles ne coûtent rien au moment de l’exécution¹. Mais le premier morceau de code est toujours meilleur que le second pour deux raisons

  • vous devez toujours initialiser les variables lorsque vous les déclarez, car elles ne peuvent jamais avoir de valeurs non initialisées. Cela va de pair avec
  • toujours utiliser la scope la plus étroite possible pour les déclarations de variables

Donc, votre premier exemple, même s’il n’est pas plus rapide que le second, est toujours meilleur.

Et toutes les personnes qui ont réagi en lui disant de ne pas optimiser son code prématurément ou micro ont tort. Il n’est jamais mauvais de savoir à quel point divers codes sont coûteux. Les meilleurs programmeurs ont une compréhension solide, presque inconsciente du coût de diverses stratégies et en tiennent compte automatiquement lors de la conception. La façon dont vous devenez programmeur consiste à poser ce type de question lorsque vous êtes débutant.

¹ En fait, il y a un petit coût lorsque chaque fonction alloue de la place pour des variables locales, mais ce coût est le même quel que soit le nombre de variables locales *.

* ok ce n’est pas vraiment vrai, mais le coût ne dépend que de la quantité totale d’espace, pas du nombre de variables.

La déclaration ne prend pas de temps du tout.

Le compilateur interprétera cette ligne comme une notification indiquant que l’espace doit exister sur la stack.

Comme d’autres l’ont déjà dit, cela ne devrait pas prendre de temps. Par conséquent, vous devez prendre cette décision en fonction d’autres facteurs: qu’est-ce qui rendrait votre code plus lisible et moins sujet aux bogues? Il est généralement considéré comme une bonne pratique de déclarer une variable aussi proche que possible de son utilisation (pour que vous puissiez voir la déclaration et l’utilisation en une fois). S’il est uniquement utilisé dans la scope interne, déclarez-le simplement à l’intérieur de cette scope – oubliez les performances sur celle-ci.

Déclarer des variables prend du temps, car il en résulte des instructions en langage machine qui allouent de l’espace aux variables de la stack. Il s’agit simplement d’un incrément du pointeur de stack, ce qui prend un temps infime, mais non nul.

Je crois que votre question est de savoir si plus de temps sera nécessaire (c.-à-d. Plus d’opérations d’incrémentation de stack) si la variable est déclarée à l’intérieur de la boucle. La réponse est non, car la stack est incrémentée une seule fois pour le bloc de boucle, et non à chaque exécution de la boucle. Ainsi, il n’y aura aucune différence dans le temps, même si la boucle exécute des zillions de zillions de fois.

Avertissement: Ce qui se produit dépend précisément de votre compilateur, de votre architecture, etc. Mais conceptuellement, voici ce qui se passe:

Lorsque vous déclarez une variable dans une méthode, elle est allouée sur la stack. L’affectation de quelque chose sur la stack implique uniquement de remonter le pointeur de la stack en fonction de la taille de la variable. Ainsi, par exemple, si SP représente l’adresse de mémoire située en haut de la stack, la déclaration de résultats de type char x dans SP += 1 et d’ int x résultats dans SP += 4 (sur un ordinateur 32 bits).

Lorsque la fonction se ferme, le pointeur de stack est retourné à son emplacement précédent avant l’appel de votre méthode. Donc, tout désallouer est rapide aussi.

Donc, dans tous les cas, il s’agit simplement d’un ajout, qui prend le même temps, quelle que soit la quantité de données.

Un compilateur intelligent combinera plusieurs déclarations de variables en un seul ajout.

Lorsque vous déclarez une variable dans une boucle, cela pourrait théoriquement changer le pointeur de la stack à chaque itération de la boucle, mais là encore, un compilateur intelligent ne le fera probablement pas.

(Une exception notable est le C ++, qui effectue un travail supplémentaire car il doit appeler des constructeurs et des destructeurs lorsque l’object alloué par stack est créé ou détruit.)

Je ne me soucierais pas d’une nanoseconde ici ou là. Sauf si vous devez accéder à sa valeur après la fin de la boucle for, laissez la variable à l’intérieur de la boucle: elle sera plus proche du code qui l’utilise (votre code sera plus lisible) et sa scope sera délimitée par la boucle elle-même ( votre code sera plus élégant et moins sujet aux bogues).

Je parie que le binary compilé sera identique dans les deux cas.

La déclaration de variable est transformée en réservation d’espace de stack par le compilateur. Maintenant, comment ce travail dépend-il entièrement de la plate-forme? Sur x86 et à peu près toutes les architectures populaires, il s’agit simplement d’une soustraction de l’adresse du cadre de la stack et / ou du mode d’adressage par indexation pour accéder du haut de la stack. Tous ces éléments entraînent le coût d’une simple soustraction \ addition, ce qui n’est vraiment pas pertinent.

Techniquement, le deuxième exemple est moins efficace, car la déclaration se produit à chaque entrée dans l’étendue de la boucle, c’est-à-dire à chaque itération de la boucle. Cependant, il y a 99,99% de chances que l’espace de la stack ne soit réservé qu’une seule fois. Même l’opération d’affectation sera optimisée, bien que, techniquement, il convienne de le faire à chaque itération de la boucle. Maintenant, en C ++, cela peut devenir bien pire si la variable a un constructeur qui sera ensuite exécuté à chaque itération de boucle.

Et en bout de ligne, vous ne devriez vraiment pas vous inquiéter de ces problèmes sans un profilage adéquat. Et même dans ce cas, il y a beaucoup plus de questions précieuses à vous poser ici, telles que “quel est le moyen le plus lisible de le faire, ce qui est plus facile à comprendre et à maintenir, etc.”.