URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9872
[ Назад ]

Исходное сообщение
"Строковые типы в C"

Отправлено noisebringer , 24-Июн-14 16:28 
Всем доброго времени суток.
Недавно начал использовать язык программирования С. Интересный язык, должен сказать.

Вот только не могу до конца разобраться со строками.

Строковую переменную можно определить описанными ниже способами:
1) char *lala;
2) char *lala = "lala";
3) char lala[] = "lala";
4) char lala[4];
5) char lala[4] = "lala";
6) char *lala = (char *) malloc (sizeof(char) * 4);

Может быть существуют ещё варианты, но мне пока что повстречались только эти.

Самый первый вопрос, который рождается в голове, это является ли объявления номер 4, 6 идентичными? Тот же вопрос для объявление номер 3 и 5.
В чём разница между объявлениями 5, 2 и 3?

И какое из этих объявлений для каких случаев лучше подходит?

За ранее благодарен.


Содержание

Сообщения в этом обсуждении
"Строковые типы в C"
Отправлено Pahanivo , 24-Июн-14 17:07 
> Всем доброго времени суток.
> Недавно начал использовать язык программирования С. Интересный язык, должен сказать.

я так понимаю дело дальше абзаца "А давайте напишем программу Hello world ..." не дошло?


"Строковые типы в C"
Отправлено noisebringer , 24-Июн-14 23:15 
>> Всем доброго времени суток.
>> Недавно начал использовать язык программирования С. Интересный язык, должен сказать.
> я так понимаю дело дальше абзаца "А давайте напишем программу Hello world
> ..." не дошло?

я так понимаю ответ дальше фразы "я так понимаю дело дальше абзаца "А давайте напишем программу Hello world... не дошло?" не дошел?


"Строковые типы в C"
Отправлено Evolve32 , 24-Июн-14 19:42 
> Самый первый вопрос, который рождается в голове, это является ли объявления номер
> 4, 6 идентичными?

Нет
4 - массив
6 - указатель
> Тот же вопрос для объявление номер 3 и 5.

Нет
3 - массив из 5 символов, а
5 - из 4, причем с выходом за границу массива
> В чём разница между объявлениями 5, 2 и 3?

2 - находится в стеке как константа.
3 - в куче, размер массива определен автоматически
5 - в куче, размер определен ручками

Единственный совет - стек лучше не загромождать и не надеятся, что все libc выделяют для него столько же памяти, сколько glibc


"Строковые типы в C"
Отправлено noisebringer , 24-Июн-14 23:07 
В первую очередь хотелось бы поблагодарить за адекватный ответ.
Надеюсь вас сильно не затруднит провести небольшой лик-без :)

>> Самый первый вопрос, который рождается в голове, это является ли объявления номер
>> 4, 6 идентичными?
> Нет
> 4 - массив
> 6 - указатель

Что из этого проистекает, как это отражается непосредственно на работе программы?
То есть я ведь могу точно так же сделать strcat в lala и из неё, обращаться посимвольно в обоих вариантах.

>> Тот же вопрос для объявление номер 3 и 5.
> Нет
> 3 - массив из 5 символов, а
> 5 - из 4, причем с выходом за границу массива

Про пять символов вы имеете в виду нолик в конце?

>> В чём разница между объявлениями 5, 2 и 3?
> 2 - находится в стеке как константа.
> 3 - в куче, размер массива определен автоматически
> 5 - в куче, размер определен ручками
> Единственный совет - стек лучше не загромождать и не надеятся, что все
> libc выделяют для него столько же памяти, сколько glibc

Тут всё понятно :)



"Строковые типы в C"
Отправлено Evolve32 , 26-Июн-14 10:18 
> В первую очередь хотелось бы поблагодарить за адекватный ответ.
> Надеюсь вас сильно не затруднит провести небольшой лик-без :)
>>> Самый первый вопрос, который рождается в голове, это является ли объявления номер
>>> 4, 6 идентичными?
>> Нет
>> 4 - массив
>> 6 - указатель
> Что из этого проистекает, как это отражается непосредственно на работе программы?
> То есть я ведь могу точно так же сделать strcat в lala
> и из неё, обращаться посимвольно в обоих вариантах.

Все верно, но массив нельзя использовать как lvalue, то есть, т.е., как выражение слева, например:

