Résumé des catégories de stockage, des liens et de la gestion de la mémoire

Gestion des catégories de stockage, des liens et de la mémoire

1. Catégorie de stockage et étendue

Le langage C contient 4 types de stockage, voir le tableau suivant:

fonctionnalité Type de stockage automatique Enregistrer le type de stockage Type de stockage statique Type de stockage externe
Mot-clé auto S'inscrire statique externe
Stocké dans RAM Registre CPU RAM RAM
Valeur initiale par défaut Valeur indésirable Valeur indésirable 0 ou vide 0 ou vide
Portée Confiné aux blocs Confiné aux blocs Confiné aux blocs Global
Cycle de la vie Bloquer Bloquer Existe entre les fonctions Existe entre les fonctions

    Le bloc fait référence à un groupe d'instructions écrites entre accolades gauche et droite: "{}". Les variables locales sont des variables déclarées dans le bloc.

La différence entre les variables locales et les variables globales:

  • Les variables locales sont des variables déclarées à l'intérieur d'un bloc ou d'une fonction. La portée des variables locales est limitée au bloc ou à la fonction. Si les variables locales ne sont pas initialisées, elles contiendront des données inutiles.

  • Les variables globales sont des variables déclarées avant tous les blocs et fonctions. Les variables globales sont valides pour toutes les fonctions déclarées après. Les variables globales sont initialisées avec des valeurs par défaut, telles que 0.

Portée

L'étendue décrit la zone du programme où l'identifiant est accessible. La portée d'une variable C peut être la portée du bloc, la portée de la fonction, la portée du prototype de fonction ou la portée du fichier.

  • Portée du
    bloc Un bloc est une zone de code entre accolades. Par exemple, l'ensemble du corps de la fonction est un bloc et toute instruction composée de la fonction est également un bloc. Les variables définies dans un bloc ont une portée de bloc, et la plage visible d'une variable de portée de bloc va de la définition à la fin du bloc contenant la définition. De plus, bien que les paramètres formels d'une fonction soient déclarés avant l'accolade ouvrante de la fonction, ils ont également une portée de bloc et appartiennent au bloc du corps de la fonction.

  • Portée de la
    fonction La portée de la fonction (portée de la fonction) n'est utilisée que pour les balises des instructions goto. Cela signifie que même si une étiquette apparaît dans le bloc interne d'une fonction pour la première fois, sa portée s'étend à la fonction entière. Si la même étiquette est utilisée dans deux blocs, ce sera déroutant. La portée de la fonction de l'étiquette empêche que cela se produise.

  • Portée du prototype de
    fonction La portée du prototype de fonction est utilisée pour les noms de paramètres (noms de variable) dans le prototype de fonction, comme indiqué ci-dessous:
    int mighty (int mouse, double large); La
    portée de la portée du prototype de fonction est de la forme La définition du paramètre se termine à la fin de la déclaration du prototype. Cela signifie que le compilateur ne se soucie que du type de paramètre dans le prototype de fonction, et le nom du paramètre (le cas échéant) n'a généralement pas d'importance. De plus, même s'il existe des noms de paramètres formels, ils ne doivent pas nécessairement correspondre aux noms de paramètres formels dans la définition de fonction. Uniquement dans les tableaux de longueur variable, les noms de paramètres formels sont utiles:
    void use_a_VLA (int n, int m, ar [n] [m]);
    Le nom déclaré dans le prototype de fonction doit être utilisé entre crochets.

  • Portée du fichier
    La définition des variables est en dehors de la fonction et a une portée de fichier. Une variable avec une portée de fichier est visible de sa définition à la fin du fichier où se trouve la définition.

2. Lien

    Les variables C ont trois attributs de lien: lien externe, lien interne ou pas de lien.
    Les variables avec une portée de bloc, une portée de fonction ou une portée de prototype de fonction sont des variables non liées. Cela signifie que ces variables sont privées du bloc, de la fonction ou du prototype dans lequel elles sont définies. Les variables ayant une portée de fichier peuvent être des liens externes ou des liens internes. Les variables de lien externe peuvent être utilisées dans des programmes multi-fichiers, et les variables de lien interne ne peuvent être utilisées que dans une unité de traduction.
     Lien détaillé

