Stockage des données en langage C en mémoire

Table des matières

avant-propos

Contenu de ce numéro

1. Introduction des types de données

1.1 Signification des types :

1.2 Existe-t-il un type chaîne en langage C ?

1.3 Classification de base des types

Famille d'entiers :

Famille à virgule flottante (réelle) :

Types de construction (personnalisés) :

Type de pointeur :

type vide :

Deuxièmement, le stockage des nombres entiers en mémoire

2.1 Code original, code inverse, code complément

Résumer:

2.2 Introduction à l'ordre des octets gros et petit endian

2.3 Qu'est-ce que le gros et le petit endian ?

2.4 Pourquoi y a-t-il des gros et des petits bouts ?

 4. Explication détaillée de plusieurs questions de test écrit

Détails sur les entiers non signés :

5. Stockage détaillé des nombres à virgule flottante en mémoire

Règles de stockage des nombres à virgule flottante


avant-propos

Nous avons appris les types de données du langage C au début, y compris les entiers, les virgules flottantes, les caractères, etc., mais nous ne semblons pas comprendre comment ils sont stockés dans la mémoire, et lorsque nous avons examiné la mémoire auparavant, nous avons constaté que les données qu'elle contenait étaient stockées à l'envers. Dans ce numéro, l'éditeur vous amène à bien comprendre les règles de stockage des données en mémoire !

Contenu de ce numéro

1. Introduction détaillée des types de données

2. Stockage d'entiers en mémoire

3. Introduction et jugement de l'ordre des octets gros et petit endian

4. Explication détaillée de plusieurs questions de test écrit

5. Stockage détaillé des nombres à virgule flottante en mémoire

1. Introduction des types de données

Nous avons déjà appris que les types de données de base des données sont des types intégrés (inclus dans le langage C) comme suit :

char type de caractère 1 octet

entier court court 2 octets

int entier 4 octets

long entier long 4/8 octets

long long plus long entier 8 octets

float Type virgule flottante simple précision 4 octets

double Type à virgule flottante double précision 8 octets

Il faut noter ici que le type caractère (char) occupe 1 octet en langage C, mais peut ne pas occuper un octet dans d'autres langages, comme 2 octets en java ! (Nous savons qu'un caractère chinois fait deux octets. En java, les variables de type char peuvent être utilisées pour stocker le genre !)

De plus, long occupe 4/8 octets car la norme du langage C stipule uniquement que la plage de taille de long est :

sizeof(int) <= sizeof(long) <= sizeof(long long) La taille spécifique dépend du compilateur

Voulez-vous la signification d'un tel type de données ici ? N'utilisons-nous pas simplement des entiers et des décimaux dans la vie quotidienne ? Il veut vraiment dire quelque chose !

1.1 Signification des types :

L'ordinateur est différent de la vie, l'ordinateur doit gérer beaucoup de données. Le type détermine son domaine d'utilisation (la taille qui peut être ouverte et accessible) et comment traiter cet espace !

Par exemple : l'autorité d'accès (taille) d'un type entier est de 4 octets et l'autorité d'accès d'un type de caractère est de 1 octet. Si vous stockez un nombre à virgule flottante dans un type entier et que vous ne le forcez pas, cela vous donnera une erreur et la précision sera perdue. Cela montre que les types sont différents.

1.2 Existe-t-il un type chaîne en langage C ?

