web-dev-qa-db-fra.com

pointeur constant vs pointeur sur une valeur constante

Quelle est la différence entre les déclarations suivantes?

char * const a;
const char * a;

Afin de comprendre la différence, j'ai écrit ce petit programme:

#include <stdio.h>
#include <stdlib.h>


int main (int argc, char **argv)
{
    char a = 'x';
    char b = 'y';

    char * const pc1 = &a;
    const char * pc2 = &a;

    printf ("Before\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    *pc1 = b;
/*     pc1 = &b; */

/*     *pc2 = b; */
    pc2 = &b;

    printf ("\n\n");

    printf ("After\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    return EXIT_SUCCESS;
}

J'ai compilé le programme (avec gcc 3.4) et l'ai exécuté. La sortie souligne assez bien la différence:

Before
pc1=ffbfd7e7
*pc1=x
pc2=ffbfd7e7
*pc2=x


After
pc1=ffbfd7e7
*pc1=y
pc2=ffbfd7e6
*pc2=x

Cependant, j'ai dû écrire le petit programme pour obtenir la réponse. Au cas où je serais loin de la machine (lors d'une interview, par exemple), je ne serais pas en mesure de répondre à la question.

Quelqu'un peut-il expliquer, en commentant l'exemple ci-dessus, comment fonctionne le mot clé const?

142
rahmu
char * const a;

signifie que le pointeur est constant et immuable, mais pas les données pointées.
Vous pouvez utiliser const_cast (en C++) ou un transtypage de style c pour éliminer la constance dans ce cas, car les données elles-mêmes ne sont pas constantes.

const char * a;

signifie que les données pointées ne peuvent pas être écrites en utilisant le pointeur a. L'utilisation d'un transtypage const_cast (C++) ou de style c pour chasser la constance dans ce cas provoque comportement non défini.

170
Alok Save

Pour analyser des types compliqués, vous devez commencer par la variable, aller à gauche et aller en spirale. S'il n'y a pas de tableaux ou de fonctions à prendre en compte (car ceux-ci se trouvent à droite du nom de la variable), cela devient un cas de lecture de droite à gauche.

Donc avec char *const a; vous avez a, qui est un pointeur const (*) vers un char. En d'autres termes, vous pouvez changer le caractère sur lequel a pointe, mais vous ne pouvez pas faire a indiquer autre chose.

Inversement, avec const char* b; vous avez b, qui est un pointeur (*) vers un char qui est const. Vous pouvez faire en sorte que b pointe sur le caractère de votre choix, mais vous ne pouvez pas modifier la valeur de ce caractère avec *b = ...;.

Vous pouvez aussi bien sûr avoir les deux types de constance à la fois: const char *const c;.

88
AAT
char * const a;

*a est accessible en écriture, mais a ne l'est pas; en d'autres termes, vous pouvez modifier la valeur pointé sur avec a, mais vous ne pouvez pas modifier a elle-même. a est un pointeur constant sur char.

const char * a; 

a est accessible en écriture, mais *a ne l'est pas; en d'autres termes, vous pouvez modifier a (en le dirigeant vers un nouvel emplacement), mais vous ne pouvez pas modifier la valeur pointée vers par a.

Notez que ceci est identique à

char const * a;

Dans ce cas, a est un pointeur sur un const char.

61
John Bode

Maintenant que vous connaissez la différence entre char * const a et const char * a. Plusieurs fois, nous sommes confus s'il s'agit d'un pointeur constant ou d'un pointeur sur une variable constante.

Comment le lire? Suivez les étapes simples ci-dessous pour identifier entre les deux supérieurs.

Voyons comment lire ci-dessous la déclaration

char * const a;

lire de droite à gauche

Maintenant, commencez par a,

1 . adjacent à a il y a const.

char * (const a);

---> Donc, a est un constant(????).

2 Allez maintenant vous obtenez *

char (* (const a));

---> Donc, a est un constantpointer à (????).

3 Allez-y et il y a char

(char (* (const a)));

---> a est une variable constantpointer à character

a is constant pointer to character variable. 

N'est-ce pas facile à lire?

De même pour la deuxième déclaration

const char * a;

Maintenant, recommencez avec a,

1 . Adjacent à a il y a *

---> Alors a est un pointer to (????)

2 Maintenant il y a char

---> donc a est pointercharacter,

Cela n'a aucun sens !!! Donc, mélangez pointer et character

---> donc a est characterpointer à (?????)

3 Maintenant vous avez constant

---> so a est characterpointer à constant variable

Mais bien que vous sachiez ce que signifie la déclaration, faisons en sorte qu’elle paraisse plus sensée.

a is pointer to constant character variable
22
Sagar Sakre

La meilleure façon de comprendre la différence est de penser aux différentes possibilités. Il y a deux objets à prendre en compte, le pointeur et l'objet pointé (dans ce cas, 'a' est le nom du pointeur, l'objet pointé est non nommé, de type char). Les possibilités sont:

  1. rien n'est const
  2. le pointeur est const
  3. l'objet pointé est const
  4. le pointeur et l'objet pointé sont tous deux const.

