当前位置:网站首页>【 langage c】 stockage des données d'analyse approfondie en mémoire

【 langage c】 stockage des données d'analyse approfondie en mémoire

2022-06-26 05:37:00 Superman ne peut pas voler, ke.


Préface

HelloIci. Superman ne peut pas volerke,Une journée si chaude,Idéal pour rester dans une chambre climatisée pour étudier,Xiao Bian a aussi été accro à l'étude ces jours - ci!Aujourd'hui, j'aimerais vous résumer quelques - uns des résultats de l'étude de ces derniers jours,Et partager quelques expériences

Cet article traite du stockage des données en mémoire,ApplicationCLa profondeur du langage analyse exactement comment les données sont stockées en mémoire,Et quelques exemples pour vous aider à comprendre et à maîtriser.Laissez - moi vous montrer la porte de la mémoire de l'ordinateur,Cultiver notre“Compétences internes cardio”C'est parti.!!



1️⃣ Description du type de données

 InCDans la langue,Pour représenter toutes sortes de choses différentes dans la vie,Plusieurs types sont définis.Non seulement il y a des types intégrés que nous connaissons,Et les types de construction que nous pouvons jouer nous - mêmes.Différents types de stockage en mémoire sont également différents, Les différences mentionnées ici se rapportent principalement à la taille de l'espace occupé , Bien sûr, il peut parfois y avoir différents types de points de vue .
