какая разница между
char* name
которая указывает на постоянный строковый литерал, и
const char* name
какая разница между
char* name
которая указывает на постоянный строковый литерал, и
const char* name
Ответы:
char*
является изменяемым указатель на изменяемый символ / строка.
const char*
является изменяемым указатель на непреложный символ / строка. Вы не можете изменить содержимое местоположения, на которое указывает указатель. Кроме того, компиляторы обязаны выдавать сообщения об ошибках, когда вы пытаетесь это сделать. По той же причине преобразование из const char *
в char*
не рекомендуется.
char* const
является неизменным указателем (он не может указывать на любое другое местоположение), но содержимое местоположения, на которое он указывает, является изменяемым .
const char* const
является непреложным указатель на непреложный символ / строка.
char const *
char *
давать ошибку сегментации во время работы?
const
если я хочу, чтобы компилятор выдавал ошибку, если я забыл и изменил данные по ошибке, верно?
char *name
Вы можете изменить символ, на который name
указывает, а также символ, на который он указывает.
const char* name
Вы можете изменить символ, на который name
указывает, но вы не можете изменить символ, на который он указывает.
Исправление: Вы можете изменить указатель, но не символ, на который name
указывает ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , см. «Примеры» ). В этом случае const
указатель относится к char
звездочке, а не к ней.
Согласно странице MSDN и http://en.cppreference.com/w/cpp/language/declarations , const
before *
является частью последовательности спецификатора decl, а const
after *
является частью декларатора.
За последовательностью спецификатора объявления могут следовать несколько объявлений, поэтому const char * c1, c2
объявляется c1
как const char *
и c2
как const char
.
РЕДАКТИРОВАТЬ:
Судя по комментариям, ваш вопрос, похоже, касается разницы между двумя объявлениями, когда указатель указывает на строковый литерал.
В этом случае вы не должны изменять символ, на который 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: предупреждения обрабатываются как ошибки
prog.c: в функции 'main':
prog.c: 9: error: при передаче аргумента 1 'strcpy' отбрасывает классификаторы из целевого типа указателя
Обратите внимание, что компилятор предупреждает о втором случае, но не о первом.
name
указывает пункт в любом случае. Это может привести к UB.
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
char *
значения приводит к ошибке сегментации, поскольку мы пытаемся изменить строковый литерал (который присутствует в постоянной памяти)
Ни в том, ни в другом случае вы не можете изменить строковый литерал независимо от того, объявлен ли указатель на этот строковый литерал как char *
или const char *
.
Однако различие заключается в том, что если указатель равен, const char *
то компилятор должен выдать диагностику, если вы пытаетесь изменить значение, на которое указывает указатель, но если указатель равен, char *
то это не так.
extern ... name
и иметь *name = 'X';
. На «правильной операционной системе» это может дать сбой, но на встроенных системах я бы ожидал, что он будет делать что-то конкретное для платформы / компилятора.
СЛУЧАЙ 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Выше указано, что str указывает на буквальное значение «Hello», которое жестко запрограммировано в двоичном изображении программы, которое помечено как доступное только для чтения в памяти, означает, что любое изменение в этом строковом литерале является недопустимым, и это приведет к ошибкам сегментации.
ДЕЛО 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
ДЕЛО 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Первое, что вы можете изменить, если хотите, второе, которое вы не можете. Читайте о const
правильности (есть несколько хороших руководств о разнице). Там также, char const * name
где вы не можете переписать это.
Вопрос в том, в чем разница между
char *name
которая указывает на постоянный строковый литерал, и
const char *cname
Т.е. дано
char *name = "foo";
и
const char *cname = "foo";
Существует не так много различий между 2 и оба могут рассматриваться как правильные. Из-за долгого наследия C-кода строковые литералы имели тип « char[]
нет» const char[]
, и существует множество более старых кодов, которые также принимают char *
вместо const char *
, даже если они не модифицируют аргументы.
Принципиальное отличие от 2 в общем состоит в том, что *cname
или cname[n]
будет вычисляться для l-значений типа const char
, тогда как *name
или name[n]
будет оцениваться для l-значений типа char
, которые являются модифицируемыми l-значениями . Соответствующий компилятор необходим для создания диагностического сообщения, если целью назначения не является изменяемое значение lvalue ; не нужно выдавать никаких предупреждений о присвоении lvalues типа char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
Компилятор не обязан останавливать компиляцию в любом случае; достаточно, чтобы он выдал предупреждение для назначения cname[0]
. Полученная программа не является правильной программой. Поведение конструкции не определено . Может произойти сбой или, что еще хуже, может не произойти сбой и может изменить строковый литерал в памяти.
Фактически, char* name
это не указатель на константу, а указатель на переменную. Возможно, вы говорите об этом другом вопросе.