Ces différentes possibilités peuvent être exprimées en C comme suit:

  1. char * a;
  2. char * const a;
  3. const char * a;
  4. const char * const a;

J'espère que cela illustre les différences possibles

16
John Vincent

Le premier est un pointeur constant sur un caractère et le second est un pointeur sur un caractère constant. Vous n'avez pas touché tous les cas dans votre code:

char * const pc1 = &a; /* You can't make pc1 point to anything else */
const char * pc2 = &a; /* You can't dereference pc2 to write. */

*pc1 = 'c' /* Legal. */
*pc2 = 'c' /* Illegal. */

pc1 = &b; /* Illegal, pc1 is a constant pointer. */
pc2 = &b; /* Legal, pc2 itself is not constant. */
12
cnicutar

Ci-dessus sont d'excellentes réponses. Voici un moyen facile de s'en souvenir:

un est un pointeur

* a est la valeur

Maintenant, si vous dites "const a" alors le pointeur est const. (c'est-à-dire car * const a;)

Si vous dites "const * a" alors la valeur est const. (c'est-à-dire const char * a;)

5
jack

Je vais d'abord l'expliquer verbalement, puis avec un exemple:

Un objet pointeur peut être déclaré comme un pointeur const ou un pointeur vers un objet const (ou les deux):

Un const pointeur ne peut pas être réaffecté pour pointer sur un objet différent de celui auquel il est initialement affecté, mais il peut être utilisé pour modifier l'objet sur lequel il pointe (appelé "pointee").
Les variables de référence constituent donc une syntaxe alternative pour les constpointers.

Un pointeur sur un objet const, en revanche, peut être réaffecté pour pointer vers un autre objet du même type ou d'un type convertible, mais il ne peut pas être utilisé pour modifier un objet.

Un pointeur const sur un objet const peut également être déclaré et ne peut être utilisé pour modifier la pointee ni être réaffecté pour pointer vers un autre objet.

Exemple:

void Foo( int * ptr,
         int const * ptrToConst,
         int * const constPtr,
         int const * const constPtrToConst ) 
{ 
    *ptr = 0; // OK: modifies the "pointee" data 
    ptr = 0; // OK: modifies the pointer 

    *ptrToConst = 0; // Error! Cannot modify the "pointee" data
     ptrToConst = 0; // OK: modifies the pointer 

    *constPtr = 0; // OK: modifies the "pointee" data 
    constPtr = 0; // Error! Cannot modify the pointer 

    *constPtrToConst = 0; // Error! Cannot modify the "pointee" data 
    constPtrToConst = 0; // Error! Cannot modify the pointer 
}

Heureux d'aider! Bonne chance!

5
Barel

Vous pouvez utiliser l'utilitaire cdecl ou ses versions en ligne, comme https://cdecl.org/

Par exemple:

void (* x)(int (*[])()); est un declare x as pointer to function (array of pointer to function returning int) returning void

2
Zinovy Nis

Essayer de répondre de manière simple:

char * const a;  => a is (const) constant (*) pointer of type char {L <- R}. =>( Constant Pointer )
const char * a;  => a is (*) pointer to char constant             {L <- R}. =>( Pointer to Constant)

Pointeur constant:

le pointeur est constant !!. c'est-à-dire que l'adresse qu'il détient ne peut être changée. Il sera stocké dans la mémoire en lecture seule.

Essayons de changer l'adresse du pointeur pour en comprendre plus:

char * const a = &b; 
char c;
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable.

Cela signifie qu'une fois que le pointeur constant pointe quelque chose, c'est pour toujours.

pointeur a pointe uniquement b.

Cependant, vous pouvez modifier la valeur de b, par exemple:

char b='a';
char * const a =&b;

printf("\n print a  : [%c]\n",*a);
*a = 'c';
printf("\n now print a  : [%c]\n",*a);

Pointeur sur Constant:

La valeur indiquée par le pointeur ne peut pas être modifiée.

const char *a;
char b = 'b';
const char * a =&b;
char c;
a=&c; //legal

*a = 'c'; // illegal , *a is pointer to constant can't change!.
1
B_San
const char * a;

Cela indique le pointeur sur le caractère constant. Pour par exemple.

char b='s';
const char *a = &b;

Ici a pointe vers un caractère constant ('s', dans ce cas). Vous ne pouvez pas utiliser a pour modifier cette valeur.Mais cette déclaration ne signifie pas que la valeur sur laquelle elle pointe est - vraiment une constante, cela signifie simplement que la valeur est une constante en ce qui concerne a. Vous pouvez modifier la valeur de b directement en modifiant la valeur de b, mais vous ne pouvez pas modifier la valeur indirectement via le pointeur a.

*a='t'; //INVALID b='t' ; //VALID

char * const a=&b

Cela indique un pointeur constant sur char. Il oblige a à ne pointer que vers b mais il vous permet de modifier la valeur de b.

J'espère que ça aide!!! :)

0
user4291320