Różnica między znakiem * a znakiem const*?

Jaka jest różnica między

char* name

, który wskazuje na stały ciąg literalny, oraz

const char* name
Author: zergius, 2012-03-23

9 answers

char* jest zmienny wskaźnik na zmienny znak/ciąg znaków.

const char* jest zmiennym wskaźnikiem na niezmiennym znak/ciąg znaków. Nie można zmienić zawartości lokalizacji, do których wskazuje ten wskaźnik. Ponadto Kompilatory muszą podawać komunikaty o błędach, gdy próbujesz to zrobić. Z tego samego powodu konwersja z const char * na {[0] } jest przestarzała.

char* const jest wskaźnikiem niezmiennym (nie może wskazywać na inne miejsce) ale zawartość miejsca, na które wskazuje, jest zmienna .

const char* const jest niezmiennym wskaźnikiem do niezmiennym znakiem/łańcuchem znaków.

 311
Author: ankit.karwasra,
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-02-28 23:51:04
char *name

Możesz zmienić znak, na który wskazuje name, a także znak, na który wskazuje.

const char* name

można zmienić znak, na który wskazuje name, ale nie można modyfikować znaku, na który wskazuje.
korekta: można zmienić wskaźnik, ale Nie znak, na który name wskazuje na ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a (v=vs.100). aspx , patrz "przykłady"). W tym przypadku const specifier dotyczy char, a nie gwiazdki.

Według strony MSDN i http://en.cppreference.com/w/cpp/language/declarations , const przed * jest częścią sekwencji dekl-specifier, podczas gdy const po * jest częścią Decl-specifier.
Po sekwencji deklaracji może następować wiele deklaratorów, dlatego const char * c1, c2 deklaruje c1 jako const char * i c2 jako const char.

EDIT:

Z komentarzy, Twój question wydaje się być pytaniem o różnicę między dwoma deklaracjami, gdy wskaźnik wskazuje na literalny łańcuch znaków.

W takim przypadku, nie powinieneś modyfikować znaku, na który wskazuje name, ponieważ może to spowodować niezdefiniowane zachowanie . Literały łańcuchów mogą być przydzielane w regionach pamięci tylko do odczytu (zdefiniowanych w implementacji) i program użytkownika nie powinien ich modyfikować. Każda próba tego powoduje nieokreślone zachowanie.

Więc jedynym różnica w tym przypadku (użycie z literałami ciągów) polega na tym, że druga deklaracja daje niewielką przewagę. Kompilatory zazwyczaj dają ostrzeżenie w przypadku próby zmodyfikowania ciągu literalnego w drugim przypadku.

Przykładowy Online:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

Wyjście:

Cc1: Ostrzeżenia traktowane jako błędy
prog.c: w funkcji "main":
prog.c: 9: error: passing argument 1 of' strcpy ' disclards qualifiers from pointer target type

Zauważ, że kompilator ostrzega o drugim przypadku, ale nie o pierwszym.

 41
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
2015-02-10 06:10:41
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok
 14
Author: Afriza N. Arief,
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-03-23 04:37:29

W żadnym przypadku nie można modyfikować literału łańcuchowego, niezależnie od tego, czy wskaźnik do niego jest zadeklarowany jako char * lub const char *.

Jednak różnica polega na tym, że jeśli wskaźnik jest const char *, kompilator musi dać diagnostykę, jeśli próbujesz zmodyfikować wartość wskazywaną, ale jeśli wskaźnik jest char *, to nie.

 9
Author: caf,
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-03-23 04:22:48

Pierwszy można rzeczywiście zmienić, jeśli chcesz, drugi nie. poczytaj o const poprawności (jest kilka fajnych poradników o różnicy). Istnieje również char const * name gdzie nie można go ponownie umieścić.

 2
Author: chikuba,
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-12-18 23:13:24

W rzeczywistości char* name nie jest wskaźnikiem do stałej, ale wskaźnikiem do zmiennej. Możesz mówić o tym innym pytaniu.

Jaka jest różnica między char * const a const char*?

 1
Author: Jeff Wolski,
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-05-23 12:02:47

Przypadek 1:

char *str = "Hello";
str[0] = 'M'  //No warning or error, just Undefined Behavior

Powyższe ustawienie str wskazuje na literalną wartość "Hello", która jest zakodowana na twardo w obrazie binarnym programu, który jest oznaczany jako Tylko do odczytu w pamięci, oznacza, że każda zmiana w tym Literale jest nielegalna i powodowałaby błędy segmentacji.

Przypadek 2:

const char *str = "Hello";
str[0] = 'M'  //Compiler issues a warning

Przypadek 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
 1
Author: Mohit,
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-11-15 06:45:36

Dla dodatkowego przykładu:

    std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because
    //2.3 is a double
    //But the "double" returned by typeid(2.3).name() is indeed a 
    //const char * which consists of 'd','o','u','b','l','e'and'\0'.
    //Here's a simple proof to this:
    std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *"
    const char* charptr
    charptr = typeid(2.3).name();
    std::cout << charptr[3]; // --------->  prints: "b"

(używam biblioteki typeinfo: http://www.cplusplus.com/reference/typeinfo/type_info/name )

    //Now let's do something more interesting:
    char* charptr2="hubble";
    strcpy(charptr, charptr2);  // --------> Oops! Sorry, this is not valid!
Możesz go uruchomić i zobaczyć rzeczy lepiej dla siebie.
 0
Author: M-J,
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-06-12 17:46:45

Pytanie, Jaka jest różnica między

char *name

Który wskazuje na stały ciąg literalny i

const char *cname

Tzn. podane

char *name = "foo";

I

const char *cname = "foo";

Nie ma dużej różnicy między 2 i oba mogą być postrzegane jako prawidłowe. Ze względu na długą spuściznę kodu C, literały łańcuchów mają typ char[], a nie const char[], i istnieje wiele starszych kodów, które podobnie akceptują char * zamiast const char *, nawet jeśli nie modyfikują argumentów.

Zasadnicza różnica 2 w ogóle polega na tym, że *cname lub cname[n] będą oceniać do wartości LV typu const char, podczas gdy *name lub name[n] będą oceniać do wartości LV typu char, które są , które można modyfikować do wartości LV. Kompilator zgodny jest wymagany do wygenerowania komunikatu diagnostycznego, jeśli cel przypisania nie jest modyfikowanym lvalue; nie musi generować żadnego ostrzeżenia przy przypisaniu do lvalue typu char:

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

Kompilator nie jest wymagane aby zatrzymać kompilację w obu przypadkach; wystarczy, że wygeneruje Ostrzeżenie dla przypisania do cname[0]. Wynikowy program nie jest poprawnym programem. Zachowanie konstrukcji jest niezdefiniowane . Może się zawiesić, lub co gorsza, może się nie zawiesić i może zmienić literalny ciąg znaków w pamięci.

 0
Author: Antti Haapala,
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-08-24 19:13:29