char x[4];
char *pt;
x = pt; // Ошибка


"Строковые типы в C"
Отправлено pavlinux , 25-Июн-14 00:39 
> 5 - из 4, причем с выходом за границу массива

Нет там никакого выхода! Просто нуля в конце не будет. Из этих соображений
эту строку нельзя напрямую юзать в строковых функциях strcpy, strcmp, printf %s и т.д.


"Строковые типы в C"
Отправлено noisebringer , 25-Июн-14 03:54 
>> 5 - из 4, причем с выходом за границу массива
> Нет там никакого выхода! Просто нуля в конце не будет. Из этих
> соображений
> эту строку нельзя напрямую юзать в строковых функциях strcpy, strcmp, printf %s
> и т.д.

Очень благодарен за дельное замечание!


"Строковые типы в C"
Отправлено Andrey Mitrofanov , 25-Июн-14 09:41 
> Нет там никакого выхода! Просто нуля в конце не будет.

Правда?

$ ./tst.bb
- 0
$ cat tst.c
#include <stdio.h>

char str[4]="abab";
char *canary="zzzz";

int main() {
    printf( "%c - %d\n", str[4], (int)str[4]);
}


"Строковые типы в C"
Отправлено Andrey Mitrofanov , 25-Июн-14 09:51 
>> 5 - из 4, причем с выходом за границу массива
> Нет там никакого выхода! Просто нуля в конце не будет.

А и правда,

$ ./tst.bb
0x6008ec 0x6008f1 0x6008f5
-5/ y - 121
-4/ y - 121
-3/ y - 121
-2/ y - 121
-1/  - 0
  0/ a - 97
  1/ b - 98
  2/ a - 97
  3/ b - 98
  4/ z - 122
  5/ z - 122
  6/ z - 122
  7/ z - 122
  8/  - 0


char canarx[]="yyyy";
char str[4]="abab";
char canary[]="zzzz";

int main() {
    int i;
    printf("%p %p %p\n", canarx, str, canary);
    for(i=-5;i<20;i++)
        printf( "%3d/ %c - %d\n", i, str[i], (int)str[i]);


"Строковые типы в C"
Отправлено noisebringer , 25-Июн-14 04:17 
До этого я имел дело с языками в которых память может распределяться автоматически, а тут такого дела не оказалось и меня мучал вопрос, как сделать так, чтобы не разводить бред из серии lala[1000000] = "lala", а всё остальное свободное.
Оказалось, что здесь это делается так
        char *lala; //Объявляем указатель
        lala = (char *) calloc(strlen("lala") + 1, sizeof(char)); // выделяем в куче кусочек памяти заполненный нулями необходимый для строки lala
        strcat(lala, "lala"); // записываем туда строку lala
        char tutu[5] = "tutu";
        tutu[5] = 0;
        lala = (char *) realloc(lala, (strlen(lala) + strlen(tutu) + 1) * sizeof(char)); //добавляем память для строки tutu
        strcat(lala, tutu); //записываем строку tutu
        printf("lala is %s\n", lala);
        free(lala);
Надеюсь, что здесь всё написано правильно, за исключением обработки возможных ошибок при распределении памяти, но здесь их можно опустить ибо это пример, и тему можно закрывать :)

"Строковые типы в C"
Отправлено pavlinux , 26-Июн-14 02:46 
> Надеюсь, что здесь всё написано правильно,

tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has been started. USA destroyed */

И ваще, это "плохая" строка, забудь про такие фишки (на ближайшие лет 7-8).
Ты либо улетишь за пределы массива, либо затрёшь последний символ.  


"Строковые типы в C"
Отправлено noisebringer , 26-Июн-14 05:43 
>> Надеюсь, что здесь всё написано правильно,
> tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has
> been started. USA destroyed */
> И ваще, это "плохая" строка, забудь про такие фишки (на ближайшие лет
> 7-8).
> Ты либо улетишь за пределы массива, либо затрёшь последний символ.

Почему out of bounds если изначально массив объявлялся как массив из пяти элементов?
Если не так, то каким образом обозначать окончание строки? '\0' ? И чем отличается '\0' от просто 0?


"Строковые типы в C"
Отправлено Аноним , 26-Июн-14 06:44 

>> tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has been started. USA destroyed */

To Pavlinux - Нынче пишут "Курс доллара упал до 0" :-)