La réponse est non! Dans le dernier numéro, nous venons de dire que les chaînes en langage C sont stockées dans des tableaux de caractères ou que les chaînes constantes sont stockées dans des pointeurs de caractères (l'adresse du premier élément de la chaîne) !

1.3 Classification de base des types

Famille d'entiers :

caractère non signé caractère signé

court non signé court signé

entier entier non signé entier signé

long non signé long signé long

long long non signé long long signé long long

Ici, vous devez vous demander pourquoi char est classé dans la famille des entiers ?

En fait, lorsque le type de caractère est stocké, il stocke essentiellement la valeur ASCII correspondante, qui est essentiellement un nombre ! Il appartient donc à la famille des entiers !

De plus, les types généraux sont signés, si vous voulez faire du non signé, il faut ajouter du non signé !

Famille à virgule flottante (réelle) :

flotter

double

Types de construction (personnalisés) :

Type de tableau : type [const num] ;

Type de structure : structure

Type d'énumération : enum

Type de syndicat (public): syndicat

Certains amis peuvent ne pas connaître le type de tableau ici, supprimez le nom du tableau pour obtenir le type de tableau ! D'autres structures, dénombrements et syndicats seront introduits dans les prochains numéros !

Type de pointeur :

entier *p ;

caractère *pc ;

flottant *pf ;

vide * pv;

Ceux-ci ont été évoqués dans les deux numéros précédents, donc je n'en dirai pas plus ici, la seule chose à laquelle il faut faire attention est : le pointeur void*, il peut recevoir n'importe quel type de pointeur, et le forcer à ce dont vous avez besoin lors de son utilisation !

type vide :

void représente un type vide (comme une valeur de retour)

Habituellement utilisé pour les valeurs de retour de fonction, les paramètres de fonction, etc. !

Notez qu'il n'y a pas de valeur de retour ici : vous n'avez pas besoin de revenir, si vous devez revenir, vous pouvez l'écrire comme ceci : return ;

Deuxièmement, le stockage des nombres entiers en mémoire

Nous avons introduit que la création d'une variable nécessite d'ouvrir de l'espace en mémoire, et la taille de l'espace est déterminée par son type ! Mais comment les données sont-elles stockées dans la mémoire après l'ouverture de l'espace ? Découvrons ensemble ci-dessous !

2.1 Code original, code inverse, code complément

Les nombres entiers dans les ordinateurs sont stockés sous forme binaire, et il existe trois représentations binaires : originale, inverse et complémentaire !

Les trois méthodes de représentation binaire sont composées de deux parties, le bit de signe et le bit de valeur ! Le bit le plus élevé est le bit de signe et les bits restants sont des bits de valeur ! Le bit de signe est 0 pour positif et 1 pour négatif !

L'original, l'inverse et le complément des entiers positifs (nombres non signés) sont les mêmes !

Les trois formes d'entiers négatifs n'ont pas besoin d'être calculées :

Code original : la traduction directe du décimal en binaire est le code original !

Code négatif : le bit de signe reste inchangé et les autres bits sont inversés petit à petit !

Code complémentaire : ajoutez 1 au code inverse pour compléter le code !

Prenez une châtaigne :

Jusqu'à présent, nous savons que les entiers sont stockés sous forme binaire en mémoire, et nous comprenons également les trois formes de binaire ! Alors, quel type de binaire est stocké en mémoire ? Lorsque nous avons présenté les opérateurs plus tôt, les opérateurs liés aux bits opèrent sur le code de complément à 2. Nous supposons que le code de complément à 2 correspondant sera stocké ? Vérifions-le avec une châtaigne :

int main()
{
	int a = -1;
	return 0;
}

Nous savons que le code d'origine, le code inverse et le code complémentaire des entiers positifs sont tous identiques. Qu'est-ce qui est stocké exactement ? Alors testons avec des nombres négatifs ! On sait que le complément de -1 est 32 1, il suffit donc de vérifier si tous les 1 sont stockés en mémoire, et comme la valeur de la mémoire est en hexadécimal, on sait que 1 chiffre hexadécimal équivaut à 4 chiffres binaires, c'est-à-dire si le résultat en mémoire est : ff ff ff ff, cela signifie que le code stocké est le code complément, sinon c'est le code original !

Effectivement, le code complémentaire est enregistré ! Cette châtaigne montre également que les données stockées dans la mémoire sont du code complémentaire, et que le code d'origine est utilisé lors de l'impression !

Nous avons appris plus haut que les entiers sont stockés sous forme de code complément dans la mémoire, alors est-ce calculé dans le code d'origine ou le code complément ? Voici une châtaigne pour le prouver :


int main()
{
	int a = -3;
	int b = 5;
	int c = a + b;
	return 0;
}

En supposant que le code d'origine est stocké pour le calcul :

C'est évidemment déraisonnable ! Par conséquent, il est exclu que le code d'origine soit utilisé pour le calcul !

En supposant qu'il est stocké en complément à deux pour le calcul :

Le résultat est correct ! Ainsi, les données sont calculées et exploitées dans leur complément à deux ! 

Résumer:

En fait, dans le système informatique, toutes les valeurs sont représentées et stockées en code complémentaire. La raison en est qu'en utilisant le code complémentaire, le bit de signe et le bit de valeur peuvent être traités de manière uniforme. En même temps, l'addition et la soustraction peuvent également être traitées de manière uniforme (le processeur n'a qu'un additionneur). De plus, le code complémentaire et le code d'origine sont convertis l'un à l'autre. Le processus de fonctionnement est le même et aucun circuit matériel supplémentaire n'est requis !

Cela explique tous les problèmes ci-dessus! De plus, faites attention à cette phrase : "Le code complémentaire et le code d'origine sont convertis l'un à l'autre, et le processus de fonctionnement est le même, aucun circuit matériel supplémentaire n'est nécessaire !" Que signifie cette phrase ? On sait : Les entiers négatifs doivent être inversés du code original vers le code complément (le bit de signe reste inchangé et les autres bits sont inversés) + 1. Du code complément au code original, il faut soustraire 1 puis l'inverser ! Cette phrase introduit en fait une autre méthode : du code original au code complément, il faut inverser + 1, et du code complément au code original, on peut aussi prendre la méthode + 1 ;

Fais un dessin pour comprendre :

2.2 Introduction à l'ordre des octets gros et petit endian

Lorsque nous avons observé la mémoire, nous avons constaté que les données sont stockées à l'envers :

Par exemple:


int main()
{
	int a = 15;
	return 0;
}

Le binaire de 15 est 00000000 00000000 00000000 00001111 converti en hexadécimal est 00 00 00 0f Il va de soi que la mémoire doit être stockée dans cet ordre !

Regardez la mémoire:

La mémoire est juste placée à l'envers, pourquoi est-ce? En fait, il s'agit d'un problème d'ordre des octets du gros et du petit endian ! Introduisons ce qu'est l'ordre des octets gros et petit endian ! 

Ordre des octets : discutez de la forme de stockage des données en unités d'octets !

2.3 Qu'est-ce que le gros et le petit endian ?

Mode Big Endian (stockage) : les données de poids faible sont stockées dans des adresses hautes, et les données de poids fort sont stockées dans des adresses basses !

Mode Little-endian (stockage) : les données de faible poids sont enregistrées dans des adresses basses, et les données de poids fort sont enregistrées dans des adresses hautes !

D'ACCORD! Fais un dessin pour comprendre :

Notre machine est en mode stockage little-endian !

2.4 Pourquoi y a-t-il des gros et des petits bouts ?

En effet, dans le système informatique, nous utilisons les octets comme unité, chaque unité d'adresse correspond à un octet, et un octet est de 8 bits, mais dans le langage C, en plus du caractère 8 bits, il existe des types courts 16 bits, int 32 bits ou long (voir le compilateur pour plus de détails). Par conséquent, l'ordre des octets gros et petit endian est produit !

Je ne sais pas si vous comprenez ce que j'ai dit ci-dessus, mais ici je vais le trier pour vous en langue vernaculaire :

C'est-à-dire que vous pouvez enregistrer la valeur d'une variable d'octet comme vous le souhaitez, sans ordre ! Mais le stockage de plus d'un octet a un problème d'ordre ! Par exemple:

Afin d'être facile à retirer après le stockage, il est donc laissé à la fin.Les deux ci-dessus sont les grandes et les petites extrémités. Les deux suivants sont jetés en raison d'un stockage irrégulier !

Jusqu'à présent, je dois introduire une question de test écrite pour les ingénieurs système de Baidu en 2015 :

Veuillez décrire brièvement les concepts de big-endian et little-endian, et concevoir un programme pour déterminer si la machine actuelle est big-endian ou little-endian.

Le concept ici n'est pas présenté, juste terminé dessus ! L'accent est mis ici sur la deuxième question : comment déterminer s'il s'agit d'un big endian ou d'un little endian ?

Il y a deux manières de compiler une question ici : 1. Pointer 2. Joint. L'éditeur suivant présentera ces deux méthodes :

int check_sys()
{
	int i = 1;
	//return (*(char*)&i) & 1;
	return (*(char*)&i);
}

int main()
{
	if (check_sys() == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

	return 0;
}

Ce code doit être compréhensible ! Regardons-en un autre :

int check_sys()
{
	union
	{
		int i;
		char c;
	}un;//创建了一个联合体对象un,他有两个成员,一个是int i和char c;
	un.i = 1;
	return un.c;
}

int main()
{
	if (check_sys() == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

	return 0;
}

Ce que je veux dire ici, c'est : la taille du syndicat est la taille de son plus grand membre ! Ici aussi int i ; les variables membres combinées ne peuvent pas être utilisées en même temps, renvoie ici la valeur de char c, si c'est en petit boutiste, c'est 1, sinon c'est 0 ; faites un dessin pour expliquer :

Peu importe si vous ne comprenez pas ici, je le présenterai dans un certain numéro plus tard !

Regardez les deux résultats :

Ceci est cohérent avec ce que nous avons présenté ci-dessus !

 4. Explication détaillée de plusieurs questions de test écrit

(1)

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;
}

Pensez-y d'abord, quelle est la réponse à cette question?

Regardez le résultat :

Je ne sais pas si c'est la même chose que ce que vous pensez ? L'éditeur vous amènera à analyser :

On a dit avant a et b : char == char signé

 Si vous ne comprenez pas l'amélioration du plastique ici, jetez un œil à cet article que j'ai écrit auparavant :

Amélioration de la mise en forme du langage C http://t.csdn.cn/bCGN6 Analysons ce c :

(2)

int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}

Pensez-y d'abord, quelle est la réponse à cette question?

Regardez le résultat :

Cette question est susceptible d'être répondue pendant un moment, donc je vais l'expliquer:

 

(3) 


int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

Quelle est la réponse à cette question ?

Regardez le résultat :

Il devrait être très facile de faire cette question après avoir terminé la dernière, et vous n'avez pas besoin de l'analyser étape par étape comme ça ! Celui qui y est stocké est le même que celui stocké dans -128 ci-dessus et tous sont imprimés sous la forme %u, donc le résultat devrait être le même !

(4)

int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	return 0;
}