3. Période de stockage

    La portée et le lien décrivent la visibilité de l'identifiant. La période de stockage décrit la durée de vie des objets accessibles via ces identifiants.
    Les objets C ont quatre périodes de stockage: période de stockage statique, période de stockage des threads, période de stockage automatique et période de stockage d'allocation dynamique.
    Si l'objet a une durée de stockage statique, il existera toujours pendant l'exécution du programme. Les variables d'étendue de fichier ont une période de stockage statique. Notez que pour les variables d'étendue de fichier, le mot - clé static indique l'attribut de lien, pas la période de stockage . La variable de portée de fichier déclarée comme statique a un lien interne. Mais qu'il s'agisse d'un lien interne ou d'un lien externe, toutes les variables d'étendue de fichier ont une période de stockage statique.
    La période de stockage des threads est utilisée pour la programmation simultanée et l'exécution du programme peut être divisée en plusieurs threads. Les objets avec une période de stockage de thread existent à partir du moment où ils sont déclarés jusqu'à la fin du thread. Lorsqu'un objet est déclaré avec le mot-clé _Thread_local, chaque thread obtient une copie privée de la variable.
    Les variables à portée de bloc ont généralement une durée de stockage automatique. Lorsque le programme entre dans le bloc où ces variables sont définies, de la mémoire est allouée pour ces variables; lorsque le bloc est quitté, la mémoire qui vient d'être allouée pour les variables est libérée. Cette approche équivaut à traiter la mémoire occupée par les variables automatiques comme une zone de travail réutilisable ou une zone de stockage temporaire. Par exemple, après la fin d'un appel de fonction, la mémoire occupée par ses variables peut être utilisée pour stocker les variables de la fonction appelée suivante. Les tableaux de longueur variable sont légèrement différents et leur période de stockage va de la déclaration à la fin du bloc, et non du début du bloc à la fin du bloc.

4. Variables dynamiques indépendantes

    Les variables appartenant à la catégorie de stockage automatique ont une durée de stockage automatique, une étendue de bloc et aucun lien. Par défaut, toute variable déclarée dans un en-tête de bloc ou de fonction appartient à la catégorie de stockage automatique.
    Les variables avec période de stockage automatique signifient que les variables existent lorsque le programme entre dans le bloc où la variable est déclarée, et les variables disparaissent lorsque le programme quitte le bloc. L'emplacement mémoire initialement occupé par la variable peut maintenant être utilisé à d'autres fins.

Variable statique Variable automatique Enregistrer la variable
Toutes les variables déclarées en dehors du bloc de code Variables définies à l'intérieur du bloc de code Variables modifiées avec registre
Stocké en mémoire statique Stocké dans le tas et la pile Stocké dans le registre
Créé avant l'exécution du programme et existe pendant toute l'exécution jusqu'à la fin du programme Le flux de contrôle est créé lors de la saisie du bloc de code et détruit lors de la sortie L'heure de création et de destruction est la même que la variable automatique

5. Variables statiques de type bloc

    Une variable statique sonne comme une variable immuable. En fait, statique signifie que la variable reste en place en mémoire et non que sa valeur ne change pas.
    Les variables avec une portée de fichier ont automatiquement (et doivent être) une durée de stockage statique.
    Vous pouvez créer des variables locales avec une durée de stockage statique et une portée de bloc. Ces variables ont la même portée que les variables automatiques, mais ces variables ne disparaîtront pas une fois que le programme aura quitté la fonction dans laquelle elles se trouvent. En d'autres termes, cette variable a une portée de bloc, pas de lien, mais a une période de stockage statique. L'ordinateur enregistre leurs valeurs entre plusieurs appels de fonction. Dans le bloc (fournir une portée de bloc et aucun lien), déclarer ce type de variable avec le spécificateur de classe de stockage static (fournir une période de stockage statique)

6. Variables statiques des liens externes

    Les variables statiques liées en externe ont une portée de fichier, une liaison externe et une période de stockage statique. Cette catégorie est parfois appelée classe de stockage externe et les variables appartenant à cette catégorie sont appelées variables externes. Mettre la déclaration de définition des variables en dehors de toutes les fonctions crée des variables externes. Bien entendu, afin de souligner que la fonction utilise des variables externes, vous pouvez utiliser le mot-clé extern pour la déclarer à nouveau dans la fonction. Si une variable externe utilisée par un fichier de code source est définie dans un autre fichier de code source, vous devez utiliser extern pour déclarer la variable dans ce fichier.
Comme suit:

int Errupt;        /* 外部定义的变量 */
double Up[100];      /* 外部定义的数组 */
extern char Coal;     /* 如果Coal被定义在另一个文件,则必须这样声明 */
void next(void);
int main(void)
{
    
    
    extern int Errupt;   /* 可选的声明*/
    extern double Up[];  /* 可选的声明*/
    ...
}
void next(void)
{
    
    
    ...
}

    Notez que lorsque vous déclarez le tableau Up dans main () (il s'agit d'une déclaration facultative), vous n'avez pas besoin de spécifier la taille du tableau, car la première déclaration a déjà fourni les informations sur la taille du tableau. Les deux déclarations externes dans main () peuvent être complètement omises, car les variables externes ont une portée de fichier, donc Errupt et Up sont visibles de la déclaration à la fin du fichier. Ils n'y apparaissent que pour illustrer que la fonction main () utilise ces deux variables.

7. Fonction aléatoire

Besoin d'inclure les fichiers d'en-tête:

