Je suis un programmeur de départ Lecture de K & R, et je me sens comme si le livre suppose beaucoup de connaissances antérieures. Un aspect qui me confond est la représentation réelle, ou devrais-je dire l'existence, des variables en mémoire. Qu'est-ce qu'un type de données spécifie exactement pour une variable? Je ne suis pas sûr de la façon de verser cette question ... mais je vais poser quelques questions et peut-être que quelqu'un peut proposer une réponse cohérente pour moi. P>
Lors de l'utilisation de getchar (), on m'a dit qu'il est préférable d'utiliser le type "INT" que de type "caractère" en raison du fait que "INT" peut contenir plus de valeurs alors que "Char" ne peut contenir que 256 valeurs. Étant donné que nous devrions avoir besoin de la variable pour contenir la valeur EOF, nous aurons besoin de plus de 256 ou de la valeur EOF se chevauchent avec l'un des 256 caractères. Dans mon esprit, je considère cela comme une bande de boîtes avec des trous vides. Quelqu'un pourrait-il me donner une meilleure représentation? Est-ce que ces "cases" ont des nombres d'index? Lorsque EOF se chevauche avec une valeur dans les 256 valeurs disponibles, pouvons-nous prédire quelle valeur il se chevauchera avec? P>
En outre, cela signifie-t-il que le type de données "Char" est bien à utiliser lorsque nous attribuons simplement une valeur à une variable manuellement, telle que Char c = 'a', lorsque nous savons certainement que nous aurons seulement 256 caractères ASCII possibles? P>
En outre, quelle est la différence importante entre "char" et "int"? Si nous pouvons utiliser le type "INT" au lieu de type "caractère", pourquoi décidons-nous d'utiliser un sur l'autre à certains moments? Est-ce de sauvegarder la "mémoire" (j'utilise des citations comme je ne fais pas vraiment comment "mémoire" fonctionne exactement). P>
Enfin, comment sont exactement les 256 valeurs disponibles de type Char obtenues? J'ai lu quelque chose à propos de Modulo 2 ^ N, où n = 8, mais pourquoi cela fonctionne-t-il (quelque chose à voir avec binaire?). Quelle est la moyenne modulo de "modulo 2 ^ n" signifie (s'il a une pertinence pour l'arithmétique modulaire, je ne peux pas voir la relation ...)? P>
10 Réponses :
g'day, p>
aller plus profond, je recommanderais vivement le livre excellent de Charles Petzold " Code " P>
Il couvre plus que ce que vous demandez, tout cela conduit à une meilleure compréhension de ce qui se passe réellement sous les couvertures. P>
htth p>
Vraiment, les fichiers de données sont une abstraction permettant à votre langage de programmation de traiter quelques octets à une adresse comme une sorte de type numérique. Considérez le type de données comme objectif qui vous permet de voir un morceau de mémoire en tant qu'ob ou un flotteur. En réalité, tout est juste des bits à l'ordinateur. P>
Le OP encadré en termes de matériel, mais je suis d'accord avec vous; Les questions individuelles ont tous été mieux répondues avec une courte introduction à la théorie de type.
Un aspect qui me confond est le représentation réelle, ou devrais-je dire existence, de variables dans la mémoire. Que signifie exactement un type de données précise pour une variable? p> blockQuote>
Au niveau de la machine, la différence entre
int code> et
char code> est seulement la taille ou le nombre d'octets, de la mémoire allouée pour lui par le langage de programmation. En C, IIRC, un
char code> est un octet alors qu'un
int code> est de 4 octets. Si vous deviez « look » à ces intérieur de la machine elle-même, vous verriez une séquence de bits pour chacun. Être capable de les traiter comme
int code> ou
char code> dépend de la façon dont la langue décide de les interpréter (ce qui est aussi la raison pour laquelle il est possible de convertir dans les deux sens entre les deux types). p>
Lors de l'utilisation getchar (), on m'a dit que il est préférable de type d'utilisation « int » que type « char » en raison du fait que « int » peut contenir plusieurs valeurs alors peut « char » maintenir seulement 256 valeurs. p> blockQuote>
Ceci est parce qu'il y a 2 ^ 8, 256 ou des combinaisons de 8 bits (car un bit peut avoir deux valeurs possibles), alors il y a 2 ^ 32 combinaisons de 32 bits. La constante de EOF (tel que défini par C) est une valeur négative, ne tombant pas dans la plage de 0 et 255. Si vous essayer d'affecter cette valeur négative à un char (ce serrant ses 4 octets en 1), les bits d'ordre supérieur seront perdus et vous finirez avec une valeur char valide qui n'est pas le même que EOF. C'est la raison pour laquelle vous avez besoin de le stocker dans un int et vérifier avant de lancer en char. P>
En outre, ce que cela signifie que les données type « char » est seulement bien utiliser quand nous attribuons simplement une valeur à une variables manuellement, par exemple c = 0char « A », quand nous savons pertinemment que nous aura seulement 256 ASCII possible caractères? p> blockQuote>
Oui, d'autant plus que dans ce cas, vous assignez un littéral de caractères. P>
En outre, quel est l'importance réelle différence entre « char » et « int »? Si nous pouvons utiliser « int » de type au lieu de type « char », pourquoi nous décidons d'utiliser un sur l'autre à certains moments? p> blockQuote>
Plus important encore, vous choisirait
int code> ou
char code> au niveau de la langue selon que vous vouliez traiter la variable comme un numéro ou une lettre (à l'interrupteur, vous aurait besoin de caster l'autre type). Si vous voulez une valeur entière qui a moins de place, vous pouvez utiliser un
short int code> (qui je crois est de 2 octets), ou si vous étiez vraiment concernés par l'utilisation de la mémoire, vous pouvez utiliser un
omble chevalier code>, bien que la plupart du temps ce n'est pas nécessaire. p>
Modifier strong>: voici une lien décrivant les différents types de données en C et modificateurs qui peuvent leur être appliquées. Voir le tableau à la fin des tailles et des plages de valeurs. P>
Nitpick: Pour gérer des personnages, vous remporteriez l'enfer loin du charret et utilisez une abstraction de niveau supérieur d'une bibliothèque comme Glib.
Bien sûr, mais je pense toujours qu'il est important de comprendre ce qui se passe réellement aux niveaux inférieurs.
En C, un int code> peut être 4 octets, ou plus ou moins.
int code> doit pouvoir représenter des valeurs entre
-32767 code> et
+32767 code>.
int n'est pas nécessaire 4 octets. Tout ce qui dit: court <= int <= long et court> = 2 octets et longue> = 4 octets. Voir «Le langage de programmation C», la version ANSI C, par K & R, page 36.
De plus, en C, Char code> peut être signé, auquel cas il peut i> Store
EOF code>, mais bien sûr
char code> Peut-être aussi non signé, et c'est pourquoi nous utilisons
int code> dans ce cas.
Alok: Toutefois, si Char code> est signé, il ne peut pas stocker toutes les valeurs de retour valides de
getchar code> (qui sont soit
non signé Char code> valeurs code> non signé, ou
EOF code>), alors vous feriez mieux d'utiliser
int code>.
De grandes questions. K & R a été écrit dans les jours où il y avait beaucoup moins à connaître sur les ordinateurs, et les programmeurs savaient donc beaucoup plus sur le matériel. Chaque programmeur doit em> connaître ce genre de choses, mais (naturellement) de nombreux programmeurs de départ ne sont pas. P>
à l'Université Carnegie Mellon, ils ont développé un cours complet pour remplir cet écart dans la connaissance, ce que j'étais un TA pour. Je recommande le manuel pour cette classe: "Systèmes informatiques: perspective d'un programmeur" http://amzn.com/013034074x/ a> p>
Les réponses à vos questions sont plus longues que celles-ci peuvent vraiment être couvertes ici, mais je vous donnerai de brefs directeurs pour vos propres recherches. P>
Fondamentalement, les ordinateurs stockent toutes les informations - que ce soit dans la mémoire (RAM) ou sur le disque - en binaire, un système de numéros de base-2 (par opposition à la décimale, qui est la base 10). Un chiffre binaire est appelé un peu. Les ordinateurs ont tendance à travailler avec la mémoire dans des morceaux de 8 bits appelés octets. P>
Un char en C est un octet. Un Int est typiquement de quatre octets (bien qu'il puisse être différent sur différentes machines). Donc, un caractère ne peut contenir que 256 valeurs possibles, 2 ^ 8. Un int peut contenir 2 ^ 32 valeurs différentes. P>
Pour plus, lisez certainement le livre ou lisez quelques pages Wikipedia: P>
Bonne chance! P>
Merci! Pourriez-vous expliquer la partie "modulo" de 2 ^ n?
Je préférerais avoir déclaré "de retour dans l'époque où la programmation était un niveau plus faible, plus proche du matériel, alors l'apprentissage de la programmation est rapidement nécessaire (et abouti à) une bonne compréhension de base du matériel sous-jacent".
Singe logiciel: bien dit, je pense que c'est plus précis que ce que j'ai écrit.
Finchamicals: réponse mise à jour avec quelques informations sur l'arithmétique modulaire; J'espère que cela t'aides.
BTW, sur certaines plates-formes, il y a au moins un caractère dans le jeu de caractères C dont la valeur dépasse la valeur maximale d'un caractère signé. Par exemple, dans EBCDIC, '0' est 0xF0. Sur de telles machines, 'CHAR' doit être non signé. Sur certaines autres plates-formes (par exemple, des DSP), Tailleof (Char) == Tailleof (int), et les deux peuvent contenir des valeurs -32767..32767 (et peut-être d'autres valeurs également). Sur de telles machines, 'CHAR' doit être signé. Notez plus avant que sur ces machines, il serait possible que -1 soit une valeur de caractère valide et pour que l'EOF soit une valeur autre que -1.
Selon "STDIO.H", la valeur de retour de GetChars () est INT et EOF est définie comme -1. Selon le codage réel, toutes les valeurs comprises entre 0..255 peuvent survenir, il n'est pas suffisant de représenter le -1 et l'INT est utilisé. Voici une belle table avec des informations détaillées http://en.wikipedia.org/wiki/iso/ Iec_8859 p>
eof code> est un "petit nombre négatif". li>
- in c,
de caractères code> peut être non signé, ce qui signifie qu'il ne peut pas représenter des valeurs négatives. LI>
- Pour des types non signés, lorsque vous essayez d'attribuer une valeur négative, ils sont convertis en une valeur non signée. Si
max code> est la valeur maximale Un type non signé peut contenir, puis l'attribution -n code> à un tel type est équivalente à l'attribution de max - (n% max) + 1 code>. Ainsi, pour répondre à votre question spécifique sur la prédiction, "oui tu peux". Par exemple, disons char code> est non signé et peut contenir des valeurs 0 code> à 255 code> inclus. Ensuite, attribuer -1 code> à un caractère est équivalent à l'attribution de 255 - 1 + 1 = 255 code> à celui-ci. Li>
ul>
Compte tenu de ce qui précède, pour pouvoir stocker eof code> dans C code>, c code> ne peut pas être char code> taper. Ainsi, nous utilisons int code>, car il peut stocker "de petites valeurs négatives". En particulier, en C, int code> est garanti de stocker des valeurs dans la plage -32767 code> et +32767 code>. C'est pourquoi getchar () code> retourne int code>. P>
En outre, cela signifie-t-il que le type de données "Char" est bien à utiliser lorsque nous attribuons simplement une valeur à une variable manuellement, telle que Char c = 'a', lorsque nous savons certainement que nous aurons seulement 256 caractères ASCII possibles? P>
blockQuote>
Si vous attribuez des valeurs directement, la standard C garantit que les expressions telles que 'a' code> vont dans un char code>. Notez que dans C, 'a' code> est de type int code>, pas de caractère, mais il va bien faire char c = 'a' code>, car 'a' code> est capable d'installer dans un type char code>. p>
À propos de votre question sur la variable de type A devrait contenir, la réponse est la suivante: utilisez le type qui a du sens. Par exemple, si vous comptez ou cherchez des longueurs de chaîne, les chiffres ne peuvent être supérieurs ou égaux à zéro. Dans de tels cas, vous devez utiliser un type non signé. taille_t code> est un tel type. p>
Notez qu'il est parfois difficile de comprendre le type de données, et même les "avantages" peuvent faire des erreurs. GZIP code> Format Par exemple, stocke la taille des données non compressées dans les 4 derniers octets d'un fichier. Cela pause pour d'énormes fichiers> 4 Go de taille, qui sont assez communs de nos jours. P>
Vous devriez faire attention à votre terminologie. En C, un Char c = 'A' Code> attribue une valeur entière correspondant à 'A' code> à c code>, mais il n'est pas nécessaire de ne pas être ASCII. Cela dépend de tout votre codage à utiliser. P>
À propos de la partie "Modulo" et 256 valeurs de type Char code>: Si vous avez n code> binaires dans un type de données, chaque bit peut coder 2 valeurs: 0 et 1. Donc, vous avez 2 * 2 * 2 ... * 2 code> ( n code> fois) valeurs disponibles, ou 2 n sup>. Pour les types EM> non signés, tout trop-plein est bien défini, c'est comme si vous divisiez le nombre par (la valeur maximale possible + 1) et a pris le reste. Par exemple, disons non signé Char code> peut stocker des valeurs 0..255 code> (256 valeurs totales). Ensuite, attribuant 257 code> à un non signé le char code> la diviser essentiellement de 256, prenez le reste (1) et assignez la valeur à la variable. Cette relation est vraie pour des types non signés uniquement. Voir Ma réponse à une autre question Pour plus. P>
Enfin, vous pouvez utiliser des tableaux char code> pour lire des données à partir d'un fichier en C, même si vous pouvez finir par frapper EOF code>, car c fournit d'autres moyens de détecter < code> eof code> sans avoir à le lire dans une variable explicitement, mais vous en apprendrez plus tard lorsque vous avez lu sur les tableaux et les pointeurs (voir fgets () code> si vous êtes curieux pour un exemple). P>
La beauté de K & R est la concision et la lisibilité, les écrivains doivent toujours faire des concessions pour leurs objectifs; Plutôt que d'être un manuel de référence de 2000 pages, il sert de référence de base et d'un excellent moyen d'apprendre la langue en général. Je recommande Harbinson et Steele "C: un manuel de référence" pour un excellent livre de référence C pour plus de détails et la norme C bien sûr. P>
Vous devez être prêt à google cette affaire. Les variables sont représentées en mémoire à des endroits spécifiques et sont connues du programme dont elles font partie de la portée donnée. Un caractère sera généralement stocké dans 8 bits de mémoire (sur certaines plates-formes rares, ce n'est pas nécessairement vrai). 2 ^ 8 représente 256 positions distinctes pour les variables. Différents CPU / compilateurs / etc. représentent les types de base int, de longues tailles variables. Je pense que la norme C pourrait spécifier des tailles minimales pour ces tailles, mais pas maximales. Je pense que pour le double, il spécifie au moins 64 bits, mais cela n'empêche pas Intel d'utiliser 80 bits dans une unité à point flottante. Quoi qu'il en soit, des tailles typiques de la mémoire sur des plates-formes Intel 32 bits seraient de 32 bits (4 octets) pour Int et flotteur non signé, 64 bits (8 octets) pour double, 8 bits pour char (signé / non signé). Vous devriez également rechercher l'alignement de la mémoire si vous êtes vraiment intéressé par le sujet. Vous pouvez également utiliser exactement la mise en page de votre débogueur en obtenant l'adresse de votre variable avec l'opérateur "&", puis coupant cette adresse à cette adresse. Les plates-formes Intel peuvent vous confondre un peu lorsque vous regardez des valeurs en mémoire, alors veuillez rechercher le petit Endian / Big Endian. Je suis sûr que le débordement de la pile a également de bons résumés de cela. P>
Fondamentalement, la mémoire système est une énorme série de bits, chacun peut être soit "sur" ou "off". Le reste est des conventions et une interprétation. P>
Tout d'abord, il n'ya aucun moyen d'accéder directement aux bits individuels; Au lieu de cela, ils sont regroupés en octets, généralement en groupes de 8 (quelques systèmes exotiques sont pas le cas, mais vous pouvez l'ignorer pour l'instant), et chaque octet obtient une adresse mémoire. Donc, le premier octet en mémoire a une adresse 0, la seconde a l'adresse 1, etc. p>
Un octet de 8 bits a 2 ^ 8 valeurs différentes différentes, qui peuvent être interprétées comme un nombre compris entre 0 et 255 (octet non signé), ou en tant que nombre compris entre -128 et +127 (octet signé), ou en tant que Caractère ASCII. Une variable de type Mais les octets sont trop petits pour beaucoup de choses, d'autres types ont donc été définis qui sont plus grands (c'est-à-dire qu'ils consistent en plusieurs octets) et les CPU prennent en charge ces différents types via des constructions matérielles spéciales. Un une variable de type En tant que SidENOTE, la plupart des systèmes nécessitent des types plus importants pour être "alignés par mot", c'est-à-dire que leurs adresses doivent être multiples de la taille du mot, car cela facilite les choses pour le matériel. Il n'est donc pas possible d'avoir une variable int Démarrer à l'adresse 999, ou l'adresse 17 (mais 1000 et 16 sont ok). P> Char code> par standard C a une taille de 1 octet. P>
int code> est typiquement de 4 octets de nos jours (bien que la norme C ne le spécifie pas et que les INT ne puissent être plus petits ou plus importants sur différents systèmes) car 4 octets sont 32 bits, et jusqu'à récemment ce que les processeurs traditionnels sont supportés. comme leur "taille de mot". p>
int code> est de 4 octets grand. Cela signifie que lorsque son adresse mémoire est par exemple. 1000, alors il couvre en fait les octets aux adresses 1000, 1001, 1002 et 1003. En C, il est possible de répondre à ces octets individuels également à la fois, et c'est la manière dont les variables peuvent se chevaucher. P>
Encore une fois, int code> peut être 4 octets ou 2 ou même 1, ou quoi que ce soit. Il doit être capable de représenter la plage + -32767.
ne serait-il pas 2 ^ 7 et pas 2 ^ 8?
@Alok, oui c'est ce que je dis un paragraphe plus élevé. @Roboto: Nope. 8 bits signifie 2 ^ 8 valeurs différentes. Un bit a 2 valeurs (2 ^ 1), chaque bit supplémentaire double ceci.
Je ne vais pas vraiment répondre à votre question, mais je voudrais vous aider à comprendre les variables, car j'avais les mêmes problèmes de les comprendre, lorsque j'ai commencé à programmer moi-même.
Pour le moment, Don ' T Touche avec la représentation électronique des variables en mémoire. Pensez à la mémoire comme un bloc continu de cellules 1 octet, chacun stockant un motif de bit (composé de 0s et 1s). P>
En regardant uniquement la mémoire, vous ne pouvez pas déterminer, quel Les bits y sont représentés! Ce ne sont que des séquences arbitraires de 0 et 1s. C'est vous, qui spécifie, comment interpréter ces modèles de bits! Jetez un oeil à cet exemple: p> Vous auriez pu écrire ce qui suit aussi: p> dans les deux cas, Les variables A, B et C sont stockées quelque part dans la mémoire (et vous ne pouvez pas raconter leur type). Maintenant, lorsque le compilateur compilait votre code (qui traduit votre programme dans les instructions de la machine), il s'assure, de traduire le "+" en INTEGER_ADD dans le premier cas et float_add dans le second cas, la CPU interprétera ainsi les modèles de bits Correctement et exécuter, ce que vous avez souhaité. p>
Tous les caractères nécessaires dans une langue sont resprustés par ASCII et ASCII étendu. Donc, il n'y a pas de caractère au-delà de l'ASCII étendu. P>
Tout en utilisant de l'utilisation de caractères, il est probable que la valeur des ordures puisse stocker directement le caractère mais en utilisant INT, il y a moins de probabilité qu'elle stocke la valeur ASCII du caractère. p>
"Quand nous savons certainement que nous n'aurons que 256 caractères ASCII possibles?" NIT-Pick: Il n'y a que 128 caractères en ASCII.
Il y a plus que "INT" .. Il n'y a pas non signé INT (0-65535) et signé INT (-32767 à 32767) ... Un caractère ordinaire dans la plupart des implémentations est de 0 à 255 dans un non signé. Vous avez également court et long. Court est deux octets, INT est de 4 octets et de 8 octets est de 8 octets. Voyez ici: home.att.net/~jackklein/c/inttypes.html a>
Désolé: S. S puis pourrais-je demander pourquoi nous ne pouvons pas utiliser les 256 valeurs disponibles du type "CHAR" si nous utilisons également la fonction getchar () et attendez-vous un EOF à un moment donné?
Vous êtes dans un moment intéressant. Je veux dire qu'en cas de sarcasme, juste des encouragements. Il y a beaucoup de choses très intéressantes devant vous sur cette route. Comme Rob l'a mentionné ci-dessous, obtenez le livre de Petzold et lisez-le. Profitez de l'apprentissage!
@withchemicals: car Int peut également être char et charrette retournera sur 0 s'il est non signé (valeur supérieure à 255)
Finchamique: parce que "CHAR" n'implique pas vraiment "ASCII". En C, "Char" implique "la plus petite pièce de mémoire adressable", autrement appelée "octet". getchar () vous donne simplement un octet d'un ruisseau (ou EOF).
Beaucoup de réponses ci-dessous assument la représentation des nombres de deux deux. C ne fait aucune garantie de ce type. Il peut courir (et fonctionne) sur des machines de complément et des machines de signalisation (ou tout autre coding étrange qu'il y a!).