Quelle est la réponse à cette question ?

Regardez le résultat :

 analyser:

 (5)

int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}

Quel est le résultat de ce code ?

Jetez un œil aux résultats :

Oui, il est dans une boucle sans fin, pourquoi ? Laissez-moi l'analyser pour vous :

En fait, la raison est très simple : i est un nombre non signé, qui est toujours supérieur ou égal à 0. La condition de jugement de boucle ici est >=0, donc c'est toujours vrai ! Vous êtes donc pris dans une boucle sans fin de profit ! Mais pourquoi continuer à en imprimer un si grand nombre ? Ici nous allons en parler en détail, entier non signé !

Détails sur les entiers non signés :

Nous savons que si l'entier n'est pas ajouté non signé sur VS, il sera signé (signé) par défaut. Quelle est la plage que chaque type peut représenter ? On dirait que nous n'avons pas encore été présentés ! L'éditeur suivant présente en détail la gamme de représentations signées et non signées !

char        occupe un octet (8 bits, le bit le plus élevé est le bit de signe), donc la plage de sa valeur positive est

               0 ~ 2 ^ 7 - 1 = 0 ~ 127

               La valeur du nombre négatif est -1 ~ -2 ^ 7 = - 1 ~ -128, la plage de valeurs de multicha est : -2 ^ 7 -- 2 ^ 7 - 1