> Почему out of bounds если изначально массив объявлялся как массив из пяти элементов?

Всё верно от tutu[0] до tutu[4] :-) Тут вам на васик какой ...

> Если не так, то каким образом обозначать окончание строки? '\0' ? И
> чем отличается '\0' от просто 0?

Да не поможет это. Этот код:
char tutu[5] = "tutu";
посмотри в ассемблере чего делает - это константная строка, еЯ менять нельзя.
Да - да в ассемблере, тут вам не васик, тут ты по локоть в железе :)


"Строковые типы в C"
Отправлено Аноним , 26-Июн-14 06:59 
> Да не поможет это. Этот код:
> char tutu[5] = "tutu";
> посмотри в ассемблере чего делает - это константная строка, еЯ менять нельзя.

Ага ... сам посмотрел. Для 4.7.2 это больше не так :) Ложет их в .data - то есть менять - можно.

Сорьки - лопухнулся йа :)


"Строковые типы в C"
Отправлено pavlinux , 27-Июн-14 02:17 
>>> tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has been started. USA destroyed */
> To Pavlinux - Нынче пишут "Курс доллара упал до 0" :-)

Они ещё напечатают.


"Строковые типы в C"
Отправлено noisebringer , 26-Июн-14 09:22 
>>> Надеюсь, что здесь всё написано правильно,
>> tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has
>> been started. USA destroyed */
>> И ваще, это "плохая" строка, забудь про такие фишки (на ближайшие лет
>> 7-8).
>> Ты либо улетишь за пределы массива, либо затрёшь последний символ.
> Почему out of bounds если изначально массив объявлялся как массив из пяти
> элементов?
> Если не так, то каким образом обозначать окончание строки? '\0' ? И
> чем отличается '\0' от просто 0?

Правда-правда. Опять попутал с количественными и порядковыми циферками :))
tutu[4] = 0
а элементы 0,1,2,3 занимают четыре элемента строки.
Благодарен за напоминание :)


"Строковые типы в C"
Отправлено pavlinux , 27-Июн-14 01:17 
> И чем отличается '\0' от просто 0?

типами: первый - char, второй - int.
(Но по секрету, char во внутреннем представлении С это int. Только я тебе это не говорил)

void main() {
       int i;
        for (i=0x30; i < 0x80; i++)
             write(0, &i, 1);
}

вот эта хрень вроде должна напечатать все видимые символы.


"Строковые типы в C"
Отправлено pavlinux , 25-Июн-14 00:07 
> Может быть существуют ещё варианты, но мне пока что повстречались только эти.

char *lala[] = {"lala"};


"Строковые типы в C"
Отправлено noisebringer , 25-Июн-14 03:55 
>> Может быть существуют ещё варианты, но мне пока что повстречались только эти.
> char *lala[] = {"lala"};

Мусье знает толк в извращениях :)


"Строковые типы в C"
Отправлено Аноним , 25-Июн-14 10:56 
> Тьфу, ёклмн. Не туда написал сообщение. В общем заинтересованные личности найдут.

2) char *lala = "lala";

и словишь разыменование NULL-указателя.


"Строковые типы в C"
Отправлено pavlinux , 26-Июн-14 03:08 
>> Тьфу, ёклмн. Не туда написал сообщение. В общем заинтересованные личности найдут.
> 2) char *lala = "lala";
> и словишь разыменование NULL-указателя.

Чей-то вдруг?


"Строковые типы в C"
Отправлено Andrey Mitrofanov , 26-Июн-14 09:19 
>> 2) char *lala = "lala";
>> и словишь разыменование NULL-указателя.
> Чей-то вдруг?

lala=NULL; И "Усё пропало, шеф!"


"Строковые типы в C"
Отправлено pavlinux , 27-Июн-14 01:15 
>>> 2) char *lala = "lala";
>>> и словишь разыменование NULL-указателя.
>> Чей-то вдруг?
> lala=NULL; И "Усё пропало, шеф!"

Ну надеюсь этот код в конце функции, и пырыменная ляля больше не юзается?  


"Строковые типы в C"
Отправлено noisebringer , 30-Июн-14 16:51 
Нашел для себя отличие между вариантами 4 и 6.
Вариант 4 компилятор не дает использовать внутри функций.

