stały wskaźnik vs wskaźnik na stałej wartości [duplikat]

To pytanie ma już odpowiedź tutaj:

Jaka jest różnica między poniższymi deklaracjami?

char * const a;
const char * a;

Aby zrozumieć różnicę napisałem ten mały program:

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

Skompilowałem program (z gcc 3.4) i uruchomiłem go. Na wyjście podkreśla różnicę dość dobrze:

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


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

Jednak musiałem napisać mały program, aby uzyskać odpowiedź. W przypadku, gdy jestem z dala od maszyny (na przykład na rozmowie kwalifikacyjnej), nie byłbym w stanie odpowiedzieć na pytanie.

Czy ktoś może wyjaśnić, komentując powyższy przykład, jak działa słowo kluczowe const?

Author: another, 2012-04-10

11 answers

char * const a;

Oznacza, że wskaźnik jest stały i niezmienny, ale dane wskazywane nie są.
Możesz użyć const_cast (W C++) lub c-style cast, aby odrzucić stałość w tym przypadku, ponieważ same dane nie są stałe.

const char * a;

Oznacza, że wskazywane dane nie mogą być zapisywane za pomocą wskaźnika a. Użycie odlewu const_cast(C++) lub c-style do odrzucenia stałości w tym przypadku powoduje nieokreślone zachowanie .

 161
Author: Alok Save,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-26 23:39:08

Aby przeanalizować skomplikowane typy, zaczynasz od zmiennej, idziesz w lewo i spiralnie na zewnątrz. Jeśli nie ma żadnych tablic lub funkcji, o które można się martwić (ponieważ znajdują się one po prawej stronie nazwy zmiennej), staje się to przypadkiem odczytu od prawej do lewej.

Więc z char *const a; MASZ a, który jest const wskaźnikiem (*) na char. Innymi słowy, możesz zmienić znak, na który a wskazuje, ale nie możesz zmienić a na cokolwiek innego.

]} masz b, który jest wskaźnikiem (*) do char, który jest const. Możesz ustawić b na dowolny znak, ale nie możesz zmienić wartości tego znaku za pomocą *b = ...;.

Można również oczywiście mieć oba smaki const-ness w jednym czasie: const char *const c;.

 74
Author: AAT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 09:11:11
char * const a;

*a można zapisać, ale a nie jest; innymi słowy, można zmodyfikować wartość wskazywaną na przez a, ale nie można zmodyfikować samej a. a jest stałym wskaźnikiem do char.

const char * a; 

a jest zapisywalna, ale *a nie jest; innymi słowy, można modyfikować a (wskazując ją na nową lokalizację), ale nie można modyfikować wartości wskazywanej na przez a.

Zauważ, że jest to identyczne z

char const * a;

W tym przypadku a jest wskaźnik do a const char.

 59
Author: John Bode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 08:34:13

Teraz, kiedy znasz różnicę między char * const a i const char * a. Wiele razy mylimy się, jeśli jest stałym wskaźnikiem lub wskaźnikiem do stałej zmiennej.

Jak to odczytać? Wykonaj poniższy prosty krok, aby zidentyfikować między dwoma górnymi.

Zobaczmy, jak odczytać poniższą deklarację

char * const a;

Czytaj od prawej do lewej

Teraz zacznij od a,

1 . obok a znajduje się const.

Char * (const a);

- - - > więc a jest constant (????).

2 . A teraz idź, dostaniesz *

Char (* (const a));

- - -> więc a jest constant pointer do (????).

3 . Go along and there is char

(char (* (const a)));

---> a jest constant pointer do character zmiennej

a is constant pointer to character variable. 

Czy to nie jest łatwe do odczytania?

Analogicznie do drugiej deklaracji

const char * a;

Teraz znowu zacznij od a,

1 . W sąsiedztwie a znajduje się *

- - - > więc a jest pointer do (????)

2 . Teraz jest char

- - -> więc a jest pointer character,

To nie ma sensu!!! Więc shuffle pointer i character

- - -> więc a jest character pointer do (?????)

3 . Teraz masz constant

- - -> więc a jest character pointer do constant zmiennej