Qu'en est-il du caractère non signé ? Puisque le bit le plus élevé n'est plus un bit de signe mais un bit de valeur, sa plage est 0~2^8-1

short         occupe deux octets (16 bits, le bit le plus élevé est le bit de signe), donc la plage de sa valeur positive est

                0 ~ 2 ^ 15 - 1

                La valeur négative est -1 ~ -2 ^ 15, donc la plage de valeurs est : -2 ^ 15 -- 2 ^ 15 - 1

Qu'en est-il de l'unsishort ? Puisque le bit le plus élevé n'est plus un bit de signe mais un bit de valeur, sa plage est 0~2^16 -1 ;

La méthode d'analyse dans d'autres familles d'entiers est la même que cette méthode d'analyse, int -2^31~2^31-1 ; unsigned int est 0~2^31-1 ; ici, je ne vais pas les énumérer un par un ! Laissez-moi vous expliquer pourquoi il en est ainsi ! Prenons char comme exemple (les autres sont pareils) :

caractère signé :

Lorsque vous comprenez cela, vous pouvez regarder une telle image:

 caractère non signé :

Sachant cela, vous pouvez expliquer pourquoi la question ci-dessus imprime un grand nombre après une boucle infinie !

Parce que i est un type int non signé qui est toujours supérieur ou égal à 0, lorsqu'il est égal à 0 puis moins 1, il devient la valeur maximale de int non signé de plus de quatre milliards ! Alors la boucle a été réduite et a été supérieure ou égale à 0 ! Il en va de même pour les deuxième et troisième questions ci-dessus !

