Question

Je voudrais savoir architectures qui violent les hypothèses J'ai énuméré ci-dessous. De plus, je voudrais savoir si l'une des hypothèses sont fausses pour toutes les architectures (qui est, si l'un d'entre eux sont tout simplement complètement faux).

  1. sizeof (int *) == sizeof (char *) == sizeof (void *) == sizeof (func_ptr *)

  2. La représentation en mémoire de tous les pointeurs pour une architecture donnée est la même quel que soit le type de données pointé.

  3. La représentation en mémoire d'un pointeur est identique à un nombre entier de la même longueur de bits que l'architecture.

  4. et la division des multiplication des types de données de pointeur ne sont interdites par le compilateur. REMARQUE: Oui, je sais que cela est absurde. Ce que je veux dire est - est-il un soutien matériel pour interdire cette utilisation incorrecte

  5. Toutes les valeurs de pointeur peuvent être coulés à un seul nombre entier. En d'autres termes, quelles architectures utilisent encore des segments et des compensations?

  6. incrémentation d'un pointeur est équivalent à l'ajout d'sizeof(the pointed data type) à l'adresse de mémoire mémorisée par le pointeur. Si p est un int32* alors p+1 est égale à l'adresse mémoire 4 octets après p.

Je suis le plus utilisé pour les pointeurs utilisés dans un espace de mémoire virtuelle contiguë,. Pour cette utilisation, je peux généralement obtenir en pensant à eux comme adresses sur une ligne numérique. Voir la question Stack Overflow comparaison pointeur .

Était-ce utile?

La solution

Je ne peux pas vous donner des exemples concrets de tout cela, mais je ferai de mon mieux.

sizeof(int *) == sizeof(char *) == sizeof(void *) == sizeof(func_ptr *)

Je ne sais pas de tout système où je sais que cela est faux, mais pensez:

Les appareils mobiles ont souvent une certaine quantité de mémoire en lecture seule dans lequel le code de programme et tel est stocké. Valeurs en lecture seule (variables const) peuvent éventuellement être stockées dans la mémoire en lecture seule. Et puisque l'espace d'adressage ROM peut être inférieure à l'espace d'adressage de la RAM normale, la taille du pointeur peut être différent aussi bien. De même, des pointeurs vers des fonctions peuvent avoir une taille différente, car ils peuvent pointer vers cette mémoire en lecture seule dans lequel le programme est chargé, et qui peuvent par ailleurs pas être modifiés (en si vos données ne peuvent être stockées).

Je ne connais pas de plates-formes sur lesquelles j'ai observé que le ne tient pas au-dessus, mais je peux imaginer des systèmes où il pourrait être le cas.

  

La représentation en mémoire de tous les pointeurs pour une architecture donnée est la même quel que soit le type de données pointé.

Pensez pointeurs membres vs pointeurs réguliers. Ils ne sont pas la même représentation (ou la taille). Un pointeur d'élément est constitué d'un pointeur de this et un décalage.

Et comme ci-dessus, il est concevable que chargerait données constantes certaines unités centrales dans une zone séparée de la mémoire, qui a utilisé un format de pointeur distinct.

  

Le pointeur d'une représentation en mémoire est identique à un nombre entier de la même longueur de bits que l'architecture.

Cela dépend de la façon dont cette longueur de bit est défini. :) Un int sur plusieurs plates-formes 64 bits est toujours 32 bits. Mais un pointeur est de 64 bits. Comme nous l'avons dit, CPU avec un modèle de mémoire segmentée aura des pointeurs constitués d'une paire de nombres. De même, les pointeurs membres consistent en une paire de nombres.

  

et la division des multiplication des types de données de pointeur ne sont interdites par le compilateur.

En fin de compte, les pointeurs types de données uniquement existent dans le compilateur. Ce que le CPU fonctionne avec des pointeurs n'est pas, mais les entiers et les adresses mémoire. Donc, il n'y a nulle part ailleurs où ces opérations sur les types de pointeur peut être interdits. Vous pourriez aussi bien demander la CPU d'interdire concaténation des objets chaîne de C. Il ne peut pas le faire parce que le type de chaîne C de existe seulement dans le langage C ++, pas dans le code machine généré.

