LINUX.ORG.RU

[c]объединение строк

 


0

0

[code] char *s1="str1", *s2="strr2"; strcat(s1,s2); ... Segmentation fault [/code] [code] char s1[9]="str1", *s2[5]="strr2"; strcat(s1,s2); ... str1strr2 [/code] Почему в первом случае неудача? И как можно объединить 2 строки которые объявлены как char *s1, *s2; ?

anonymous

[code] 
char *s1="str1", *s2="strr2"; 
strcat(s1,s2); 
... 
Segmentation fault 
[/code] 
[code] 
char s1[9]="str1", *s2[5]="strr2"; 
strcat(s1,s2);
... 
str1strr2 
[/code] 
Почему в первом случае неудача? И как можно объединить 2 строки которые объявлены как char *s1, *s2; ?

anonymous
()
Ответ на: комментарий от koTuk

В древнем компиляторе под дос borland_c++_3 1й вариант работает, в gcc -- нет. Как можно выделить память под str1 что бы влез str2, т.е. как можно объединить 2 строки которые объявлены как char *s1, *s2; ?

anonymous
()
Ответ на: комментарий от anonymous

Память, порожденную строковыми литералами можно только читать. А strcat туда пишет, да еще и больше чем там есть места.

man 3 malloc

dilmah ★★★★★
()
Ответ на: комментарий от anonymous

> В древнем компиляторе под дос borland_c++_3 1й вариант работает

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

Ничего личного, но ты просто не знаешь Си.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

>В древнем компиляторе под дос

дос это вообще не ос. Там любая программа может записать куда угодно что угодно и не поморщиться. Что такое защита памяти в многозадачных ос слышал ? Строки можно многими способами объединить - лучше учебник внимательней почитать про указатели, массивы, организацию памяти и строки в си-стиле.

koTuk
()
Ответ на: комментарий от anonymous

А с тем, что понадобится дальше, что будешь делать?

char *s1 = "str1", *s2 = "str2", *s3;

s3 = malloc(strlen(s1) + strlen(s2) + 1);
if (s3) {
strcpy(s3, s1);
strcat(s3, s2);
}

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

спасибо! >Там защиты памяти нет. В первом случае строки размещаются в сегменде данных, который обычно защищен от записи; во втором - на стеке, которые от записи не защищен.

А за это еще большее спасибо. Элементарные вещи, а не знаю. Есть общие представления о си. Опыт программирования под дос на вышеупомянутом компиляторе:(. Что подскажешь почитать, что бы понять все эти тонкости "правильного" си? Просмотрел K&R, там не встречал упоминаний про стэк и ds.

anonymous
()
Ответ на: комментарий от anonymous

> Просмотрел K&R, там не встречал упоминаний про стэк и ds.

англоязычный K&R, аппендикс, цитата:

the behavior of a program that attempts to alter a string literal is undefined.

dilmah ★★★★★
()
Ответ на: комментарий от anonymous

> есть что-то еще ?

Еще неплохо бы представлять, как работают компилятор, загрузчик и менеджер памяти ОС. И используемый процессор.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Еще неплохо бы представлять, как работают компилятор, загрузчик и менеджер памяти ОС. И используемый процессор.

ага. а еще чем

char *str="str1";

отличается от

char str[]="str1";

особенно в глобальном пространстве :)

xydo ★★
()
Ответ на: комментарий от anonymous

>> char *str="str1"; отличается от char str[]="str1";

>А чем отличается?

Разный linkage. Если в .h файле будет объявление extern char* str а в .c файле char str[]="str1" то линкер будет искать указатель str в объектном коде, но наткнется на массив с таким же именем и отвалится.

Absurd ★★★
()
Ответ на: комментарий от Absurd

char *str = "str";

это объявление указателя + создание строкового литерала в константной
памяти для литералов + присваивание указателю указателя на литерал.

Заметь что после:

char *str1 = "str";
char *str2 = "str";

указатели str1 и str2 могут оказаться равны, потому что компилятор имеет право мержить строковые литералы.


char str[] = "str";

это объявление массива, инициализованного данными символами.

После:

char str1[] = "str";
char str2[] = "str";

str1 и str2 это отдельные массивы, в разных местах памяти.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> это объявление массива, инициализованного данными символами.

а ноль на конце откуда берется?

объявление массива это

const char str1[] = {'s', 't', 'r'};

anonymous
()
Ответ на: комментарий от anonymous

ноль берется потому что он входит в понятие "данные символы".

если предел массива явно укажешь char str[3] = "str"; то нуля не будет.

dilmah ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.