Разница между char* и const char*?

в чем разница между

char* name

что указывает на постоянный строковый литерал и

const char* name

9 ответов


char* Это mutable указатель на mutable символ/строку.

const char* это mutable указатель на неизменяемые символ/строку. Вы не можете изменить содержимое местоположения, на которое указывает этот указатель. Кроме того, компиляторы должны выдавать сообщения об ошибках при попытке сделать это. По той же причине, преобразование из const char * to char* устарела.

char* const это неизменяемые указатель (он не может указывать на любое другое место)но содержимое местоположение точки mutable.

const char* const это неизменяемые указатель на неизменяемые символ/строку.


char *name

вы можете изменить символ, который name указывает, а также символ, на который он указывает.

const char* name

вы можете изменить символ, который name указывает, но вы не можете изменить символ, на который он указывает.
устранение: вы можете изменить указатель, но не чар, которым name указывает на (https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a (v=против 100).aspx, см. "примеры"). В этом случае const спецификатор применяется к char, а не звездочка.

по данным на странице MSDN и http://en.cppreference.com/w/cpp/language/declarations на const до * является частью последовательности спецификатора decl, в то время как const после * часть Декларатора.
Последовательность спецификатора объявления может быть затем следует несколько деклараторов, поэтому const char * c1, c2 объявляет c1 as const char * и c2 as const char.

EDIT:

из комментариев ваш вопрос, похоже, спрашивает о разнице между двумя объявлениями, когда указатель указывает на строковый литерал.

в этом случае не должен изменить символ, к которому name баллов, так как это может привести к неопределено Поведение. Строковые литералы могут быть выделены в областях памяти только для чтения (реализация определена), и пользовательская программа не должна изменять его в любом случае. Любая попытка сделать это приводит к неопределенному поведению.

так что единственная разница в этом случае (использования со строковыми литералами) заключается в том, что второе объявление дает вам небольшое преимущество. Компиляторы обычно дают вам предупреждение, если вы попытаетесь изменить строковый литерал во втором случай.

Пример Онлайн-Примера:

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

выход:

cc1: предупреждения рассматриваются как ошибки
еда.c: в функции ' main’:
еда.c: 9: ошибка: передача аргумента 1 'strcpy' отбрасывает квалификаторы из целевого типа указателя

обратите внимание, что компилятор предупреждает о втором случае, но не о первом.


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] = ''; // compile error
charconstp[3] = ''; // compile error
charpconst[3] = ''; // 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

ни в том, ни в другом случае вы не можете изменить строковый литерал, независимо от того, объявлен ли указатель на этот строковый литерал как char * или const char *.

однако разница в том, что если указатель const char * тогда компилятор должен дать диагностику, если вы пытаетесь изменить значение, указывающее на, но если указатель char * тогда это не так.


первый вы можете изменить, если хотите, второй вы не можете. Читайте о const правильность (есть несколько хороших руководств о разнице). Существует также char const * name где вы не можете переопределить его.


на самом деле char* name - Это не указатель на константу, а указатель на переменную. Возможно, вы говорите о другом вопросе.

в чем разница между char * const и const char *?


Пример 1:

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

выше устанавливает str, чтобы указать на литерал "Hello", который жестко закодирован в двоичном образе программы, который помечен как только для чтения в памяти, означает, что любое изменение в этом строковом литерале незаконно, и это вызовет ошибки сегментации.

Пример 2:

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

случай 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".

просто, чтобы дать дополнительный пример:

    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''.
    //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"

(Я использую библиотеку 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!

Вы можете запустить его и посмотреть вещи лучше для себя.


вопрос в том, в чем разница между

char *name

что указывает на постоянный строковый литерал и

const char *cname

т. е. учитывая

char *name = "foo";

и

const char *cname = "foo";

нет большой разницы между 2 и оба можно рассматривать как правильные. Из-за длительного наследия кода C строковые литералы имели тип char[], а не const char[], и есть много старого кода, который также принимает char * вместо const char *, даже если они не изменяют аргументы.

принципиальным отличием 2 в целом является то, что *cname или cname[n] будет оценивать lvalues типа const char, а *name или name[n] будет оценивать lvalues типа char, которые модифицируемые lvalues. Соответствующий компилятор необходим для создания диагностического сообщения, если цель назначения не является изменяемой lvalue; ему не нужно произвести никакое предупреждение дальше назначение lvalues типа char:

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

компилятор не требуются чтобы остановить компиляцию в любом случае; достаточно, чтобы она произвела предупреждение за задание cname[0]. Полученная программа не является правильно