Cependant, pour répondre à ce que vous signifie , regardez les processeurs Motorola 68000. Je crois qu'ils ont des registres séparés pour les entiers et les adresses mémoire. Ce qui signifie qu'ils peuvent facilement interdire ces opérations insensées.

  

Toutes les valeurs de pointeur peuvent être casté en un seul entier.

Vous êtes en sécurité. Les normes C et C ++ garantissent que cela est toujours possible, peu importe la mise en page de l'espace mémoire, l'architecture du processeur et toute autre chose. Plus précisément, ils garantissent une cartographie de mise en œuvre définies . En d'autres termes, vous pouvez toujours convertir un pointeur vers un entier, puis convertir cet entier en arrière pour obtenir le pointeur d'origine. Mais les langues C / C ++ ne disent rien sur ce que devrait être la valeur entière intermédiaire. C'est au compilateur individuel, et le matériel qu'il cible.

  

incrémentation d'un pointeur est équivalent à l'ajout de sizeof (le type de données pointu) à l'adresse de mémoire mémorisée par le pointeur.

Encore une fois, cela est garanti. Si l'on considère que le plan conceptuel, un pointeur ne pointe pas vers une adresse, il pointe un objet , cela est parfaitement logique. Ajout d'un au pointeur fera alors évidemment pointer vers suivant objet. Si un objet est de 20 octets, incrémenter le pointeur se déplacer 20 octets, de sorte qu'il se déplace à l'objet suivant .

Si un pointeur était simplement une adresse mémoire dans un espace d'adressage linéaire, si elle était essentiellement un entier, incrémenter alors il seraitajouter 1 à l'adresse - à savoir, il passer à la suivante octet

.

Enfin, comme je l'ai mentionné dans un commentaire à votre question, gardez à l'esprit que C ++ est juste une langue. Il ne se soucie pas que l'architecture, il est compilé. Un grand nombre de ces limites peut sembler obscur CPU moderne de. Mais si vous ciblez CPU d'antan de? Que faire si vous ciblez de la prochaine décennie de CPU? Vous ne savez même pas comment ils vont travailler, de sorte que vous ne pouvez pas assumer beaucoup sur eux. Que faire si vous ciblez une machine virtuelle? Compilateurs existent déjà qui génèrent bytecode pour Flash, prêt à fonctionner à partir d'un site Web. Que faire si vous voulez compiler C ++ au code source Python?

Rester dans les règles spécifiées dans les garanties standard que votre code fonctionnera dans tous ces cas.

Autres conseils

Je n'ai pas d'exemples spécifiques du monde réel à l'esprit, mais la « autorité » est la norme C. Si quelque chose ne l'exige pas la norme, vous pouvez construire une mise en œuvre conforme qui ne volontairement se conformer à toutes les autres hypothèses. Certaines de ces hypothèse sont vraies la plupart du temps juste parce qu'il est pratique de mettre en œuvre un pointeur comme un entier représentant une adresse de mémoire qui peut être directement téléchargée par le processeur, mais cela est juste une conséquence de « commodité » et ne peut pas être tenue comme une vérité universelle.

  1. Non requis par la norme ( voir cette question ). Par exemple, sizeof(int*) peut être inégale à size(double*). void* est garanti pour être en mesure de stocker une valeur de pointeur.
  2. Non requis par la norme. Par définition, la taille est une partie de la représentation. Si la taille peut être différente, la représentation peut être différent aussi.
  3. Pas nécessairement. En fait, « la longueur binaire d'une architecture » est une déclaration vague. Qu'est-ce qu'un processeur 64 bits, vraiment? Est-ce le bus d'adresse? Taille des registres? Bus de données? Quoi?
  4. Il n'a pas de sens de « multiplier » ou « diviser » un pointeur. Il est interdit par le compilateur mais vous pouvez de multiplier ou diviser la représentation sous-jacente bien sûr (ce qui ne fait pas vraiment de sens pour moi) et qui se traduit par un comportement non défini.
  5. Peut-être que je ne comprends pas votre point, mais tout dans un ordinateur numérique est tout simplement une sorte de nombre binaire.
  6. Oui; genre de. Il est garanti pour pointer vers un endroit qui est un sizeof(pointer_type) plus loin. Ce n'est pas nécessairement équivalent à l'addition arithmétique d'un nombre (par exemple plus est un concept logique ici. La représentation réelle est une architecture spécifique)