"Строковые типы в C"
Отправлено pavlinux , 30-Июн-14 17:05 
> Нашел для себя отличие между вариантами 4 и 6.
> Вариант 4 компилятор не дает использовать внутри функций.

Чёй-то вдруг?

char lala[4];
memset(lala, 0, sizeof(lala)/sizeof(lala[0]));

По-стандарту - массив не инициализированный, по-gcc - там нули.
и даже printf отработает нормально.


"Строковые типы в C"
Отправлено noisebringer , 30-Июн-14 17:11 
warning: function returns address of local variable

Это говорит компилятор примерно в таком случае:

char *f() {
char lala[10];
return lala;
}

int main() {
printf("%s", f());
return 0;
}


"Строковые типы в C"
Отправлено pavlinux , 30-Июн-14 18:53 
> warning: function returns address of local variable

Ну правильно - в ресторан со своими напитками нельзя!
Либо тут покупай, либо не занимай столик.

> Это говорит компилятор примерно в таком случае:
> char *f() {
>  char lala[10];
>  return lala;
> }
> int main() {
>  printf("%s", f());
>  return 0;
> }

Надо как "настоящие" кодеры - объявить lala[10] как глобальную переменную :)
<offtop> Первый признак - чем больше глобальных переменных, тем дол..ёбистей программер :)</offtop>


char lala[10];
char *f() {
       return lala;
}
int main() {
     return printf("%s", f());
}


"Строковые типы в C"
Отправлено noisebringer , 30-Июн-14 20:27 
Меня только одно беспокоит.
Для того чтобы функция могла возвращать указатель, нужно чтобы в ней делался alloc какого-то количества памяти. А если делается alloc, то его нужно free. А если перед окончанием функции сделать его free, то, по идее, это значит что память где хранится результат и куда в дальнейшем будет ссылаться основной код как бы free и в любой момент может быть потерта.
Но если не в конце функции, то где делать это free.

P.S. Спасибо за лестное замечание. На данный момент глобальные переменные отсутствуют :)


"Строковые типы в C"
Отправлено Аноним , 30-Июн-14 20:43 
> Меня только одно беспокоит.

Твой доктор беспокоится ещё больше. Он уже произносил "мы его теряем! " ....

> Для того чтобы функция могла возвращать указатель, нужно чтобы в ней делался
> alloc какого-то количества памяти.

Похоже зря твой доктор волнуется. Мы тебя уже потеряли, спи спокойно моск noisebringer'a ...



"Строковые типы в C"
Отправлено noisebringer , 30-Июн-14 20:51 
А вот тут не понял. Чтобы функция могла вернуть ссылку на какую-то область памяти, и в этой области памяти что-то лежало, то нужно сначала выделить эту область, потом сложить туда что-то. А потом вернуть ссылку на эту область.

Но если делается alloc, то где-то должен делаться free. Где?


"Строковые типы в C"
Отправлено pavlinux , 01-Июл-14 02:35 
> А вот тут не понял. Чтобы функция могла вернуть ссылку на какую-то
> область памяти, и в этой области памяти что-то лежало, то нужно
> сначала выделить эту область, потом сложить туда что-то. А потом вернуть
> ссылку на эту область.
> Но если делается alloc, то где-то должен делаться free. Где?

char *myfunc() { /* тут объявили, адрес ужо есть */
   char *lala = (char *)malloc(10);
   return lala;
}

// Чо происходит?!: *myfunc указывает на lala, *lala на 10-байтный кусок.

void main() {

   char *dudu = myfunc();  // dudu -> myfunc -> lala -> 10;
   free(dudu);  //
}

Отседа вывод - можно сделать даже так:

void main() {
   free(myfunc());
}


"Строковые типы в C"
Отправлено noisebringer , 01-Июл-14 05:46 
Так я и предполагал, так я и сделал :)
Указатели на функции. Видел краем глаза, но пока возиться не охото, но они быстрее говорять.

"Строковые типы в C"
Отправлено noisebringer , 01-Июл-14 09:38 
Ой. Перепутал :) Не указатель на функцию :)
В общем идею уяснил :)

"Строковые типы в C"
Отправлено pavlinux , 01-Июл-14 21:04 
> Указатели на функции.

Тоже можно, но через ж...у


char *myfunc() {
        char *lala = (char *)malloc(10);
        return lala;
}

void main() {

        char* (*dudu)() = myfunc;
        (*dudu)();
        free(dudu);
}