#include <stdlib.h>

    La fonction rand () génère des entiers dans l'ordre spécifié, donc chaque fois que l'instruction ci-dessus est exécutée, les deux mêmes valeurs sont affichées. Par conséquent, le caractère aléatoire du langage C n'est pas aléatoire dans le vrai sens du terme. Parfois, il l'est aussi appelé nombre pseudo-aléatoire . Avant d'utiliser rand () pour générer des nombres aléatoires, vous devez initialiser la séquence de nombres pseudo-aléatoires avec la fonction d'initialisation srand (graine non signée) du générateur aléatoire (également située dans stdlib.h). La graine est également appelée graine aléatoire. En termes simples, si vous la fournissez à chaque fois Si les graines sont les mêmes, les dernières valeurs aléatoires générées à chaque tour sont également les mêmes, elles sont donc appelées nombres pseudo-aléatoires, vous devez donc pour fournir une valeur de départ différente à chaque fois pour obtenir un caractère aléatoire complet. Nous utilisons généralement la fonction de temps time (NULL) Comme valeur de départ, car la valeur de temps est différente chaque seconde, cette fonction doit inclure les fichiers d'en-tête suivants:

#include <time.h>

8. Allouer de la mémoire: malloc () et free ()

Voyez ce que le patron a dit:

9. Qualificateur de type ANSI C

1. qualificatif de type de monstre
la description Exemple sens
Const avant le type const float * p Le pointeur lui-même peut être modifié et la valeur pointée ne peut pas être modifiée
Const avant le nom de la variable float * const p Le pointeur lui-même ne peut pas être modifié et la valeur pointée peut être modifiée
Tapez, const avant le nom de la variable const float * const p Le pointeur lui-même ne peut pas être modifié et la valeur pointée ne peut pas être modifiée
Après le type, * avant const float const * p Le pointeur lui-même peut être modifié et la valeur pointée ne peut pas être modifiée

    En général: const est placé sur le côté gauche de [], les données pointées par le pointeur ne peuvent pas être modifiées, placé sur le côté droit de [], le pointeur lui-même ne peut pas être changé

2. Qualifiant de type volatil

    Le qualificatif volatile indique à l'ordinateur que l'agent (et non le programme où se trouve la variable) peut modifier la valeur de la variable. Habituellement, il est utilisé pour les adresses matérielles et le partage de données entre d'autres programmes ou threads s'exécutant en même temps.

(1) Le compilateur interdira l'optimisation de lecture et d'écriture des variables modifiées volatiles.

    Le mot clé volatile est un modificateur de type. La variable de type déclarée avec elle peut être modifiée par certains facteurs inconnus du compilateur, tels que le système d'exploitation, le matériel ou d'autres threads. Lorsqu'il rencontre la variable déclarée par ce mot-clé, le compilateur n'optimisera plus le code qui accède à la variable, de manière à fournir un accès stable à l'adresse spéciale.

(2) Chaque fois qu'une variable volatile modifiée est lue, elle sera lue depuis la mémoire.

    Volatile peut être interprété comme un "accès direct à l'adresse mémoire d'origine"; la "variabilité" est causée par des facteurs externes, tels que le multithreading, les interruptions, etc., pas parce que la variable modifiée avec volatile est "volatile", sinon cause externe, même si une définition volatile est utilisée, elle ne changera pas.

3. qualificatif de type de restriction

    Le mot clé restrict permet au compilateur d'optimiser certaines parties du code pour mieux prendre en charge les calculs. Il ne peut être utilisé que pour les pointeurs, indiquant que le pointeur est le seul et initial moyen d'accéder à l'objet de données.
    Restrict est introduit par la norme C99. Il ne peut être utilisé que pour limiter et restreindre les pointeurs. L'objet a été référencé par le pointeur et le contenu de l'objet ne peut pas être modifié par toutes les autres méthodes directes ou indirectes à l'exception du pointeur. Autrement dit, il indique au compilateur que toutes les opérations qui modifient le contenu de la mémoire pointée par le pointeur doivent être modifiées via le pointeur, et ne peuvent pas être modifiées par d'autres moyens (autres variables ou pointeurs); l'avantage de ceci est qu'il peut aider le compilateur à exécuter un code mieux optimisé pour générer un code d'assemblage plus efficace. Par exemple, l'unité de mémoire pointée par int * restrict ptr, ptr n'est accessible que par ptr, et tous les autres pointeurs qui pointent également vers cette unité de mémoire sont indéfini, simple C'est un pointeur non valide. L'émergence de restrict est due aux failles inhérentes au langage C. Les programmeurs C devraient activement éviter cette faille, et le compilateur optimisera également votre code de manière très coopérative.
    Le qualificatif restrict peut également être utilisé pour les pointeurs dans les paramètres de fonction. Cela signifie que le compilateur peut supposer que d'autres identificateurs dans le corps de la fonction ne modifieront pas les données pointées par le pointeur, et le compilateur peut essayer de l'optimiser afin qu'il ne soit pas utilisé à d'autres fins

FIN —— Résumé de ce chapitre:

sommaire

Je suppose que tu aimes

Origine blog.csdn.net/qq_52355487/article/details/111083201
conseillé
Classement