En résumé,On peut en arriver là.c Le sens du type dans la langue :

  1. Spécifie l'espace ouvert en mémoire pour différents types d'utilisation (Taille de l'espace occupé)
  2. Comment voir la perspective de l'espace mémoire

On va trier ça. c Type de langue !

1.Famille entière

char(Type de caractère)
signed char
unsigned char
Taille de l'espace occupé:1Octets
Pourquoi les types de caractères sont - ils également inclus dans la famille entière ?
Parce que la nature des caractères est ASCIIValeur du Code, Ces valeurs sont des entiers , C'est pourquoi il a été inclus dans la famille entière.


short (Forme courte)
signed short [int]
unsigned short [int]
Taille de l'espace occupé:2Octets


int
signed int
unsigned int
Taille de l'espace occupé:4Octets


long(Long lifting)
signed long [int]
unsigned long [int]

Inc99 Il a également été ajouté à la norme long long Type d'entier long , Sa taille est de huit octets

Il y a deux choses dont nous devons tenir compte ici. :

  1. unsignedType non signé( Pour définir les données de la vie qui n'ont pas de nombres négatifs ,c La langue définit unsignedType de,Par exemple::Taille、Poids corporel);
  2. Lorsque nous créons un type short、int、longLorsque la variable, Le compilateur par défaut est une variable signée (Par exemple:intPar défautsigned int);
  3. Et quand nous créons un type charLorsque la variable, Le compilateur n'est pas nécessairement par défaut à signed char. Différents compilateurs ont des valeurs par défaut différentes pour eux .
  4. Quand nous créons des variables , Si vous voulez représenter un nombre qui n'a que des nombres positifs, vous pouvez créer un unsignedType, Au lieu de cela, vous pouvez créer un signedType.

2.Famille de nombres flottants

float(Faible précision)


double(Haute précision)

Les nombres flottants sont généralement utilisés pour représenter des décimales

3.Type de construction

Type de tableau
Type de structure:struct
Type d'énumération:enum
Type d'union:union

4.Type de pointeur

int* pi
char* pc
float* pf
double* pd
void* pv




2️⃣Stockage des données en mémoire

Donc, une fois que vous connaissez le type de données, , Voyons comment les données sont stockées en mémoire !

Nous savons que,Les variables sont créées pour créer de l'espace en mémoire, La taille de l'espace est déterminée par le type de variable .Alors, Dans cet espace ouvert, , Sous quelle forme les données sont - elles stockées? ? Comment les différents types de données sont - ils stockés différemment? ? Nous allons maintenant discuter de deux façons de stocker des données entières et flottantes en mémoire .


1. Stockage des entiers en mémoire

Code source、Code inverse、Complément

Comment les entiers sont stockés en mémoire ?
Pour découvrir la vérité , Nous devons d'abord comprendre les concepts suivants ——
Code source、Code inverse、Complément:
Il y a trois types d'entiers dans un ordinateur2Représentation décimale,C'est le code original.、Inversion et complément.Les trois représentations ont deux parties: les bits symboliques et les bits numériques, Le BIT de symbole est le premier bit d'une séquence binaire ,Avec0Représentation“Positif”,Avec1Représentation“Négatif”,Et les bits numériques,Original of positive、Contre、Le complément est le même,Les trois représentations des entiers négatifs sont différentes( Une méthode de représentation des entiers négatifs Les détails sont les suivants:

  1. Code source:Le code source peut être obtenu en traduisant les nombres directement en binaires sous forme de nombres positifs et négatifs.;
  2. Code inverse: Le code original est inversé en fonction de la position, à l'exception de la position du symbole. ,Obtenez le Code inverse;
  3. Complément:Code inverse+1J'ai un complément..

Prends une châtaigne.:TailleintType -6Code original、Code inverse、 Le complément est le suivant: :
Insérer la description de l'image ici

En fait...,Pour les entiers:La mémoire de stockage des données contient en fait un complément.Comme ci - dessus.-6,Si on en crée unintVariable de typeint a = -6, Il ouvre un espace de taille appropriée dans la mémoire en fonction du type de variable ( Le type de variable ici est int Ouvre un espace de quatre octets ). Ensuite, le complément des données initialisées est stocké dans cet espace . Pas seulement l'initialisation , Il en va de même pour l'attribution des variables , C'est juste qu'il n'y a pas d'espace. .

Comme le montre la figure
Insérer la description de l'image ici

L'Unit é d'adresse en mémoire est un octet , Ouvrir l'espace correspondant en fonction du type , Pour éviter le gaspillage d'espace .Nous savons que,Un octet est8Bits, Par conséquent, chaque octet contient 8Bits, Juste déposé. 32Bits.Ce qui est important ici, c'est que, La création de la variable locale a été créée dans la zone de pile en mémoire ,Et les variables globales、 Les variables statiques sont créées dans la zone statique .

Pour faciliter l'analyse ultérieure , Nous convertissons une séquence binaire en hexadécimal ,Comme le montre la figure( Un chiffre hexadécimal correspond à quatre chiffres binaires ):
Insérer la description de l'image ici


Alors la question se pose, Pourquoi les données entières sont - elles stockées en mémoire avec un complément ?

Dans un système informatique,Les valeurs numériques sont toujours représentées et stockées par un complément.La raison en est que

  1. Utiliser un complément,Les bits symboliques et les champs numériques peuvent être traités uniformément
  2. En même temps,L'addition et la soustraction peuvent également être traitées uniformément(CPUAdder seulement)
  3. En outre,Conversion mutuelle du complément et du code source,Le processus de calcul est le même,Aucun circuit matériel supplémentaire n'est nécessaire.

Explication

  1. Représentation des données positives et négatives par des bits symboliques , Les bits de symbole et les bits valides peuvent être traités de façon uniforme ;
  2. CPUAdder seulement, Comment la soustraction est - elle réalisée? ?Par exemple, calcul1-1,EtCPU Est converti en 1+(-1).Et pour1+(-1), Si vous Calculez directement avec le code source ,Et:
    1+(-1)=00000000000000000000000000000001+10000000000000000000000000000001=10000000000000000000000000000010
    Le résultat n'est pas égal à 0, Nous n'obtenons pas les résultats que nous voulons . Et si on calcule avec un complément ,Et:
    1+(-1)=00000000000000000000000000000001+11111111111111111111111111111111=100000000000000000000000000000000
    Et voici un qui devient 33Bits,Ça déborde.intLa gamme spatiale de. Donc, en abandonnant le plus haut, on obtient le résultat suivant: 0,C'est le résultat que nous voulons. Cela démontre l'avantage d'utiliser des compléments pour stocker des données
  3. C'est aussi l'astuce du complément. . Le processus de conversion du code source du complément est le même , C'est tout. 1.
    Par-1Par exemple
    Insérer la description de l'image ici
    Comme le montre la figure, Il est vérifié que le processus de conversion entre le complément et le code source est le même .



Introduction à la taille

Voici une autre question. .Regardez les photos.!
Insérer la description de l'image ici
En dessinant des images de données stockées dans l'espace mémoire , Les stocker dans l'ordre habituel ,Alors, Quel est l'ordre dans lequel les données sont stockées en mémoire ? Est - ce dans cet ordre que nous avons dessiné ?
Voici un concept que nous devons comprendre ——Taille, Comprendre la taille , Pour comprendre le mystère. .

  • Qu'est - ce que la taille? ?

La taille est c Deux modes de stockage des données en mémoire dans la langue :

  • Grande extrémité(Stockage)Mode,Le BIT inférieur des données est stocké dans une adresse mémoire élevée,Et les bits élevés des données sont stockés dans des adresses basses en mémoire;
  • Petit bout(Stockage)Mode,Le BIT inférieur des données est stocké dans une adresse mémoire basse,Et le haut niveau des données,Enregistrer en mémoire à haute adresse.

Ici.,Est en octets, Un ordre d'octets composé à la fois d'octets bas et élevés , Appelé Ordre des octets de fin de taille .

  • Pourquoi y a - t - il des extrémités de taille?

Inc Il existe de nombreux types dans la langue ,Par exemple:short、int、long… Ils sont tous de tailles différentes. ,Par exemple,shortLa taille de2Octets,intLa taille de4Octets. Le stockage de plusieurs octets en mémoire implique nécessairement des problèmes d'ordre , Parce qu'il y a beaucoup de façons différentes de trier ,c Il y a deux langues :Mode grand et petit. Le mode de stockage sur l'ordinateur peut être grand ou petit , Le matériel détermine lequel .

Ici, nous prenons la séquence hexadécimale 11223344 Exemple de stockage en mémoire , Aide à l'illustration :
Insérer la description de l'image ici
Insérer la description de l'image ici
Je vois., Les deux modes de stockage sont diamétralement opposés . Le stockage à grande échelle est plus logique pour la pensée humaine , Et les petites extrémités stockent la logique de fonctionnement des ordinateurs plus symboliques .

Pour mieux comprendre les grandes et les petites extrémités , Voici un exemple de taille :

Concevoir une applet pour déterminer l'ordre des octets de la machine actuelle

Directement au Code

#include <stdio.h>
int check_key()
{
    
	int a = 1;//Créer une variablea
	char* p = (char*)&a;
	//Prends - le.aAdresse( Par la connaissance du pointeur ,Variable entièrea L'adresse de est l'adresse de l'octet le plus bas de son espace de quatre octets )
	// Et force le type à char*Type, Enregistrer la variable pointeur pMoyenne
	return *p;//RetourpValeur en,Si oui1Petite extrémité,- Oui.0C'est grand
}
int main()
{
    
	int ret = check_key();// Déterminer la taille par la valeur de retour de la fonction 
	if (ret == 1)
	{
    
		printf("Petit bout\n");
	}
	else
	{
    
		printf("Grande extrémité\n");
	}
	return 0;
}

Insérer la description de l'image ici
Vous pouvez voir la mémoire en débogage ( L'ordre des octets ici est exprimé en hexadécimal ),a Les données sont stockées en mode petit terminal . Donc quand nous changeons le type de pointeur char* Lors de l'accès aux données dans son premier octet ,Ce qu'on a, c'est1Octet le plus bas de01. S'il s'agit d'un grand stockage, nous obtiendrons 00.




Lifting、Conversion arithmétique et exemples

Maîtrise du stockage des données en mémoire , Nous savons comment les données vont dans la mémoire “Pose ça.”.Alors,Oui.“Pose ça.”C'est sûr.“Prends ça.”, Quand nous voulons extraire et utiliser des données entières en mémoire , Qu'y a - t - il de si merveilleux? ? Pour comprendre le mystère , Nous devons maîtriser ces concepts :Lifting、Conversion arithmétique

1.Lifting

  • Qu'est - ce qu'un lifting?

C.Les opérations arithmétiques d'un entier sont toujours effectuées avec au moins la précision du type entier par défaut.Pour obtenir cette précision,Les caractères et les opérandes d'entiers courts dans les expressions sont convertis en entiers normaux avant utilisation,Cette conversion est appeléeLifting.

  • Importance de l'amélioration de la forme?

L'opération entière d'une expression doit êtreCPUExécution dans le dispositif informatique correspondant de,CPUOpérateur d'entier interne(ALU)La longueur en octets de l'opérande pourintLongueur des octets pour,En même temps,CPULongueur du registre général pour.Donc,,Même les deuxcharAjouter des types,InCPUEn fait, vous devez d'abord convertir enCPULongueur standard de l'opérande entier intérieur.GénéralitésCPU(general-purpose CPU)C'est difficile de réaliser deux8Opération d'addition directe de bits octets(Bien que cette instruction d'addition d'octets puisse exister dans l'instruction machine).Alors...,Les différentes longueurs de l'expression peuvent être inférieures àintValeur entière de la longueur,Doit être converti enintOuunsigned int,Avant d'entrerCPUPour effectuer des opérations.

  • Quand l'amélioration de la forme se produira - t - elle? ?
  1. char、short Opérande de type en cours Opérations d'expression Le levage intégral se produit avant
  2. InprintfEn fonction,Quandchar、shortType de donnéesPar%dOu%uImprimer le format pour Heure, L'élévation de l'entier se produit en premier (Par%u Le format est converti en unsigned int)
  • Comment effectuer une promotion intégrale?

*Levage plastique négatif:char c1 = -1; Variablesc1Binaire de(Complément)Il n'y a que8Bits:1111111 ,Parce que char Signé char, Donc quand le lifting,Bit de symbole supplémentaire haut de gamme,C'est - à - dire:1,Le résultat après l'Ascension est :
11111111111111111111111111111111
*Amélioration de la forme positive:char c2 = 1; Variablesc2Binaire de(Complément)Il n'y a que8Bits: 00000001 ,Parce que char Signéchar,Donc quand le lifting,Bit de symbole supplémentaire haut de gamme,C'est - à - dire:0,Le résultat après l'Ascension est :
00000000000000000000000000000001

*Levage de forme non signé: Supplément supérieur0

Prenez deux châtaignes

Exemple 1:

#include <stdio.h>
int main()
{
    
	char a = 1;
	char b = -1;
	char c = a + b;
	//00000001 -> 00000000000000000000000000000001 a
	//11111111 -> 11111111111111111111111111111111 b
	//a+b == 00000000000000000000000000000000
	//00000000 -> c
	return 0;
}

aEtbLa valeur de est portée à un entier normal,Effectuer le calcul. Le résultat de l'opération est également un entier normal , Dépôt général entier cMoyenne,Ça doit arriverTroncatureDépôt ultérieur, Dépôt existant cLa valeur de0
Troncature: Lors de l'attribution d'un type de données grand octet à un type de données petit octet , Manque d'espace pour les petits types de données , Impossible d'accommoder le type de Big Data , Il y a donc une troncature . La règle de troncature est : Le BIT inférieur du type Big Data est stocké dans le type Small Data .(Comme ici.intÀchar,À prendreintFaible8Position assignée àchar)


Exemple 2:

#include <stdio.h>
int main()
{
    
	char a = 0xb6;
	short b = 0xb600; 
	int c = 0xb6000000; 
	//
	if (a == 0xb6)
		printf("a"); 
	if (b == 0xb600)
		printf("b"); 
	if (c == 0xb6000000)
		printf("c"); 
	return 0;
}

Lorsque la variable agit comme opérateur de relation 、 Lorsque l'opérande d'un opérateur logique , C'est aussi une expression. , Une élévation de type entier peut également se produire .
Ici.a,bPour effectuer un lifting plastique,MaiscPas besoin de Lifting plastique a,bAprès le lifting,Est devenu négatif,Donc l'expression a==0xb6 , b==0xb600C'est faux.,La valeur de retour est0,MaiscPas de levage de forme,Alors l'expression c==0xb6000000 Le résultat est vrai.
Le résultat de la sortie programmée est: c


2.Conversion arithmétique

Si les opérandes d'un opérateur sont de types différents,À moins que l'un des opérandes ne soit converti en un autre type d'opérande,Sinon, l'opération ne peut pas être effectuée.Le système hiérarchique suivant est appeléConversion arithmétique ordinaire.

Insérer la description de l'image ici

Si le type d'un opérande est classé bas dans la liste ci - dessus( Les flèches pointent de bas en haut ),Ensuite, vous devez d'abord convertir le type en un autre opérande et effectuer l'opération.

Prends une châtaigne.

#include <stdio.h>
int main()
{
    
	int a = -4;
	unsigned int b = 8;
	printf("%d", a + b);
	return 0;
}

L'illustration est la suivante::

Insérer la description de l'image ici

Attention! La conversion arithmétique doit être raisonnable, Cela peut entraîner une perte de précision

float f = 3.14;
int num = f;//Conversion implicite,Il y aura une perte de précision

3.Exemples

Maîtrise du levage intégral et de la conversion arithmétique “Compétences internes”Après, Maintenant, pratiquons quelques questions pour les consolider


Un.、

// Perdre. Sortez! Qu'est - ce que - Oui. ? 
#include <stdio.h> 
int main()
{
    
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}

Insérer la description de l'image ici
Résultats des opérations
Insérer la description de l'image ici



2.、

// Perdre. Sortez! Qu'est - ce que - Oui. ? 
#include <stdio.h> 
int main()
{
    
	char a = -128;
	printf("%u\n", a);
	return 0;
}

Insérer la description de l'image ici
Résultats des opérations
Insérer la description de l'image ici



Trois、

// Perdre. Sortez! Qu'est - ce que - Oui. ? 
#include <stdio.h> 
int main()
{
    
	char a = 128;
	printf("%u\n", a);
	return 0;
}

Insérer la description de l'image ici
Résultats des opérations

Le résultat est le même que pour la deuxième question
Insérer la description de l'image ici



Quatre、

//Produit quoi??
#include <stdio.h> 
int main()
{
    
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
}

Insérer la description de l'image ici
Résultats des opérations
Insérer la description de l'image ici



Cinq、

#include <stdio.h>
//Quel est le résultat??
int main()
{
    
	unsigned int i;
	for (i = 9; i >= 0; i--) 
	{
    
		printf("%u\n", i);
	}
}

Parce que les variablesiLe type deunsigned int, Donc ça ne peut pas être plus petit que 0, C'est - à - dire que le cycle ne peut pas se terminer . Donc le programme va entrer dans un cycle mort .




Six、

//Le résultat est?
#include <stdio.h>
int main()
{
    
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
    
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

Pour comprendre le problème ,La première chose à savoirchar Plage de taille des données de type . Le diagramme ci - dessous aide à comprendre :
Insérer la description de l'image ici

Nous savons que,charType1Octets,Oui.8Bits,8 Les chiffres que les bits peuvent représenter sont: 2^8C'est - à - dire256- Oui.. Comme le montre la figure 0C'est parti., Un tour dans le sens des aiguilles d'une montre est char Tous les nombres qui peuvent être représentés . Il y a une exception ici ,10000000 Si ce complément est converti en original ,Oui.100000000,Un de plus,Ça déborde.charDe l'espace.Donc,,c Les dispositions linguistiques charType,10000000Représentation-128.En résumé,char La plage de taille des données de type est -128~127.

Après avoir maîtrisé ce point de connaissance, nous reviendrons à la question :
Insérer la description de l'image ici
Résultats des opérations
Insérer la description de l'image ici

Vous voulez connaître les plages de taille pour d'autres types d'entiers ,Vous pouvez le faire en interrogeantlimits.hFichier d 'en - tête, En savoir plus . Ce dont nous devons nous souvenir, c'est que charBon frère de unsigned char,Son champ d'application est0~255.

Voici le code dans l'en - tête

#pragma once
#define _INC_LIMITS

#include <vcruntime.h>

#pragma warning(push)
#pragma warning(disable: _VCRUNTIME_DISABLED_WARNINGS)

_CRT_BEGIN_C_HEADER

#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define UCHAR_MAX 0xff

#ifndef _CHAR_UNSIGNED
    #define CHAR_MIN SCHAR_MIN
    #define CHAR_MAX SCHAR_MAX
#else
    #define CHAR_MIN 0
    #define CHAR_MAX UCHAR_MAX
#endif

#define MB_LEN_MAX 5
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
#define USHRT_MAX 0xffff
#define INT_MIN (-2147483647 - 1)
#define INT_MAX 2147483647
#define UINT_MAX 0xffffffff
#define LONG_MIN (-2147483647L - 1)
#define LONG_MAX 2147483647L
#define ULONG_MAX 0xffffffffUL
#define LLONG_MAX 9223372036854775807i64
#define LLONG_MIN (-9223372036854775807i64 - 1)
#define ULLONG_MAX 0xffffffffffffffffui64

#define _I8_MIN (-127i8 - 1)
#define _I8_MAX 127i8
#define _UI8_MAX 0xffui8

#define _I16_MIN (-32767i16 - 1)
#define _I16_MAX 32767i16
#define _UI16_MAX 0xffffui16

#define _I32_MIN (-2147483647i32 - 1)
#define _I32_MAX 2147483647i32
#define _UI32_MAX 0xffffffffui32

#define _I64_MIN (-9223372036854775807i64 - 1)
#define _I64_MAX 9223372036854775807i64
#define _UI64_MAX 0xffffffffffffffffui64

#ifndef SIZE_MAX
    // SIZE_MAX definition must match exactly with stdint.h for modules support.
    #ifdef _WIN64
        #define SIZE_MAX 0xffffffffffffffffui64
    #else
        #define SIZE_MAX 0xffffffffui32
    #endif
#endif

#if __STDC_WANT_SECURE_LIB__
    #ifndef RSIZE_MAX
        #define RSIZE_MAX (SIZE_MAX >> 1)
    #endif
#endif

_CRT_END_C_HEADER

#pragma warning(pop) // _VCRUNTIME_DISABLED_WARNINGS



2. Stockage en mémoire flottante

Nous avons maîtrisé le stockage des données entières en mémoire .EtcDans la langue, Il y a une autre famille ——Famille de nombres flottants, Sont - ils stockés de la même manière que les données entières ? Si c'est différent, quel est le modèle? ? Passons maintenant à ces questions. .

Nombre de points flottants, Décimale , Utilisé pour représenter les différentes décimales de notre vie .Les nombres courants de points flottants sont:3.14159,1E10.La famille des nombres flottants comprend::float, double, long double.

Voici un exemple pour introduire le stockage de nombres flottants en mémoire :

#include <stdio.h>
int main()
{
    
	int n = 9;
	float* pFloat = (float*)&n;
	printf("nLa valeur de:%d\n", n);
	printf("*pFloatLa valeur de:%f\n", *pFloat);
	//
	*pFloat = 9.0;
	printf("nLa valeur de:%d\n", n);
	printf("*pFloatLa valeur de:%f\n", *pFloat);
	return 0;
}

Résultats des extrants:
Insérer la description de l'image ici
Nous pouvons tirer des conclusions de cet exemple : Les données entières et les données flottantes sont stockées et extraites différemment en mémoire , Qu'est - ce qui est différent? ? Pour explorer le mystère , Nous devons comprendre les règles de stockage des nombres flottants en mémoire :

Représentation du nombre de points flottants à l'intérieur de l'ordinateur
Interprétation détaillée:
Conformément aux normes internationalesIEEE(Institute of Electrical and Electronic Engineering) 754,N'importe quel nombre binaire de points flottantsVPeut être exprimé sous la forme suivante:: (-1)^S * M * 2^E

(-1)^S Représente un bit de symbole,QuandS=0,VEst un nombre positif;QuandS=1,VEst négatif.
M Indique un nombre valide(1≤M<2)
2^E Représente un bit exponentiel.

Par exemple, Comme décimal5.0,Sa représentation binaire est101.0,équivalent à1.01*2^2
D'après ce qui précèdeVReprésentation de,Ici.S=0,M=1.01,E=2
Comme décimal5.0,Sa représentation binaire est-101.0,équivalent à(-1)^1*1.01*2^2
D'après ce qui précèdeVReprésentation de,Ici.S=1,M=1.01,E=2

IEEE754Utilisation prévueS, E, M Trois chiffres pour n'importe quel nombre binaire flottant , Et en utilisant ces trois chiffres , Spécifie le mode de stockage du nombre de points flottants en mémoire :

Pour32Nombre de points flottants de bits,Le plus élevé1Les bits sont des bits symboliquess,C'est parti.8Les bits sont des indicesE,Le reste23Bit est un nombre valideM
Insérer la description de l'image ici
Pour64Nombre de points flottants de bits,Le plus élevé1Les bits sont des bits symboliquess,C'est parti.11Les bits sont des indicesE,Le reste52Bit est un nombre valideM
Insérer la description de l'image ici

IEEE754Pour les chiffres validesMEt indexE,Il existe également des dispositions spéciales
PourM

Comme je l'ai dit, 1≤M<2 ,C'est - à - dire,MPeut être écrit comme1.xxxxxxForme,Parmi euxxxxxxxReprésente la partie décimale.IEEE754Le règlement,Enregistrer à l'intérieur de l'ordinateurMHeure,Par défaut, le premier chiffre de ce nombre est toujours1,Pour qu'il puisse être abandonné.,Enregistrer uniquement les suivantsxxxxxxSection.Comme la préservation1.01Quand,Enregistrer seulement01,Attendez la lecture.,Encore une fois.1Ajouter.L'objet de cette action,- Oui.Économies1Nombre effectif de bits.Par32Exemple de nombre de points flottants,Laisse - le.MSeulement23Bits,Le premier1Après le départ,C'est l'équivalent de pouvoir enregistrer24Nombre effectif de bits.
(Note:: Lors du stockage des flotteurs ,SiM En premier. 1Après,Derrière.xxxxxx Insuffisance partielle 23Bits(Ou64Bits), À compléter 0 Jusqu'à ce que le nombre de chiffres soit suffisant )
Pour l'indiceE

Tout d'abord,,EEst un entier non signé(unsigned int) Cela signifie,SiEPour8Bits,Sa plage de valeurs est0~255;SiEPour11Bits,Sa plage de valeurs est0~2047.Mais,Nous savons que,Dans le comptage scientifiqueEPeut être négatif,Alors...IEEE754Le règlement,En mémoireELa valeur réelle de doit être ajoutée à un nombre intermédiaire,Pour8BitwiseE,Ce nombre moyen est127;Pour11BitwiseE,Ce nombre moyen est1023. Par exemple,,2^10DeE- Oui.10,Alors gardez - le.32Bit float,Doit être sauvegardé sous10+127=137,C'est - à - dire:10001001.


Et quand nous extrayons des nombres flottants de la mémoire, ,E Il y a trois autres situations .


1.EPas tout à fait.0Ou pas tous1

À ce stade, le nombre de points flottants est retiré selon les règles normales , Indice existant EMoins127(Ou1023)Je l'ai.EValeur réelle,Ensuite, les chiffres validesM La première place devant 1 Obtenir la vérité M.
Par exemple,:
Séquence binaire0 01111110 00000000000000000000000
Vous pouvez voir que cette séquence binaire a 32Bits, Est un nombre flottant de précision unique .
Première étape: Lire le premier chiffre SPour0, Le nombre de points flottants est un nombre positif .
Deuxième étape: Lisez les huit derniers chiffres du premier , Ces huit chiffres représentent le nombre moins 127Je l'ai.ELa vraie valeur deE = 01111110 - 01111111 = -1
Troisième étape: Lire le reste 23Bits,Voilà.23 Bit plus haut 1Je l'ai.M,EtM = 1.00000000000000000000000
Donc ce nombre est égal à (-1)^0 * 1.00000000000000000000000 * 2^(-1) = 0.1, Convertir en décimal est 0.5


2.ETout est0

À ce moment - là,,Indice du nombre de points flottantsEégal à1-127(Ou1-1023)Est la valeur réelle,Nombre effectifMPlus de premier1,Mais revenir à0.xxxxxxLa décimale de.C'est pour montrer±0,Et près de0Un petit nombre.


3.ETout est1

À ce moment - là,,Si un nombre valideMTout est0,Représentation±Infini(Plus ou moins dépend du BIT de symboles)



OK! Comprendre les règles de stockage du nombre de points flottants en mémoire , Revenons à l'exemple introduit au début ! Pourquoi y a - t - il des résultats inattendus ici ? Analysons - le étape par étape. ( Analyse en deux parties ):

//Exemples
#include <stdio.h>
int main()
{
    
    //Partie supérieure
	int n = 9;
	float* pFloat = (float*)&n;
	printf("nLa valeur de:%d\n", n);
	printf("*pFloatLa valeur de:%f\n", *pFloat);
	//Partie inférieure
	*pFloat = 9.0;
	printf("nLa valeur de:%d\n", n);
	printf("*pFloatLa valeur de:%f\n", *pFloat);
	return 0;
}

Partie supérieure:
Insérer la description de l'image ici
Insérer la description de l'image ici



Partie inférieure
Insérer la description de l'image iciInsérer la description de l'image ici

Nous pouvons donc conclure, L'impression est anormale parce que nous stockons et Récupérons les données différemment , Les résultats pourraient nous surprendre . Nous devons être prudents lors de l'écriture du Code ,Et la mémoire“ Faites affaire. ”,DiminutionbugL'apparition de~


Résumé

C'est la fin du partage d'aujourd'hui.!En cas d'erreur,Bienvenue, mon grand.~
J'aimerais partager une phrase que j'ai vue aujourd'hui. :Do what you love, love what you do.
C'est le sens de la vie de faire ce qu'on aime. !Allezxdm!
Si tu vois ça, donne - moi une triple compagnie. ~

原网站

版权声明
本文为[Superman ne peut pas voler, ke.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260533517337.html