"Строковые типы в C"
Отправлено Andrey Mitrofanov , 02-Июл-14 10:02 
>         free(dudu);

malloc(sizeof) + memcpy забыл для полного комплекта. </code review>


"Строковые типы в C"
Отправлено noisebringer , 02-Июл-14 12:19 
Насколько я знаю это не через ж**у, а так быстрее работать будет. Указатели на функции вроде как быстрее.

"Строковые типы в C"
Отправлено pavlinux , 02-Июл-14 14:45 
>  вроде как быстрее.

Как быстрее, это уже следующий уровень, после K&R
Затем: Как меньше.
Потом: Как меньше и быстрее.
И последний: А ну вас в ж...у, все равно никто не оплачивает. Ушел на C++/PHP/HTML/QT/JS/...


"Строковые типы в C"
Отправлено noisebringer , 02-Июл-14 19:41 
K&R?

"Строковые типы в C"
Отправлено anonymous , 03-Июл-14 00:32 
> Насколько я знаю это не через ж**у, а так быстрее работать будет.
> Указатели на функции вроде как быстрее.

Да-да, послушай идиотов. Его free(dudu) равнозначен free(myfunc), что являет собой адрес функции, который с динамической памятью связан чуть менее, чем никак. И покажи мне того полудурка, который что-то сказал о "быстрее" и "указатели на функции". Вся ветка вообще бред немыслимый, беги отсюда пока таким же не стал, мой тебе совет.


"Строковые типы в C"
Отправлено pavlinux , 03-Июл-14 02:00 
>> Насколько я знаю это не через ж**у, а так быстрее работать будет.
>> Указатели на функции вроде как быстрее.
> Да-да, послушай идиотов. Его free(dudu) равнозначен free(myfunc),

Ты всех авторов ядра назвал лохами!
На изучай, только как школу закончишь:  https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux....

> что являет собой адрес
> функции, который с динамической памятью связан чуть менее, чем никак.

Ога, ваще не связан, ну разве только, что указывает на кусок динамической памяти,
а так да... ваще никак..

> И покажи мне того полудурка, который что-то сказал о "быстрее" и "указатели
> на функции". Вся ветка вообще бред немыслимый, беги отсюда пока таким
> же не стал, мой тебе совет.

Толсто


"Строковые типы в C"
Отправлено Andrey Mitrofanov , 03-Июл-14 09:24 
>>Его free(dudu) равнозначен free(myfunc),
> Ты всех авторов ядра назвал лохами!
> На изучай, только как школу закончишь:  torvalds/linux.git/tree/mm/slab.c
> Толсто

"Строковые типы в C"
Отправлено anonymous2 , 03-Июл-14 20:18 
Собери свой выхлоп, прочитай ради приличия выхлоп компилятора, запусти полученный бинарник.
Запустил? Теперь забейся в угол и рыдай, бессмысленный бот.

"Строковые типы в C"
Отправлено pavlinux , 04-Июл-14 02:40 
> Собери свой выхлоп, прочитай ради приличия выхлоп компилятора,

Пффф... придумал тоже. У меня тут целый зоопарк кодеров за меня это делает.


"Строковые типы в C"
Отправлено anonymous , 03-Июл-14 00:21 
Форум на опеннете все такой же детсад и раковник, анонимус вахуе.

> 1) char *lala;

Указатель как указатель, значение мусор.

> 2) char *lala = "lala";

Указатель на статичную строку (далее литерал), кстати const char *, т.к. "lala" имеет именно такой тип.

> 3) char lala[] = "lala";

Автоматический массив из пяти char'ов, скопированный из литерала. Массив не указатель.

> 4) char lala[4];

Автоматический массив из четырех char'ов с мусором.

> 5) char lala[4] = "lala";

Автоматический массив из четырех char'ов, скопированный из литерала. Си-строкой не является.

> 6) char *lala = (char *) malloc (sizeof(char) * 4);

Динамический массив из четырех char'ов. Си-строкой не является, т.к. внутри мусор. Канонично "= malloc(4)" без каста.

> Может быть существуют ещё варианты, но мне пока что повстречались только эти.