Pour 6 .: un pointeur est pas nécessairement une adresse mémoire. Voir par exemple « Le grand pointeur Conspiracy » Stack utilisateur overflow jalf :

  

Oui, je le mot « adresse » dans le commentaire ci-dessus. Il est important de comprendre ce que je veux dire par là. Je ne veux pas dire « l'adresse mémoire à laquelle les données sont stockées physiquement », mais simplement un résumé « tout ce dont nous avons besoin afin de localiser la valeur. L'adresse de la i est peut-être quelque chose, mais une fois que nous l'avons, nous pouvons toujours trouver et modifier i. »

  

Un pointeur est pas une adresse de mémoire! Je l'ai mentionné ci-dessus, mais disons encore. Pointeurs sont généralement mis en œuvre par le compilateur simplement que les adresses mémoire, oui, mais ils ne doivent pas être. "

Certains plus d'informations sur les pointeurs de la norme C99:

  • 6.2.5 §27 garantit que void* et char* ont des représentations identiques, à savoir qu'ils peuvent être utilisés sans conversion interchangeable, soit la même adresse est indiquée par le même motif de bits (qui ne doit pas être vrai pour d'autres types de pointeur )
  • 6.3.2.3 §1 prévoit que tout pointeur vers un type incomplet ou d'un objet peut être coulée à (et de) void* et retour et être toujours valide; cela ne comprend pas les pointeurs de fonction!
  • 6.3.2.3 §6 indique que void* peut être coulée à (et de) entiers et 7.18.1.4 §1 fournit des types apropriate intptr_t et uintptr_t; le problème: ces types sont en option - la norme mentionne explicitement qu'il n'a pas besoin d'être un type entier assez grand pour contenir réellement la valeur du pointeur

sizeof(char*) != sizeof(void(*)(void)? - Pas sur x86 en 36 bits mode d'adressage (pris en charge sur à peu près tous les CPU Intel depuis le Pentium 1)

« Le pointeur d'une représentation en mémoire est identique à un nombre entier de la même longueur de bit » - il n'y a pas de représentation en mémoire sur une architecture moderne; mémoire marquée n'a jamais pris sur et était déjà obsolète avant C a été normalisée. Mémoire en fait ne tient même pas des entiers, et sans doute seulement des bits mots (pas d'octets. La plupart mémoire physique ne vous permet pas de lire seulement 8 bits)

"La multiplication des pointeurs est impossible" - 68000 famille; registres d'adresses (les titulaires des pointeurs) ne prennent pas en charge que IIRC.

"Tous les pointeurs peuvent être coulés en entiers" -. Pas sur PICs

« incrémenter T * équivaut à ajouter sizeof (T) à l'adresse de mémoire » - vraie par définition. En outre équivalent à &pointer[1].

Je ne sais pas pour les autres, mais pour DOS, l'hypothèse de # 3 est faux. DOS est 16 bits et utilise différentes astuces pour carte beaucoup plus de 16 bits d'une valeur de la mémoire.

  

Le pointeur d'une représentation en mémoire est identique à un nombre entier de la même longueur de bits que l'architecture.

