Указатель C, ошибка сегмента - PullRequest
0 голосов
/ 06 марта 2012

У меня следующая программа собирается в segfault.Я не могу понять, почему.Пожалуйста, помогите мне.

int main(){
    char *a="String One", *b="String Two";
    while(*a++=*b++);
return 0;
}

Для анализа я удалил цикл while и упростил его.Тем не менее это дает Segfault!

int main(){
    char *a="String One", *b="String Two";
    *a++=*b++;
return 0;
}

Но это работает.Я имею в виду нет segfault!

int main(){
    char *a="String One", *b="String Two";
    *a++;
    *b++;
return 0;
}

Отвечая Лучиену:

На самом деле я пытался эмулировать strcpy.Что-то вроде этого.Теперь, когда я знаю, что строковый литерал предназначен только для чтения, я смог заставить это работать.Спасибо всем.

main(){
char x[10];
char *xx = x;

char *y = "Hello";

char *t=x, *f=y;

while(*xx++ = *y++);

printf(" %s ...%s \n",t,f);
}

Ответы [ 7 ]

4 голосов
/ 06 марта 2012

С

char *a="String One", *b="String Two";

ваш a указывает на постоянную память, содержащую данную строку.Изменение это неопределенное поведение.

3 голосов
/ 06 марта 2012

Многие операционные системы хранят литеральные строковые значения в разделе памяти только для чтения, что означает, что попытки изменить память приводят к тому, что ОС сообщает программе: эй, вы не можете этого коснуться! ВклВ Unix-системах ОС делает это, отправляя процессу сигнал SEGV, что обычно приводит к завершению процесса.

Так как программы на C работают во встроенных системах с открытым исходным кодом и во многих различных операционных системах, некоторые из которых имеют это ограничение, а некоторые нет, стандарт C объявляет это неопределенное поведение .

0 голосов
/ 06 марта 2012

Те строки, которые a, b хранятся в разделе данных.Этот раздел доступен только для чтения.Таким образом, вы не можете изменить строки в разделе данных.a и b - это просто указатель на строки в разделе данных.x хранится в стеке, так что вы можете изменить его.

0 голосов
/ 06 марта 2012
while(*xx++ = *y++);

Это действительно то, что вы хотите? Что вы хотите достичь? Это на самом деле неопределенное поведение, так как вы не знаете, что будет хх после этого. Будете ли вы сначала увеличивать xx или сначала скопировать значение из y в xx, а затем увеличить? См. http://www.open -std.org / jtc1 / sc22 / wg14 / www / docs / n1256.pdf 6.5.2

0 голосов
/ 06 марта 2012

В третьем фрагменте кода *a++ получит доступ к адресу, на который указывает a, который содержит символ 'S', поэтому ошибка сегмента отсутствует.

0 голосов
/ 06 марта 2012

Когда вы создаете строковую константу, говоря char *a="String One", 'a' - это не массив, а указатель, который инициализируется для указания на строковую константу. Если вы хотите изменить строку, на которую она указывает, вы можете указать ее в другом месте, но попытка изменить содержимое на месте приводит к неопределенному поведению.

0 голосов
/ 06 марта 2012

Вы модифицируете строковый литерал, который неопределенное поведение .

Меня тоже раздражает, что

char *a="String One"

на самом деле

const char *a="String One"

"StringOne" хранится в постоянной памяти и поэтому не может быть изменен.

...