Подружись с к-н книжкой, не надо тыкать пальцем в небо и искать себе подобных.
Си-строка это последовательность char'ов, заканчивающаяся нулевым символом ('\0'). "lala" это 5 символов (ноль неявный). Другие последовательности по определению строками не являются. Четырех-символьный массив не сможет содержать "lala", потому что не хватает места для конечного нуля. Где находится строка -- неважно, но это может быть автоматическая память (стек), динамическая (malloc), или статическая (литералы и глобальные массивы (не указатели)). Указатель и массив условно взаимозаменяемы, если говорить по-детсадовски, т.к. оба являют собой адрес первого символа (но типы имеют разные; почему и как -- RTFM).

> За ранее благодарен.


"Строковые типы в C"
Отправлено pavlinux , 03-Июл-14 02:02 
> Си-строка это последовательность char'ов, заканчивающаяся нулевым символом ('\0').

И кто тут идиот?! :D В Си ваще нет строк, а ноль в конце это для лохов,
которые границы не указывают.

> Четырех-символьный массив не сможет содержать "lala",

char lala[4] = {'l','a','l','a'};  Всё пиштец, массив, 4 символа.  
и прикинь, даже в stdout заслать можно  write(1, lala, 4);

>  Указатель и массив условно взаимозаменяемы,

Шёл бы ты мимо.


"Строковые типы в C"
Отправлено datswd , 04-Ноя-14 18:49 
Результатом стало следующее.

Для того чтобы в C по-человечески работать с строками была создана библиотека mstring, функции которой выполняя операции со строками выделяют соответствующее количество памяти в куче.

------mstring.h
char* Msprintf(char* To, char* Fmt, ...);
//форматированный вывод в строку To с заменой её содержимого

char* MCsprintf(char* To, char* Fmt, ...);
//форматированный вывод в конец строки To

char* Mstrcat(char* CatTo, char* ToCat);
//Вывод строки ToCat в переменную CatTo

char* Mstrcpy(char* CpyTo, char* ToCpy);
//Копирование строки ToCpy в строку CpyTo

int IsPosDigit(char* ToCheck);
//Является ли строка ToCheck положительным числом, то есть все символы 0-9

И со строкой работать нужно вот так вот.

char* MyString = NULL //Определяем указатель

int I = 5;
MyString = Msprintf(MyString, "lalala blblb %i", I); //Делаем форматированный вывод в строку MyString
printf("%s", MyString); //Выводим строку MyString

if(MyString) free(MyString); //Если MyString не NULL освобождаем выделенную память


Ну и собственно исходный код библиотеки.


------mstring.c

char* MCsprintf(char* To, char* Fmt, ...) {
    va_list Ptr;
    va_start(Ptr, Fmt);
    int L = vsnprintf(NULL, 0, Fmt, Ptr);
    va_end(Ptr);
    int M = To ? strlen(To) : 0;
    To = (char *)realloc(To, (L + M + 2) * CHAR_SIZE);
    va_start(Ptr, Fmt);
    vsprintf(To + M, Fmt, Ptr);
    va_end(Ptr);
    return To;
}

char* Msprintf(char* To, char* Fmt, ...) {
    va_list Ptr;
    va_start(Ptr, Fmt);
    int L = vsnprintf(NULL, 0, Fmt, Ptr);
    va_end(Ptr);
    if(To) free(To);
    To = (char *)calloc((L + 2), CHAR_SIZE);
    va_start(Ptr, Fmt);
    vsprintf(To, Fmt, Ptr);
    va_end(Ptr);
    return To;
}

int IsPosDigit(char *ToCheck) {
    if(ToCheck && strlen(ToCheck)) {
        int I = 0;
        for(I = 0; I < strlen(ToCheck); I++) if(!isdigit(ToCheck[I])) return 0;
        return 1;
    }
    else return 0;
}

char* Mstrcat(char* CatTo, char* ToCat) {
    int P = CatTo ? strlen(CatTo) : 0;
    CatTo = (char*)realloc(CatTo, (P + strlen(ToCat) + 2) * CHAR_SIZE);
    strcpy(CatTo + P, ToCat);
    return CatTo;
}

char* Mstrcpy(char* CpyTo, char* ToCpy) {
    if(ToCpy) {
        if(CpyTo) free(CpyTo);
        CpyTo = (char*)calloc(strlen(ToCpy) + 2, CHAR_SIZE);
        strcpy(CpyTo, ToCpy);
    }
    return CpyTo;
}


