si une interface de conteneur déclarer des pointeurs sur le contenu contenu
éléments tels que Tâche: Concevoir un conteneur en C (Remarque: Ceci est explicitement sur le CLAIR C,
pas em> à propos de C ++, ni C #). Le conteneur doit être nourri avec des pointeurs vers
articles, et devrait renvoyer des pointeurs à des éléments. P> Un MWe quelque peu inutile, mais l'idée s'étend aux conteneurs utiles comme
Eh bien: p> jusqu'à présent, si bon. p> Eh bien, le conteneur ne doit pas utiliser les pointeurs pour modifier la version stockée.
Les données. J'aimerais rendre cela clair dans l'interface, par un petit
Changement: p> const code>?
return (void *)c->data;
4 Réponses :
Cela signifie que si l'utilisateur souhaite modifier votre contenu de données, vous pourrez le faire. Mais l'adresse restera la même chose. P>
Cependant, tout le monde est libre de définir leur pointeur à une adresse. Vous ne pouvez pas empêcher cela. P>
Pour plus d'informations, consultez Ce lien (le livre C - Const et volatils) Chapitre 8.4.1. P> const * code> signifie que vous pouvez accéder et modifier les données de cette adresse mais ne peut pas modifier l'adresse que vous pointez. P>
const * code> n'est pas un type valide, laissant-moi incertain ce que l'on entend, mais cette réponse semble dirigée dans la mauvaise direction. Par exemple, les deux
const char * code> et
chartons * code> sont (modifiables) des pointeurs non modifiables
char code>. Si vous voulez que le pointeur i> soit non modifiable, alors c'est orthographié
char * cons code>.
vous avez raison. Dire const * je suppose que tout le monde voit ce que je voulais dire.
Comme je l'ai dit, I I> Je ne savais pas ce que vous vouliez dire. Je ne fais toujours pas, d'ailleurs. Je pourrais déduire que vous parlez de pointeurs non modifiables si cela était en fait pertinent pour la question, mais ce n'est pas le cas.
Ce n'est pas correct. Dans const * code>, le
const code> ne fait jamais référence au
* code>. Vous voulez dire
* const code>.
Si vous voulez la Constitution du pointeur Y em>, la bonne façon serait la suivante: Si vous voulez détenir ce que vous points sur em>, alors, comme vous l'avez mentionné:
const int * y = get (& c); code> p>
C'est vrai, mais cela ne répond pas à la question.
Un type de conteneur est juste que - un conteneur. Il permet à l'utilisateur d'ajouter / supprimer / accéder à l'élément contenu. Ce que l'utilisateur fait avec elle est à l'utilisateur. P>
Si vous voulez toujours un pointeur à constante, votre 2e approche est ce qui fonctionne mieux. Mais si un utilisateur peut lancer const, le code du conteneur peut ainsi que la promesse de ne pas modifier les données est peu profonde. P>
Notez également que votre conteneur stocke le pointeur à vide. Que ce soit-il est une indication forte pour l'utilisateur que le code du conteneur ne peut pas faire grand chose parce qu'il n'a aucune idée du type de données que le pointeur pointera. Oui, il peut toujours écrire des ordures à cet emplacement de la mémoire. P>
étant donné que le const ne garantit pas la constante de qualité I.e. Le compilateur peut ne pas placer les données de Const dans une mémoire en lecture seule, l'utilisateur du code de conteneur peut toujours tenter d'utiliser Const. Maintenant, il est possible que les données de Cons-ce puissent réellement se retrouver dans une mémoire en lecture seule ou que l'utilisateur puisse fournir le conteneur l'adresse d'une mémoire en lecture seule. Autrement dit, l'utilisateur a assuré qu'aucun code ne peut modifier les données constantes. Dans ce cas, vous n'avez pas à vous soucier de définir un pointeur à des données constantes. Si l'utilisateur a vérifié que les données ne peuvent pas être faites en lecture seule, il peut toujours ajouter des trucs comme CRC aux données. De cette façon, quand il / il saisit les données S / il peut vérifier si les données sont fiables ou non. P>
résumer strong>: si vous avez un pointeur à vide, ce qui en fait un pointeur pour Const Void est un peu inutile. En outre, il appartient à l'utilisateur de protéger ses données. Une structure de données ne devrait se soucier que de son objectif. P>
Votre interface fait un contrat, c'est-à-dire que l'objet qui est transmis ne sera jamais modifié à travers cet accès. Donc, en substance, vous auriez besoin de deux types de conteneurs, ou plus généralement d'interfaces, qui suppose que l'objet est mutable (a C'est un problème qui se produit dans de nombreux endroits, même dans la bibliothèque C. E.g Votre problème de stockage de la valeur puis de le reproduire à un endroit complètement indépendant dans le code ne peut pas être évité. Les normes C et POSIX ont ce problème pour Void * code> version) et celui qui suppose qu'il peut être modifié (un
VOID Const * code> version. P>
MemChR code> est une telle interface qui en silence une conversion de
const code> de l'objet. Cette trahison directe pourrait être contournée dans le C moderne C avec
_generic code>. P>
tss_set / tss_get code> et
pthread_setspecific / pthread_getspecific code> et résolvez le problème de manière incompatible. La variante C a
void * code> pour les deux, la variante POSIX a
void const * code> pour régler et
vide * code> pour obtenir. P>
Je ne serais pas d'accord pour dire que j'ai besoin de deux interfaces, voir ma réponse au commentaire de John Bollinger à ma question. Mais je choisis cette réponse, car il décrit le mieux le problème, et que C const code> ne fournit pas de solution, bien mis avec "stocker la valeur, puis la reproduise à un endroit complètement indépendant"
" ... dans le code ne peut pas. i>" Err, ne peut pas savoir quoi s'il vous plaît? " ... Soyez contourné ... I>"?
@alk, oui, c'était l'idée. J'ai essayé de clarifier, maintenant.
Étant donné que
y code> n'est pas
const code>, vous pouvez modifier les octets, c'est pourquoi le compilateur se plaint.
y = (int *) get (& c); code> si vous faites cela, quel est le bénéfice du
const code>?
Oui je sais. Je comprends complètement pourquoi le compilateur se plaint. Avantage de l'utilisation de
Const code> est Twofold: 1: promis à la bibliothèque utilisateur i> que le conteneur ne modifiera pas les données. 2: Make Compiler Warn Bibliothèque MiseidLor i> À propos de la modification accidentelle des données gérées par le compilateur.
Et puis pourquoi voulez-vous une référence de const code> Const code>?
Je suis désolé, peut-être que c'est parce que ma pauvre connaissances anglaise, mais je ne comprends pas il ne devrait pas arriver à l'intérieur du conteneur! I> Que voulez-vous dire avec ça? Est-ce que vous ne voulez pas qu'il ait accès aux membres code> struct code>?
Il n'y a aucun moyen de sortir de cela, mais de casser le
const code> lorsque vous renvoyez
data code> par le getter ou dumping l'idée d'utiliser
const code> du tout . J'irais pour ce dernier.
Veuillez ne pas appeler vos types
quelque chose_t code>. Le suffixe
_t code> est réservé par POSIX pour ses types.
Le qualificatif
const code> d'un paramètre de fonction doit être interprété comme décrit le type acceptable de l'argument correspondant. C'est pas b> la même chose que ce que la fonction fera avec l'argument, bien que les deux sont lâchées. Si votre conteneur doit stocker des objets modifiables (et les renvoyer sans qualification de type ajouté), votre
Met () code> ne doit pas
const code> -qualifier ses paramètres.
Étant donné que seuls les pointeurs sont manipulés, la valeur de données d'origine doit toujours exister lorsque le pointeur est récupéré. Cependant, ce pointeur peut être constitué, car le pointeur des données est constitué. Toutefois, dans l'ensemble, le conteneur ne contient pas les données, seul un pointeur vers les données, IMO: si les données d'origine sont toujours disponibles, le conteneur pour un pointeur sur ces données est inutile.
Corrigez mon commentaire précédent: car l'utilisateur de la bibliothèque souhaite toujours modifier les données. Il faut juste modifier pas b> par le conteneur! - Désolé, tapé-toi
@John Bollinger: Une ligne de pensée intéressante, je suis sûr que je suis d'accord, bien que:
f (const int *) code> soit appliqué à une classe d'arguments plus large, tandis que
f (int * ) code> ne peut pas être appliqué aux arguments de type
const int * code>. Donc, omettre
const code> signifierait que la fonction demande la modification des données transmises?
@stefan no, omettre
const code> signifierait uniquement que la fonction n'accepte pas
const code> arguments. Il ne dit toujours rien de ce que la fonction fera avec ses arguments. Cette question même met en évidence la différence: les éléments du conteneur peuvent inclure des données
const code> ou non, et cela doit être reflété dans les signatures des fonctions de getter d'élément et de réglage. Qu'un conteneur qui puisse contenir des données
const code> peut aussi i> détenir non-
const code> est hors de propos.
@John Bollinger: Je ne sais pas que je comprenne l'intention derrière deux interfaces: une pour
const code> données, une pour non
const code> data, est-ce que c'est? Mais dans ce cas, j'avais également besoin de deux types "distincts" pour le conteneur, afin de vous assurer que seules les fonctions correspondantes (const ou non-const) sont utilisées avec le conteneur. En outre, seule l'interface avec
Const code> communiquerait à l'utilisateur que le conteneur ne fera pas violer les données.
@stefan, pour complète
const code> -Correcness Vous avez besoin non seulement d'interfaces distinctes, mais des structures de données distinctes. Il s'agit de la nature du conteneur. Si vous dessinez un élément d'un conteneur pouvant contenir des éléments
const code>, il est possible que cet élément est (destiné à être)
const code>. C'est ce que
const code> -qualifiant la fonction getter indique. Si un élément particulier réellement est i>
const code> n'est pas très pertinent, car il n'y a aucun moyen dans C pour transmettre ces informations sur une base d'éléments par éléments.