Ale chociaż można zrozumieć, co oznacza deklaracja, niech to brzmi bardziej rozsądnie.

a is pointer to constant character variable
 21
Author: Sagar Sakre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-12 08:57:22

Najprostszym sposobem na zrozumienie różnicy jest pomyślenie o różnych możliwościach. Istnieją dwa obiekty do rozważenia, wskaźnik i obiekt wskazywany (w tym przypadku 'a' jest nazwą wskaźnika, wskazywany obiekt jest nienazwany, typu char). Możliwości to:

  1. nic nie jest const
  2. Wskaźnik jest const
  3. wskazywany obiekt to const
  4. zarówno wskaźnik, jak i wskazywany obiekt są const.

Te różne możliwości można wyrazić w C w następujący sposób:

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

Mam nadzieję, że to ilustruje możliwe różnice

 13
Author: John Vincent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 09:54:54

Pierwszy jest stałym wskaźnikiem do znaku, a drugi jest wskaźnikiem do stałego znaku. Nie dotknąłeś wszystkich przypadków w swoim kodzie:

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
Author: cnicutar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-10 15:39:57

Wyjaśnię to najpierw słownie, a potem na przykładzie:

Obiekt pointer może być zadeklarowany jako wskaźnik const lub wskaźnik do obiektu const (lub obu):

Aconst pointer nie może być ponownie przypisany do innego obiektu niż ten, który jest początkowo przypisany, ale może być użyty do modyfikacji obiektu, do którego wskazuje (zwanego "pointee").
Zmienne referencyjne są więc alternatywną składnią dla konstpointerów.

A wskaźnik do obiekt const , z drugiej strony, może być przypisany do innego obiektu tego samego typu lub typu zamiennego, ale nie może być użyty do modyfikacji żadnego obiektu.

A wskaźnik const do obiektu const może być również zadeklarowany i nie może być użyty do modyfikacji punktu ani nie może być przypisany do innego obiektu.

Przykład:

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 
}
Cieszę się, że mogę pomóc! Powodzenia!
 6
Author: Barel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-03 16:43:55

Powyżej są świetne odpowiedzi. Oto prosty sposób na zapamiętanie tego:

A jest wskaźnikiem

*a jest wartością

Teraz jeśli powiesz "const a", to wskaźnik jest const. (tj. char * const a;)

Jeśli powiesz "const * a", to wartością jest const. (tj. const char * a;)

 5
Author: jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-25 15:29:20

Możesz używać narzędzia cdecl lub jego wersji online, takich jak https://cdecl.org/

Na przykład:

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

 2
Author: Zinovy Nis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 04:48:46

Próba odpowiedzi w prosty sposób:

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)

Wskaźnik Stały:

Wskaźnik jest stały !!. tzn. adres, który przechowuje, nie może zostać zmieniony. Zostanie on zapisany w pamięci tylko do odczytu.

Spróbujmy zmienić adres wskaźnika, aby zrozumieć więcej:

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.

To znaczy, że raz stały wskaźnik wskazuje coś, co jest na zawsze.

Wskaźnik a tylko punkty b.

Można jednak zmienić wartość b np:

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

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

Wskaźnik do Stała:

Wartość wskazywana przez wskaźnik nie może być zmieniona.

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
Author: B_San,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-13 17:30:19
const char * a;

Określa wskaźnik na stały znak. Dla np.

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

Tutaj a wskazuje na stały znak ('s', w tym przypadku).Nie można użyć a, aby zmienić tę wartość.Ale ta deklaracja nie oznacza, że wartość, na którą wskazuje, jest w rzeczywistości stałą , po prostu oznacza, że wartość jest stałą o ile dotyczy a. Możesz zmienić wartość b bezpośrednio, zmieniając wartość b, ale nie możesz zmienić wartości pośrednio za pomocą a pointer.

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

char * const a=&b

To określa stały wskaźnik do znaku. Ogranicza a wskazywać tylko na b, jednak pozwala na zmianę wartości b.

Mam nadzieję, że to pomoże!!! :)

 0
Author: user4291320,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 08:04:36