"Строковые типы в C"
Отправлено pavlinux , 04-Ноя-14 19:46 
> Для того чтобы в C по-человечески работать

Оптимист :)


"Строковые типы в C"
Отправлено noisebringer , 05-Ноя-14 16:40 
>> Для того чтобы в C по-человечески работать
> Оптимист :)

Спасибо. :)
А что вы думаете о самом подходе к работе со строками?


"Строковые типы в C"
Отправлено pavlinux , 05-Ноя-14 18:26 
> А что вы думаете о самом подходе к работе со строками?

Хреново. Точнее банально.

Нет проверки размеров строк.
Нет проверки malloc и Сo.
Нет поддержки UTF8/16/32
strcpy/strlen - легко Досятся
куча NULL-dereference  
+2 - какой-то непонятный констант.  


"Строковые типы в C"
Отправлено datswd , 10-Ноя-14 18:10 
>> А что вы думаете о самом подходе к работе со строками?
> Хреново. Точнее банально.
> Нет проверки размеров строк.
> Нет проверки malloc и Сo.
> Нет поддержки UTF8/16/32
> strcpy/strlen - легко Досятся
> куча NULL-dereference
> +2 - какой-то непонятный констант.

Не без этого :) И у мастерорв бывают люпы.
А какой подход используете вы?

P.S. Шутка :)


"Строковые типы в C"
Отправлено datswd , 10-Ноя-14 18:11 
>> А что вы думаете о самом подходе к работе со строками?
> Хреново. Точнее банально.
> Нет проверки размеров строк.
> Нет проверки malloc и Сo.
> Нет поддержки UTF8/16/32
> strcpy/strlen - легко Досятся

Что значи досятся? Переполняются?
> куча NULL-dereference
> +2 - какой-то непонятный констант.


"Строковые типы в C"
Отправлено NoiseBringer , 12-Янв-15 07:50 
Офигеть конечно, но, мне кажется, что все, кто тут отписывались меня затролили, если так то с...

В библиотеке stdio.h есть функция asprintf, которая как раз-таки позволяет по-человечески работать со строками. И самое в ней интересное, что в ней можно использовать рекурсию, в итоге её можно превратить в strcat с выделением памяти и много-много всего.

Код
    char *lala = NULL;
    asprintf(&lala, "ddd");
    asprintf(&lala, "%saaa", lala);
    printf("%s", lala);
Выведет
dddaaa


"Строковые типы в C"
Отправлено Alex_S , 13-Янв-15 10:11 
>[оверквотинг удален]
> работать со строками. И самое в ней интересное, что в ней
> можно использовать рекурсию, в итоге её можно превратить в strcat с
> выделением памяти и много-много всего.
> Код
>     char *lala = NULL;
>     asprintf(&lala, "ddd");
>     asprintf(&lala, "%saaa", lala);
>     printf("%s", lala);
> Выведет
> dddaaa

   free только делать придется

   а откуда вообще такая тяга к динамической аллокации строк ?
  вон под ddd - константа вообще  -  у тебя указатель потерялся же , утечка будет , не  ?


"Строковые типы в C"
Отправлено NoiseBringer , 17-Янв-15 08:10 
>    free только делать придется

Это само собой.

>    а откуда вообще такая тяга к динамической аллокации строк ?

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

>   вон под ddd - константа вообще  -  у
> тебя указатель потерялся же , утечка будет , не  ?

О каком именно участке кода идет речь?



"Строковые типы в C"
Отправлено Alex_S , 19-Янв-15 05:49 

> О каком именно участке кода идет речь?
>     asprintf(&lala, "ddd");
>     asprintf(&lala, "%saaa", lala);

аллокировал память под ddd , lala  на него указывает
потом аллокировал под dddaaa и переписал указатель .  ddd утекло .


"Строковые типы в C"
Отправлено NoiseBringer , 19-Янв-15 06:23 
>> О каком именно участке кода идет речь?
>>     asprintf(&lala, "ddd");
>>     asprintf(&lala, "%saaa", lala);
>  аллокировал память под ddd , lala  на него указывает
>  потом аллокировал под dddaaa и переписал указатель .  ddd утекло
> .

Бывает...


