#include<stdio.h>
int main(){
char *ptr="Helio";
ptr++;
printf("%s\n",ptr);
//*ptr++;
printf("%c\n",++*ptr);/*Segmentation fault on GCC*/
return 0;
}
Q1) Это отлично работает в Turbo C++, но на GCC он дает ошибку сегментации. Я не понимаю точной причины.
Может быть, приоритет оператора является одной из причин.
Q2) У каждого компилятора есть другой приоритет оператора?
Как я вижу здесь, ++ имеет более высокий приоритет, чем оператор разыменования. Может быть, GCC и Turbo C++ рассматривают их по-разному.
Нет, приоритет оператора определяется стандартом C, и весь компилятор следует за ним.
Причина разностного результата Turbo C++ и GCC в этом случае заключается в том, что вы изменили строковый литерал, что является неопределенным поведением.
Измените его на:
char arr[] = "Helio";
char *ptr = arr;
и теперь вы можете изменить содержимое строки. Обратите внимание, что arr
является именем массива и не может быть изменено, поэтому я добавил новую переменную ptr
и инициализировал ее, чтобы указать на первый элемент массива.
В вашей последней строке printf()
выражение ++*ptr
эквивалентно ++ptr[0]
, что, в свою очередь, эквивалентно ptr[0] = ptr[0]+1
. Поскольку ptr[0]=='H'
, вы пытаетесь изменить значение ptr[0]
на 'I'
.
Это ключевая проблема. Так как &ptr[0]
указывает на первый элемент константы "Helio"
, попытка изменить первый символ, H
, создает проблемы, поскольку это неопределенное поведение.
char* p = "some literal";
Это законно только из-за вонючего аргумента, который C-люди сражались во время стандартных переговоров. Вы должны рассматривать это как странность, которая существует для обратной совместимости.
Это сообщение, которое вы получаете с GCC:
предупреждение: устаревшее преобразование из строковой константы в 'char *'
В следующий раз напишите следующее:
char const* p = "some literal";
И сделайте это рефлексией в ваших привычках кодирования. Тогда вы не смогли бы скомпилировать свою неисправную линию.
который:
++*ptr
Здесь вы берете первый символ постоянного литерала и пытаетесь увеличить его, до того, что происходит после H
, поэтому I
. Но эта зона памяти находится на защищенной от записи странице, потому что это постоянная. Это очень не определено стандартом, и вы должны считать его незаконным. Ваш segfault исходит отсюда. Я предлагаю вам запустить вашу программу в valgrind
следующий раз, чтобы получить более сложные сообщения об ошибках.
В ответе, который написал Ю. Хао для вас, происходит то, что все символы копируются один за другим, из постоянного пула строк, где литерал хранится, в массив символов, выделенных стеком, кодом, который пишет компилятор на сайте инициализации/объявления, поэтому вы можете разыменовать его содержимое.