(6)

#include<string.h>
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d ", strlen(a));
	return 0;
}

Un regard de plus sur ce code et il va exploser ! Quel est le résultat de la réflexion sur l'exécution ?

Voyons ensemble :

255 Il doit y avoir beaucoup de gens qui ne s'y attendaient pas ! Lorsque l'éditeur a fait cette mention pour la première fois, son cuir chevelu était engourdi par Xiu ! Haha, permettez-moi de l'analyser ci-dessous:

Quand a[i] vaut 0, le caractère correspondant est '\0'. Nous savons que strlen calcule le contenu avant \0. Il y a 127+128=255 éléments dans le tableau avant, donc c'est 255. Cette question n'est-elle pas très délicate ! Ha ha !

(7) 

unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

Quel est le résultat de cette question ? réfléchis un peu !

Regardez le résultat :

La boucle infinie de cette mention devrait être facile à comprendre ! Je ne ferai aucun dessin ici ! unsigned char est toujours inférieur ou égal à 255) donc c'est une boucle infinie !

5. Stockage détaillé des nombres à virgule flottante en mémoire

Nombres à virgule flottante courants :

3.14

1E10 ----->1.0 * 10 ^10

Nous avons introduit la famille des nombres à virgule flottante : float et double et long double

Comment les nombres à virgule flottante sont-ils stockés en mémoire ? Discutons ensemble, regardons d'abord une châtaigne :


int main()
{
	int n = 9;
	float* pf = (float*)&n;
	printf("n = %d\n", n);
	printf("*pf = %f\n", *pf);

	*pf = 9.0;
	printf("num = %d\n", n);
	printf("*pf = %f\n", *pf);

	return 0;
}

Pensez-y encore, quel est selon vous le résultat de ce code ?

Regardez le résultat :

Je suppose que le premier et le dernier sont ce que vous pensez! Les deux autres sont différents. Il est évident que num et *pf sont le même nombre, pourquoi sont-ils imprimés différemment ? Pourquoi ? Pour résoudre ce problème, il faut parler des règles de stockage des nombres à virgule flottante en mémoire !

Règles de stockage des nombres à virgule flottante

Selon la norme internationale IEEE (Institute of Electrical and Electronics Engineering) 754, tout nombre binaire à virgule flottante V peut être exprimé sous la forme suivante :

1. (-1)^S*M*2^E

2. (-1)^ S représente le bit de signe, quand S = 0, V est un nombre positif, quand S = 1, V est un nombre négatif ;

3. M représente un nombre valide, supérieur ou égal à 1 et inférieur à 2 ;

4. 2 ^ E représente l'exposant

Qu'est-ce que cela signifie? Laissez-moi faire un dessin pour comprendre intuitivement :

D'ACCORD! Prenez une châtaigne :

int main()
{
	float f = 5.5;
	return 0;
}

Nous pouvons utiliser la norme ci-dessus pour pratiquer :

IEEE754 stipule :

Pour les nombres à virgule flottante 32 bits (float), le bit le plus élevé est le bit de signe S, les 8 bits suivants sont l'exposant E et les 23 bits restants sont des chiffres significatifs !

Pour les nombres à virgule flottante 64 bits (double), le plus élevé est le bit de signe S, le 1 suivant est l'exposant E et les 52 bits restants sont des chiffres valides !

IEEE754 a également des réglementations spéciales sur le nombre effectif M et l'exposant E :

Nous avons dit précédemment : 1 =< M < 2, c'est-à-dire que M peut s'écrire sous la forme 1.xxxxxxxx, où xxxxx représente la partie décimale !

IEEE754 stipule : Lorsque l'ordinateur enregistre M, le premier chiffre de ce nombre est toujours 1 par défaut, il peut donc être ignoré, et seul le xxxxx suivant (par exemple : 1.01 enregistre uniquement 01) est ajouté à 1 lorsqu'il est utilisé (lecture). Agrandit la gamme de stockage ! (les nombres à virgule flottante 64 bits sont les mêmes)

