Почему char* может содержать один символ в C?
это может показаться слишком сумасшедшим, но я просто подумал. В C, почему
char *pc = 'H'; // single character
char *ps = "hello"; // a string
оба действительны? Я имею в виду, почему char*
может содержать / ссылаться на символ, а также строку с нулевым завершением?
Почему нет предложения guard или ошибки компилятора, генерируемой для *pc
а то char*
Не содержит строку с нулевым завершением?
Я проверил его в Ideone и не получите никакого предупреждения.
4 ответов
char *pc = 'H';
приведенное выше утверждение определяет pc
типа char *
что означает, что он может содержать адрес объекта типа char
. Вы инициализируете его символом H
- другого типа. Помните, что символьный литерал имеет тип int
и оценивает его код символа, который в ASCII является 72
. Таким образом, приведенное выше утверждение эквивалентно
char *pc = 72;
это незаконная операция и компилятор должен предупредить вас об этом (в GCC, используйте флаг -Wall
). Не следует напрямую назначать адрес указателю, так как вы не знаете, есть ли у вас доступ к адресу памяти. Вы должны использовать address of
оператор &
чтобы получить адрес объекта, а затем назначить его указателю.
char *ps = "hello";
в приведенной выше инструкции строковый литерал вычисляется как указатель на его первый элемент. Этот адрес присваивается ps
, который имеет тот же тип, т. е. char *
. Однако строковые литералы доступны только для чтения в C
но это не так!--16--> квалифицированный (в отличие от C++
) и, таким образом, пытается изменить строковый литерал с помощью указателя ps
не приведет к ошибке компилятора, но неопределенное поведение и, скорее всего, сбой программы из-за segfault. Поэтому вы должны определить ps
как указатель на const object
-
const char *ps = "hello";
это can провести char
потому что существует неявное преобразование из char
to char *
(via int
), и потому что sizeof(char *) >= sizeof(char)
. Вы не стоит сделайте это, хотя (технически это неопределенное поведение, потому что буквальное числовое значение символа вряд ли будет допустимым адресом указателя на char
type).
и во многих / большинстве компиляторов это тут генерировать предупреждение:
$ gcc -otest test.c
test.c:5: warning: initialization makes pointer from integer without a cast
на
char *pc = 'H';
'H'
как int
будет приведено к char *
и будет использоваться для инициализации pc
, компилятор должен выдавать предупреждение об этом.
на
char *ps = "hello";
"hello"
будет оценивать его базовый адрес, который будет использоваться для инициализации ps
.
когда я компилирую вышеуказанные строки кода с помощью g++, я получаю следующее предупреждение:
test-12.c:1:12: warning: initialization makes pointer from integer without a cast [enabled by default]
компилятор выполняет несколько автоматических приведений для инициализации pc
.
char
->int
->char*
.
нужно просто обратить внимание на предупреждения компилятора, чтобы обнаружить необычные операции, как вы пытаетесь.