"Строковые типы в C"
Отправлено NoiseBringer , 19-Янв-15 17:08 
>> О каком именно участке кода идет речь?
>>     asprintf(&lala, "ddd");
>>     asprintf(&lala, "%saaa", lala);
>  аллокировал память под ddd , lala  на него указывает
>  потом аллокировал под dddaaa и переписал указатель .  ddd утекло
> .

А если на самом деле.

    char *lala = NULL;
    printf("%p\n", &lala);

    asprintf(&lala, "ddd");
    printf("%p\n", &lala);

    asprintf(&lala, "%saaa", lala ? lala : "");
    printf("%p\n", &lala);

    printf("%s", lala);

Выведет

0x7ffff40cfe68
0x7ffff40cfe68
0x7ffff40cfe68
dddaaa


"Строковые типы в C"
Отправлено pavlinux , 22-Янв-15 02:50 
> А если на самом деле.
> Выведет
> 0x7ffff40cfe68
> 0x7ffff40cfe68
> 0x7ffff40cfe68
> dddaaa

Это всё так, но только в академиеских примерах



"Строковые типы в C"
Отправлено NoiseBringer , 22-Янв-15 14:40 
>> А если на самом деле.
>> Выведет
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> dddaaa
> Это всё так, но только в академиеских примерах

А дальше? Подобными изречениями вы создаете образ дилетанта...


"Строковые типы в C"
Отправлено NoiseBringer , 22-Янв-15 15:26 
>> А если на самом деле.
>> Выведет
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> dddaaa
> Это всё так, но только в академиеских примерах

Теперь понял о чём речь и написал об этом чуть ниже.

Мог бы конечно извиниться, но не хочется, потому что сказал А, говори и Б. А если не хочется Б говорить, то не говори и А.


"Строковые типы в C"
Отправлено pavlinux , 24-Янв-15 23:02 
> что сказал А, говори и Б

Лень и поэтому готов признать себя какашкой :)


"Строковые типы в C"
Отправлено Аноним , 31-Янв-15 10:16 
> Лень и поэтому готов признать себя какашкой :)

У, павлин, теперь ты не отвертишься. В букмарки :)


"Строковые типы в C"
Отправлено NoiseBringer , 17-Янв-15 08:13 
>    а откуда вообще такая тяга к динамической аллокации строк
> ?

Ну или например запрос к базе, который может вернуть как 10 байт так и 10000 байт. Можно Можно конечно сделать массив, который будет постоянно занимать в памяти максимально возможную длинну (например 20000 байт), а можно динамически обработать.



"Строковые типы в C"
Отправлено pavlinux , 22-Янв-15 02:51 
>    free только делать придется

alloca(); но с ней всё сложно, особо для серьёзных программ.  


"Строковые типы в C"
Отправлено Alex_S , 22-Янв-15 05:05 
>>    free только делать придется
> alloca(); но с ней всё сложно, особо для серьёзных программ.

  экзотичненько , чо

  asprintf использует  malloc  ,
  хотя можно и свою имплементацию наваять ..


"Строковые типы в C"
Отправлено Alex_S , 22-Янв-15 05:09 

а зачем пост потерли про указатели  ? есть что-то нецензурное в том факте, что

  printf("%p\n", &lala);

   выведет адрес указателя , который не изменится,
   но содержимое его перетрется вторым вызовом  asprintf-a  и доступ к ddd  будет таки потерян ?

  


"Строковые типы в C"
Отправлено NoiseBringer , 22-Янв-15 15:25 
> а зачем пост потерли про указатели  ? есть что-то нецензурное в
> том факте, что
>   printf("%p\n", &lala);
>    выведет адрес указателя , который не изменится,
>    но содержимое его перетрется вторым вызовом  asprintf-a  
> и доступ к ddd  будет таки потерян ?

Вы, таки, были правы.
Проблема была в том, что я был абсолютно уверен в 2х вещах. Во-первых, я думал, что если несколько раз на один и тот же указатель вызвать malloc, то будет ошибка. Оказывается нет. Во-вторых, исходя из первого, я думал, что asprintf использует realloc.

И в самом деле утекает память. :)

P.S. Извиняюсь за то, что попросил модераторов грохнуть ваши сообщения, ибо посчитал их абсолютным бредом :)


"Строковые типы в C"
Отправлено pavlinux , 22-Янв-15 05:36 
>   хотя можно и свою имплементацию наваять ..

alloc() надо применять только по месту, никаких библиотек и шаблонов.