Quant à l'indice E, la situation est plus compliquée :

Remarque : IEEE754 considère E comme un entier non signé (unsigned int) :

Cela signifie que si E est de 8 bits, sa plage de valeurs est : 0~255, si E est de 11 bits, sa plage de valeurs est : 0~2047

Mais nous savons que l'exposant peut en fait être négatif ! Mais maintenant E est non signé, c'est-à-dire qu'il est toujours supérieur ou égal à 0, donc pour résoudre ce problème, IEEE754 stipule qu'un nombre intermédiaire doit être ajouté à la valeur réelle de E lorsqu'il est stocké en mémoire ! Pour le E 8 bits, le nombre du milieu est 127, mais pour le E 11 bits, le nombre du milieu est 1023 !

Par exemple : le E de 2^10 est 10, lorsque vous l'enregistrez (en supposant 32 bits), vous devez l'enregistrer sous la forme 10+127=137, soit : 10001001

Alors il y a trois situations où E est lu :

(1) E n'est pas tout à 0 ou pas tout à 1

À ce moment, le nombre à virgule flottante est représenté par les règles suivantes, c'est-à-dire que la valeur calculée de l'exposant E est soustraite de 127/1023 pour obtenir la valeur réelle, puis 1 est ajouté au premier chiffre devant le nombre effectif M ;

Par exemple : 0,5 (32 bits à titre d'exemple)

La valeur binaire de 0,5 est : 0,1 Puisque la partie positive doit être 1, elle peut s'écrire : 1,0 * 2^-1,

Lors de l'enregistrement, E=-1 est : -1+127=126 (cela devient un nombre positif), c'est-à-dire 01111110, et le 1 de 1,0 est omis lors de l'enregistrement et ajouté lors de son utilisation ! Ainsi, seul 0 est stocké, et le bit avec 23 bits plus 1 a 24 bits, alors remplissez-le ! 00000000 00000000 00000000 00000000

Voici comment il est stocké en mémoire :

0 0111110 000000000000000000000000

Lorsque vous lisez, 126 (01111110)-127 obtiendra le vrai E! De la même manière, l'ajout de 1 devant les chiffres effectifs à l'arrière est le vrai chiffre effectif, et il peut être restauré !

Vérifiez-le :

0 01111110 00000000000000000000000 A ce moment, le bit binaire, la mémoire est en hexadécimal, on le change en hexadécimal :

0011 1111 0000 0000 0000 0000 0000 0000-------"3f 00 00 00, et nous avons vérifié que la machine actuelle est en mode little-endian, donc elle est sauvegardée à l'envers ! c'est-à-dire 00 00 00 3f

Jetez un œil aux résultats :

Exactement la même chose, cela montre que notre ci-dessus est tout à fait correct ! 

(2) E est tout 0

A ce moment, l'exposant E du nombre à virgule flottante est égal à 1-127/1-1023, qui est la valeur réelle, et le nombre effectif M ne s'ajoute plus au premier 1, mais est restitué à une décimale de 0,xxxxxx, ceci pour représenter +/-0 et les très petits nombres proches de 0 !

Voici une explication : lorsque vous trouvez que E est tout à 0 lorsque vous le prenez, cela signifie que la valeur réelle qui y est stockée doit être -127/-1023, c'est-à-dire qu'elle est sous cette forme :

C'est un très, très petit nombre qui est presque proche de 0, donc peu importe si le 1 devant M est ajouté ou non ! 

(3) E est tout 1

A ce moment, le nombre effectif M est tout 0, ce qui signifie infini positif et négatif (positif ou négatif dépend de S);

Cette situation est aussi assez particulière, quand je l'ai prise, j'ai trouvé que c'était tout 1, c'est-à-dire 255 (1023), c'est-à-dire que la valeur réelle lors de l'épargne était de 255-127/2047-1023 et 2^128/2^1024 est un très grand nombre ! Nous comprenons comme l'infini!

Avec l'introduction ici, on peut expliquer la question juste au dessus !

D'ACCORD! Bons frères, c'est la fin de ce partage ! À la prochaine! 

Je suppose que tu aimes

Origine blog.csdn.net/m0_75256358/article/details/131806769
conseillé
Classement