Увеличивающийся символ в строковом литерале

0
    #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++ рассматривают их по-разному.

  • 0
    Нет, это потому, что вы указываете на постоянную строку, но вы разыменовываете первый символ
  • 0
    Вы хотите увеличить ptr или значение в ptr [0]?
Показать ещё 2 комментария
Теги:
gcc
turbo-c++

3 ответа

5
Лучший ответ

Нет, приоритет оператора определяется стандартом C, и весь компилятор следует за ним.

Причина разностного результата Turbo C++ и GCC в этом случае заключается в том, что вы изменили строковый литерал, что является неопределенным поведением.

Измените его на:

char arr[] = "Helio";
char *ptr = arr;

и теперь вы можете изменить содержимое строки. Обратите внимание, что arr является именем массива и не может быть изменено, поэтому я добавил новую переменную ptr и инициализировал ее, чтобы указать на первый элемент массива.

4

В вашей последней строке printf() выражение ++*ptr эквивалентно ++ptr[0], что, в свою очередь, эквивалентно ptr[0] = ptr[0]+1. Поскольку ptr[0]=='H', вы пытаетесь изменить значение ptr[0] на 'I'.

Это ключевая проблема. Так как &ptr[0] указывает на первый элемент константы "Helio", попытка изменить первый символ, H, создает проблемы, поскольку это неопределенное поведение.

  • 0
    Я чувствую, что это плагиат мой ответ довольно плохо ...
  • 0
    @ v.oddou +1 это хорошая попытка правильного ответа :).
Показать ещё 5 комментариев
2
char* p = "some literal";

Это законно только из-за вонючего аргумента, который C-люди сражались во время стандартных переговоров. Вы должны рассматривать это как странность, которая существует для обратной совместимости.

Это сообщение, которое вы получаете с GCC:

предупреждение: устаревшее преобразование из строковой константы в 'char *'

В следующий раз напишите следующее:

char const* p = "some literal";

И сделайте это рефлексией в ваших привычках кодирования. Тогда вы не смогли бы скомпилировать свою неисправную линию.

который:

++*ptr

Здесь вы берете первый символ постоянного литерала и пытаетесь увеличить его, до того, что происходит после H, поэтому I. Но эта зона памяти находится на защищенной от записи странице, потому что это постоянная. Это очень не определено стандартом, и вы должны считать его незаконным. Ваш segfault исходит отсюда. Я предлагаю вам запустить вашу программу в valgrind следующий раз, чтобы получить более сложные сообщения об ошибках.

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

  • 5
    Это не незаконное заявление
  • 0
    Вы должны рассмотреть, как это. потому что вы бросили const от const к не const. пока вы получаете доступ только в режиме чтения, это нормально, но доступ в режиме записи и бума. некоторые компиляторы выдают ошибки сборки в таком объявлении.
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню