Почему 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*.

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