Je pense que cette hypothèse est fausse parce que le 80186, par exemple, un pointeur 32 bits est maintenu dans deux registres (un registre à décalage d'un registre de segment), et qui demi-mot est allé dans lequel registre des questions lors de l'accès.

  

et la division des multiplication des types de données de pointeur ne sont interdites par le compilateur.

Vous ne pouvez pas multiplier ou diviser les types. ; P

Je ne suis pas sûr pourquoi vous voulez multiplier ou diviser un pointeur.

  

Toutes les valeurs de pointeur peuvent être casté en un seul entier. En d'autres termes, quelles architectures utilisent encore des segments et des compensations?

Le standard C99 permet pointeurs à stocker dans intptr_t, qui est un type entier. Alors, oui.

  

incrémentation d'un pointeur est équivalent à l'ajout de sizeof (le type de données pointu) à l'adresse de mémoire mémorisée par le pointeur. Si p est un int32 * alors p + 1 est égale à l'adresse mémoire 4 octets après p.

x + yx est un T * et y est un entier est equivilent à (T *)((intptr_t)x + y * sizeof(T)) autant que je sache. L'alignement peut être un problème, mais le rembourrage peut être fourni dans le sizeof. Je ne suis pas vraiment sûr.

En général, la réponse à toutes les questions est « oui », et c'est parce que les machines qui mettent en œuvre des langues populaires ont vu directement la lumière du jour et ont persisté dans le siècle actuel. Bien que les normes linguistiques se réservent le droit de modifier ces « invariants », ou affirmations, il n'a jamais passé dans des produits réels, à l'exception possible des articles 3 et 4, qui nécessitent un certain retraitement universellement vrai.

Il est certainement possible de construire des conceptions MMU segmentés, qui correspondent à peu près avec les architectures fondés sur les capacités qui étaient populaires sur le plan scolaire au cours des années passées, mais pas un tel système a généralement vu l'usage commun avec ces fonctions activées. Un tel système pourrait avoir en contradiction avec les affirmations qu'il aurait probablement eu de grands pointeurs.

En plus segmentée / capacité MMU, qui ont souvent de grands pointeurs, des conceptions plus extrêmes ont essayé de coder les types de données dans des pointeurs. Peu d'entre eux ont été jamais construit. (Cette question soulève toutes les alternatives à la base orientée mot, un pointeur-est-un-mot architectures.)

Plus précisément:

  1. La représentation de tous les pointeurs pour une architecture donnée en mémoire est le même quel que soit le type de données pointé. True à l'exception des conceptions passées extrêmement loufoques qui a essayé de mettre en œuvre une protection non dans les langues fortement typés, mais dans le matériel.
  2. La représentation en mémoire d'un pointeur est identique à un nombre entier de la même longueur de bits que l'architecture. Peut-être, certainement une sorte de type intégral est le même, voir LP64 vs LLP64 .
  3. et la division de la multiplication des types de données de pointeur ne sont interdites par le compilateur. droit .
  4. Toutes les valeurs de pointeur peuvent être casté en un seul entier. En d'autres termes, quelles architectures utilisent encore des segments et des compensations? Rien utilise des segments et des compensations aujourd'hui, mais un C int est souvent pas assez grand, vous devrez peut-être un ou long long long pour tenir un pointeur.
  5. incrémentation d'un pointeur est équivalent à l'ajout de sizeof (le type de données pointu) à l'adresse de mémoire mémorisée par le pointeur. Si p est un int32 * alors p + 1 est égale à l'adresse de la mémoire 4 octets après p. Oui.

Il est intéressant de noter que chaque CPU Intel Architecture, à savoir, chaque peecee, contient une unité de segmentation élaborée de l'épopée, le légendaire, la complexité. Cependant, il est effectivement désactivé. Chaque fois qu'un des bottes de système d'exploitation de PC vers le haut, il fixe les bases de segments à 0 et les longueurs de segments à ~ 0, annulant ainsi les segments et donnant un modèle de mémoire plat.

Il y avait beaucoup de « mot adressé » architectures dans les années 1950, 1960 et 1970. Mais je ne me souviens pas des exemples traditionnels qui ont un compilateur C. Je me rappelle la ICL / Trois-Rivières PERQ machines dans les années 1980 qui a été adressée et mot eu une écriture la mémoire de commande (microcode). L'un de ses instanciations avait un compilateur C et un goût d'Unix appelé PNX , mais le compilateur C nécessaire microcode spécial.

Le problème de base est que char * types sur mot machines traitées sont difficiles, mais vous les mettre en œuvre. Vous souvent avec sizeof(int *) != sizeof(char *) ...

Il est intéressant, avant C il y avait une langue appelée BCPL dans lequel le type de pointeur de base était une adresse de mot; qui est, incrémenter un pointeur vous a donné l'adresse du mot suivant, et ptr!1 vous a donné la parole à ptr + 1. Il y avait un autre opérateur pour adresser un octet. ptr%42 si je me souviens

EDIT: Ne pas répondre à des questions lorsque votre taux de sucre sanguin est faible. Votre cerveau (certainement, le mien) ne fonctionne pas comme prévu. :-(

nitpick mineur:

p est un int32 * alors p + 1

est faux, il doit être int32 non signé, sinon il se terminera à 2 Go.

bizarrerie intéressant - je suis arrivé ce de l'auteur du compilateur C pour la puce Transputer - il m'a dit que pour ce compilateur, NULL a été défini comme -2GB. Pourquoi? Parce que le Transputer avait une plage d'adresses signée: -2GB à + 2 Go. Pouvez-vous beleive cela? Incroyable non?

Je l'ai depuis rencontré plusieurs personnes qui me ont dit que la définition de NULL comme ça est cassé. Je suis d'accord, mais si vous ne vous finissez pas pointeurs NULL étant au milieu de votre plage d'adresses.

Je pense que la plupart d'entre nous peut être heureux que nous ne travaillons pas sur Transputers!

  

Je voudrais savoir architectures qui violent les hypothèses que j'ai   ci-dessous.

Je vois que Stephen C mentionné machines PERQ et MSalters mentionné 68000 et PICs.

Je suis déçu que personne ne répondait autre en fait la question en nommant l'une des architectures étranges et merveilleuses qui ont des normes conformes aux compilateurs C qui ne correspondent pas à certaines hypothèses injustifiées.

  

sizeof (int *) == sizeof (char *) == sizeof (void *) == sizeof (func_ptr   *)?

Pas nécessairement. Voici quelques exemples:

La plupart des compilateurs pour Harvard-architecture processeurs 8 bits - PIC et 8051 et M8C - faire sizeof (int *) == sizeof (char *), mais différent du sizeof (func_ptr *).

Certains des très petites puces dans ces familles ont 256 octets de RAM (ou moins), mais plusieurs kilo-octets de PROGMEM (Flash ou ROM), de sorte que les compilateurs font souvent sizeof (int *) == sizeof (char *) égal à 1 (un seul octet de 8 bits), mais sizeof (func_ptr *) égal à 2 (deux octets de 8 bits).

Compilateurs pour la plupart des puces plus grandes dans ces familles avec quelques kilo-octets de RAM et 128 ou si kilo-octets de PROGMEM font sizeof (int *) == sizeof (char *) égal à 2 (deux octets de 8 bits), mais sizeof (func_ptr *) égal à 3 (trois octets de 8 bits).

Quelques puces d'architecture Harvard peuvent stocker exactement une pleine 2 ^ 16 ( "64 Ko") de PROGMEM (Flash ou ROM), et un autre 2 ^ 16 ( "64 Ko") de RAM + mémoire mappée E / S. Les compilateurs pour une telle marque de puce sizeof (func_ptr *) toujours être 2 (deux octets); mais ont souvent un moyen de rendre les autres types de pointeurs sizeof (int *) == sizeof (char *) == sizeof (void *) en aa "long ptr" pointeur générique 3 octets qui a le bit magique supplémentaire qui indique si que les points de pointeur en RAM ou PROGMEM. (C'est le genre de pointeur que vous devez passer à une fonction « print_text_to_the_LCD () » lorsque vous appelez cette fonction de différents sous-programmes, parfois avec l'adresse d'une variable chaîne dans un tampon qui pourrait être n'importe où dans la RAM, et d'autres fois avec un de nombreuses chaînes constantes qui pourraient être partout dans PROGMEM). Ces compilateurs ont souvent des mots-clés spéciaux ( « court » ou « proche », « long » ou « loin ») pour laisser les programmeurs indiquent spécifiquement trois différents types de pointeurs type char dans le même programme - chaînes constantes qui ne nécessitent 2 octets pour indiquer où en PROGMEM ils se trouvent, les chaînes non constantes qui ne nécessitent 2 octets pour indiquer où dans la RAM ils se trouvent, et le genre de pointeurs de 3 octets que « print_text_to_the_LCD () » accepte.

La plupart des ordinateurs construits dans les années 1950 et 1960 utilisent un longueur de mot 36 bits ou longueur de mot de 18 bits , avec un bus d'adresses de 18 bits (ou moins). J'entends que les compilateurs C pour ces ordinateurs utilisent souvent 9 bits octets , avec sizeof (int *) == sizeof (func_ptr *) = 2 ce qui donne 18 bits, étant donné que tous les nombres entiers et les fonctions doivent être alignées mot; mais sizeof (char *) == sizeof (void *) == 4 pour profiter de PDP- spécial qui stockent ces pointeurs dans un mot de 36 bits complet. Ce mot complet 36 bits comprend une adresse de mot 18 bits, et un peu plus de bits dans les autres 18 bits qui (entre autres) indiquent la position binaire du pointu à caractère dans ce mot.

  

La représentation en mémoire de tous les pointeurs pour une architecture donnée   est le même quel que soit le type de données pointée?

Pas nécessairement. Voici quelques exemples:

Sur une des architectures je l'ai mentionné unBove, pointeurs viennent dans différentes tailles. Alors, comment auraient-ils pu « même » représentation?

Certains compilateurs sur certains systèmes utilisent « descripteurs » pour mettre en œuvre des pointeurs de caractères et d'autres types de pointeurs . Un tel descripteur est différent pour un pointeur vers le premier « char » dans un « char big_array[4000] » que pour un pointeur vers le premier « char » dans un « char small_array[10] », qui sont sans doute différents types de données , même si le petit tableau qui arrive à commencer exactement le même emplacement en mémoire précédemment occupé par le grand tableau. Descripteurs permettent à ces machines pour attraper et piéger les dépassements de tampon qui causent ces problèmes sur d'autres machines.

Le "Pointeurs Low-Fat" utilisé dans le Safelite et similaires « soft processeurs » ont analogue « informations supplémentaires » de la taille de la mémoire tampon que les points de pointeur en. pointeurs faibles en gras ont le même avantage de la capture et le piégeage des dépassements de tampon.

  

Le pointeur d'une représentation en mémoire est identique à un nombre entier de   la même longueur de bits que l'architecture?

Pas nécessairement. Voici quelques exemples:

"l'architecture tagged" machines, chaque mot de la mémoire a quelques bits qui indiquent que ce mot est un entier, ou un pointeur, ou autre chose. Avec ces machines, en regardant les bits de tag vous dira si ce mot était un entier ou un pointeur.

J'entends que Nova ont un mini-ordinateurs « bit indirection » href="http://en.wikipedia.org/wiki/addressing_mode#Memory_indirect" de chaque mot qui a inspiré . Cela ressemble à stocker un nombre entier efface ce bit, tout en stockant un pointeur définit ce bit.

  

et la division des multiplication des types de données de pointeur ne sont interdites   par le compilateur. REMARQUE: Oui, je sais que cela est absurde. Ce que je veux dire est   - est-il un soutien matériel pour interdire cette utilisation incorrecte

Oui, un peu de matériel ne supporte pas directement ces opérations.

Comme d'autres l'ont déjà dit, l'instruction « multiplier » dans le 68000 et 6809 ne fonctionnent avec (certains) « registres de données »; ils ne peuvent pas être appliquées directement aux valeurs dans le « registres ». (Il serait assez facile pour un compilateur pour contourner ces restrictions - au format MOV ces valeurs à partir d'un registre d'adresse au registre de données appropriées, puis utilisez MUL).

  

Toutes les valeurs de pointeur peuvent être casté en un seul type de données?

Oui.

memcpy () pour travailler droite, les mandats standard de C que chaque valeur de pointeur de chaque type peut être coulé à un pointeur nul ( « void * »).

Le compilateur est nécessaire pour faire ce travail, même pour les architectures qui utilisent encore des segments et des décalages.

  

Toutes les valeurs de pointeur peuvent être casté en un seul entier? En d'autres termes,   quelles architectures utilisent encore des segments et des compensations?

Je ne suis pas sûr.

Je soupçonne que toutes les valeurs de pointeur peuvent être lancés à la « size_t » et « ptrdiff_t » types de données intégrales définies dans « <stddef.h> ».

  

incrémentation d'un pointeur est équivalent à l'ajout de sizeof (les données pointu   Type) à l'adresse de mémoire mémorisée par le pointeur. Si p est un int32 *   alors p + 1 est égale à l'adresse de mémoire de 4 octets après p.

On ne sait pas ce que vous demandez ici.

Q: Si je possède un réseau d'une certaine structure ou un type de données primitive (par exemple, un « #include <stdint.h> ... int32_t example_array[1000]; ... »), et incrémenter iun pointeur qui pointe dans cette matrice (par exemple, "int32_t p = & example_array [99]; ... p ++; ..."), fait le point pointer maintenant le lendemain élément consécutive de cette matrice, qui est sizeof ( le type de données pointu) octets plus loin dans la mémoire?

A: Oui, le compilateur doit faire le pointeur, après incrémentant une fois, le point à la prochaine int32_t consécutive indépendante dans le tableau, sizeof (le type de données en pointe) octets plus loin dans la mémoire, afin d'être conforme aux standards.

Q: Ainsi, si p est un int32 *, alors p + 1 est égale à l'adresse de mémoire de 4 octets après p

A: Quand sizeof (int32_t) est en fait égal à 4, oui. Dans le cas contraire, comme pour certaines machines de mots adressables, y compris certains DSPs modernes où sizeof (int32_t) peut être égal à 2 ou même 1, alors p + 1 est égale à l'adresse de mémoire 2 ou même 1 « C octets » après p.

Q: Donc, si je prends le pointeur, et de le jeter dans un "int" ...

A:. Un type de "une hérésie VAX de tous le monde"

Q: ... puis jeté que "int" de nouveau dans un pointeur ...

A:. Un autre type de "Tout le monde est une hérésie VAX"

Q: Donc, si je prends le pointeur p qui est un pointeur vers un int32_t, et de le jeter dans un certain type intégral qui est assez grande pour contenir le pointeur, puis ajoutez sizeof( int32_t ) à ce type intégral, puis plus tard coulé ce type intégral de nouveau dans un pointeur - quand je fais tout cela, le pointeur résultant est égal à p + 1

?

Pas nécessairement.

Beaucoup de quelques DSPs et d'autres puces modernes ont orienté mot adressage, plutôt que le traitement orienté octet utilisé par des puces 8 bits.

Certains des compilateurs C pour ces puces fourrer 2 caractères dans chaque mot, mais il faut 2 ces mots pour tenir une int32_t - ils signalent que sizeof( int32_t ) est 4. (Je l'ai entendu des rumeurs selon lesquelles il y a un compilateur C pour 24 bits de Motorola 56000 qui fait cela).

Le compilateur est nécessaire pour arranger les choses telles que faire « p ++ » avec un pointeur vers un int32_t incrémente le pointeur sur la prochaine valeur int32_t. Il existe plusieurs façons pour le compilateur de le faire.

Une façon conforme aux normes est de stocker chaque pointeur vers une int32_t comme une « adresse de mot indigène ». Parce qu'il faut 2 mots pour tenir une seule valeur int32_t, le compilateur C compile « int32_t * p; ... p++ » dans un langage d'assemblage qui incrémente la valeur de pointeur de 2. D'autre part, si celui-ci ne « int32_t * p; ... int x = (int)p; x += sizeof( int32_t ); p = (int32_t *)x; », ce compilateur C pour le 56000 établira probablement à langage assembleur qui incrémente la valeur du pointeur par 4.

  

Je suis le plus utilisé pour les pointeurs utilisés dans une mémoire virtuelle contiguë,   l'espace.

Plusieurs PIC et 8086 et d'autres systèmes ont RAM non contigus - quelques blocs de RAM à des adresses « fait le matériel plus simple ». Avec E / S de mémoire mappée ou rien du tout attaché aux lacunes dans l'espace d'adressage entre ces blocs.

Il est encore plus gênant que cela puisse paraître.

Dans certains cas - comme le matériel baguage bits utilisé pour éviter les problèmes causés par lecture-modification-écriture - le même bit exact dans la RAM peut être lu ou écrit en utilisant 2 ou plusieurs adresses différentes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top