Всем доброго времени суток.
Недавно начал использовать язык программирования С. Интересный язык, должен сказать.Вот только не могу до конца разобраться со строками.
Строковую переменную можно определить описанными ниже способами:
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?И какое из этих объявлений для каких случаев лучше подходит?
За ранее благодарен.
> Всем доброго времени суток.
> Недавно начал использовать язык программирования С. Интересный язык, должен сказать.я так понимаю дело дальше абзаца "А давайте напишем программу Hello world ..." не дошло?
>> Всем доброго времени суток.
>> Недавно начал использовать язык программирования С. Интересный язык, должен сказать.
> я так понимаю дело дальше абзаца "А давайте напишем программу Hello world
> ..." не дошло?я так понимаю ответ дальше фразы "я так понимаю дело дальше абзаца "А давайте напишем программу Hello world... не дошло?" не дошел?
> Самый первый вопрос, который рождается в голове, это является ли объявления номер
> 4, 6 идентичными?Нет
4 - массив
6 - указатель
> Тот же вопрос для объявление номер 3 и 5.Нет
3 - массив из 5 символов, а
5 - из 4, причем с выходом за границу массива
> В чём разница между объявлениями 5, 2 и 3?2 - находится в стеке как константа.
3 - в куче, размер массива определен автоматически
5 - в куче, размер определен ручкамиЕдинственный совет - стек лучше не загромождать и не надеятся, что все libc выделяют для него столько же памяти, сколько glibc
В первую очередь хотелось бы поблагодарить за адекватный ответ.
Надеюсь вас сильно не затруднит провести небольшой лик-без :)>> Самый первый вопрос, который рождается в голове, это является ли объявления номер
>> 4, 6 идентичными?
> Нет
> 4 - массив
> 6 - указательЧто из этого проистекает, как это отражается непосредственно на работе программы?
То есть я ведь могу точно так же сделать strcat в lala и из неё, обращаться посимвольно в обоих вариантах.>> Тот же вопрос для объявление номер 3 и 5.
> Нет
> 3 - массив из 5 символов, а
> 5 - из 4, причем с выходом за границу массиваПро пять символов вы имеете в виду нолик в конце?
>> В чём разница между объявлениями 5, 2 и 3?
> 2 - находится в стеке как константа.
> 3 - в куче, размер массива определен автоматически
> 5 - в куче, размер определен ручками
> Единственный совет - стек лучше не загромождать и не надеятся, что все
> libc выделяют для него столько же памяти, сколько glibcТут всё понятно :)
> В первую очередь хотелось бы поблагодарить за адекватный ответ.
> Надеюсь вас сильно не затруднит провести небольшой лик-без :)
>>> Самый первый вопрос, который рождается в голове, это является ли объявления номер
>>> 4, 6 идентичными?
>> Нет
>> 4 - массив
>> 6 - указатель
> Что из этого проистекает, как это отражается непосредственно на работе программы?
> То есть я ведь могу точно так же сделать strcat в lala
> и из неё, обращаться посимвольно в обоих вариантах.Все верно, но массив нельзя использовать как lvalue, то есть, т.е., как выражение слева, например:
char x[4];
char *pt;
x = pt; // Ошибка
> 5 - из 4, причем с выходом за границу массиваНет там никакого выхода! Просто нуля в конце не будет. Из этих соображений
эту строку нельзя напрямую юзать в строковых функциях strcpy, strcmp, printf %s и т.д.
>> 5 - из 4, причем с выходом за границу массива
> Нет там никакого выхода! Просто нуля в конце не будет. Из этих
> соображений
> эту строку нельзя напрямую юзать в строковых функциях strcpy, strcmp, printf %s
> и т.д.Очень благодарен за дельное замечание!
> Нет там никакого выхода! Просто нуля в конце не будет.Правда?
$ ./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]);
}
>> 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]);
До этого я имел дело с языками в которых память может распределяться автоматически, а тут такого дела не оказалось и меня мучал вопрос, как сделать так, чтобы не разводить бред из серии 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);
Надеюсь, что здесь всё написано правильно, за исключением обработки возможных ошибок при распределении памяти, но здесь их можно опустить ибо это пример, и тему можно закрывать :)
> Надеюсь, что здесь всё написано правильно,tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has been started. USA destroyed */
И ваще, это "плохая" строка, забудь про такие фишки (на ближайшие лет 7-8).
Ты либо улетишь за пределы массива, либо затрёшь последний символ.
>> Надеюсь, что здесь всё написано правильно,
> 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[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";
посмотри в ассемблере чего делает - это константная строка, еЯ менять нельзя.
Да - да в ассемблере, тут вам не васик, тут ты по локоть в железе :)
> Да не поможет это. Этот код:
> char tutu[5] = "tutu";
> посмотри в ассемблере чего делает - это константная строка, еЯ менять нельзя.Ага ... сам посмотрел. Для 4.7.2 это больше не так :) Ложет их в .data - то есть менять - можно.
Сорьки - лопухнулся йа :)
>>> tutu[5] = 0; /* Array out of bounds. Kernel panic. Topol-M has been started. USA destroyed */
> To Pavlinux - Нынче пишут "Курс доллара упал до 0" :-)Они ещё напечатают.
>>> Надеюсь, что здесь всё написано правильно,
>> 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 занимают четыре элемента строки.
Благодарен за напоминание :)
> И чем отличается '\0' от просто 0?типами: первый - char, второй - int.
(Но по секрету, char во внутреннем представлении С это int. Только я тебе это не говорил)void main() {
int i;
for (i=0x30; i < 0x80; i++)
write(0, &i, 1);
}вот эта хрень вроде должна напечатать все видимые символы.
> Может быть существуют ещё варианты, но мне пока что повстречались только эти.char *lala[] = {"lala"};
>> Может быть существуют ещё варианты, но мне пока что повстречались только эти.
> char *lala[] = {"lala"};Мусье знает толк в извращениях :)
> Тьфу, ёклмн. Не туда написал сообщение. В общем заинтересованные личности найдут.2) char *lala = "lala";
и словишь разыменование NULL-указателя.
>> Тьфу, ёклмн. Не туда написал сообщение. В общем заинтересованные личности найдут.
> 2) char *lala = "lala";
> и словишь разыменование NULL-указателя.Чей-то вдруг?
>> 2) char *lala = "lala";
>> и словишь разыменование NULL-указателя.
> Чей-то вдруг?lala=NULL; И "Усё пропало, шеф!"
>>> 2) char *lala = "lala";
>>> и словишь разыменование NULL-указателя.
>> Чей-то вдруг?
> lala=NULL; И "Усё пропало, шеф!"Ну надеюсь этот код в конце функции, и пырыменная ляля больше не юзается?
Нашел для себя отличие между вариантами 4 и 6.
Вариант 4 компилятор не дает использовать внутри функций.
> Нашел для себя отличие между вариантами 4 и 6.
> Вариант 4 компилятор не дает использовать внутри функций.Чёй-то вдруг?
char lala[4];
memset(lala, 0, sizeof(lala)/sizeof(lala[0]));По-стандарту - массив не инициализированный, по-gcc - там нули.
и даже printf отработает нормально.
warning: function returns address of local variableЭто говорит компилятор примерно в таком случае:
char *f() {
char lala[10];
return lala;
}int main() {
printf("%s", f());
return 0;
}
> 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());
}
Меня только одно беспокоит.
Для того чтобы функция могла возвращать указатель, нужно чтобы в ней делался alloc какого-то количества памяти. А если делается alloc, то его нужно free. А если перед окончанием функции сделать его free, то, по идее, это значит что память где хранится результат и куда в дальнейшем будет ссылаться основной код как бы free и в любой момент может быть потерта.
Но если не в конце функции, то где делать это free.P.S. Спасибо за лестное замечание. На данный момент глобальные переменные отсутствуют :)
> Меня только одно беспокоит.Твой доктор беспокоится ещё больше. Он уже произносил "мы его теряем! " ....
> Для того чтобы функция могла возвращать указатель, нужно чтобы в ней делался
> alloc какого-то количества памяти.Похоже зря твой доктор волнуется. Мы тебя уже потеряли, спи спокойно моск noisebringer'a ...
А вот тут не понял. Чтобы функция могла вернуть ссылку на какую-то область памяти, и в этой области памяти что-то лежало, то нужно сначала выделить эту область, потом сложить туда что-то. А потом вернуть ссылку на эту область.Но если делается alloc, то где-то должен делаться free. Где?
> А вот тут не понял. Чтобы функция могла вернуть ссылку на какую-то
> область памяти, и в этой области памяти что-то лежало, то нужно
> сначала выделить эту область, потом сложить туда что-то. А потом вернуть
> ссылку на эту область.
> Но если делается 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());
}
Так я и предполагал, так я и сделал :)
Указатели на функции. Видел краем глаза, но пока возиться не охото, но они быстрее говорять.
Ой. Перепутал :) Не указатель на функцию :)
В общем идею уяснил :)
> Указатели на функции.Тоже можно, но через ж...у
char *myfunc() {
char *lala = (char *)malloc(10);
return lala;
}void main() {
char* (*dudu)() = myfunc;
(*dudu)();
free(dudu);
}
> free(dudu);malloc(sizeof) + memcpy забыл для полного комплекта. </code review>
Насколько я знаю это не через ж**у, а так быстрее работать будет. Указатели на функции вроде как быстрее.
> вроде как быстрее.Как быстрее, это уже следующий уровень, после K&R
Затем: Как меньше.
Потом: Как меньше и быстрее.
И последний: А ну вас в ж...у, все равно никто не оплачивает. Ушел на C++/PHP/HTML/QT/JS/...
K&R?
> Насколько я знаю это не через ж**у, а так быстрее работать будет.
> Указатели на функции вроде как быстрее.Да-да, послушай идиотов. Его free(dudu) равнозначен free(myfunc), что являет собой адрес функции, который с динамической памятью связан чуть менее, чем никак. И покажи мне того полудурка, который что-то сказал о "быстрее" и "указатели на функции". Вся ветка вообще бред немыслимый, беги отсюда пока таким же не стал, мой тебе совет.
>> Насколько я знаю это не через ж**у, а так быстрее работать будет.
>> Указатели на функции вроде как быстрее.
> Да-да, послушай идиотов. Его free(dudu) равнозначен free(myfunc),Ты всех авторов ядра назвал лохами!
На изучай, только как школу закончишь: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux....> что являет собой адрес
> функции, который с динамической памятью связан чуть менее, чем никак.Ога, ваще не связан, ну разве только, что указывает на кусок динамической памяти,
а так да... ваще никак..> И покажи мне того полудурка, который что-то сказал о "быстрее" и "указатели
> на функции". Вся ветка вообще бред немыслимый, беги отсюда пока таким
> же не стал, мой тебе совет.Толсто
>>Его free(dudu) равнозначен free(myfunc),
> Ты всех авторов ядра назвал лохами!
> На изучай, только как школу закончишь: torvalds/linux.git/tree/mm/slab.c
> Толсто
Собери свой выхлоп, прочитай ради приличия выхлоп компилятора, запусти полученный бинарник.
Запустил? Теперь забейся в угол и рыдай, бессмысленный бот.
> Собери свой выхлоп, прочитай ради приличия выхлоп компилятора,Пффф... придумал тоже. У меня тут целый зоопарк кодеров за меня это делает.
Форум на опеннете все такой же детсад и раковник, анонимус вахуе.> 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).> За ранее благодарен.
> Си-строка это последовательность char'ов, заканчивающаяся нулевым символом ('\0').И кто тут идиот?! :D В Си ваще нет строк, а ноль в конце это для лохов,
которые границы не указывают.> Четырех-символьный массив не сможет содержать "lala",
char lala[4] = {'l','a','l','a'}; Всё пиштец, массив, 4 символа.
и прикинь, даже в stdout заслать можно write(1, lala, 4);> Указатель и массив условно взаимозаменяемы,
Шёл бы ты мимо.
Результатом стало следующее.Для того чтобы в C по-человечески работать с строками была создана библиотека mstring, функции которой выполняя операции со строками выделяют соответствующее количество памяти в куче.
------mstring.h
char* Msprintf(char* To, char* Fmt, ...);
//форматированный вывод в строку To с заменой её содержимогоchar* MCsprintf(char* To, char* Fmt, ...);
//форматированный вывод в конец строки Tochar* Mstrcat(char* CatTo, char* ToCat);
//Вывод строки ToCat в переменную CatTochar* Mstrcpy(char* CpyTo, char* ToCpy);
//Копирование строки ToCpy в строку CpyToint IsPosDigit(char* ToCheck);
//Является ли строка ToCheck положительным числом, то есть все символы 0-9И со строкой работать нужно вот так вот.
char* MyString = NULL //Определяем указатель
int I = 5;
MyString = Msprintf(MyString, "lalala blblb %i", I); //Делаем форматированный вывод в строку MyString
printf("%s", MyString); //Выводим строку MyStringif(MyString) free(MyString); //Если MyString не NULL освобождаем выделенную память
Ну и собственно исходный код библиотеки.
------mstring.cchar* 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 по-человечески работатьОптимист :)
>> Для того чтобы в C по-человечески работать
> Оптимист :)Спасибо. :)
А что вы думаете о самом подходе к работе со строками?
> А что вы думаете о самом подходе к работе со строками?Хреново. Точнее банально.
Нет проверки размеров строк.
Нет проверки malloc и Сo.
Нет поддержки UTF8/16/32
strcpy/strlen - легко Досятся
куча NULL-dereference
+2 - какой-то непонятный констант.
>> А что вы думаете о самом подходе к работе со строками?
> Хреново. Точнее банально.
> Нет проверки размеров строк.
> Нет проверки malloc и Сo.
> Нет поддержки UTF8/16/32
> strcpy/strlen - легко Досятся
> куча NULL-dereference
> +2 - какой-то непонятный констант.Не без этого :) И у мастерорв бывают люпы.
А какой подход используете вы?P.S. Шутка :)
>> А что вы думаете о самом подходе к работе со строками?
> Хреново. Точнее банально.
> Нет проверки размеров строк.
> Нет проверки malloc и Сo.
> Нет поддержки UTF8/16/32
> strcpy/strlen - легко ДосятсяЧто значи досятся? Переполняются?
> куча NULL-dereference
> +2 - какой-то непонятный констант.
Офигеть конечно, но, мне кажется, что все, кто тут отписывались меня затролили, если так то с...В библиотеке stdio.h есть функция asprintf, которая как раз-таки позволяет по-человечески работать со строками. И самое в ней интересное, что в ней можно использовать рекурсию, в итоге её можно превратить в strcat с выделением памяти и много-много всего.
Код
char *lala = NULL;
asprintf(&lala, "ddd");
asprintf(&lala, "%saaa", lala);
printf("%s", lala);
Выведет
dddaaa
>[оверквотинг удален]
> работать со строками. И самое в ней интересное, что в ней
> можно использовать рекурсию, в итоге её можно превратить в strcat с
> выделением памяти и много-много всего.
> Код
> char *lala = NULL;
> asprintf(&lala, "ddd");
> asprintf(&lala, "%saaa", lala);
> printf("%s", lala);
> Выведет
> dddaaafree только делать придется
а откуда вообще такая тяга к динамической аллокации строк ?
вон под ddd - константа вообще - у тебя указатель потерялся же , утечка будет , не ?
> free только делать придетсяЭто само собой.
> а откуда вообще такая тяга к динамической аллокации строк ?
В процессе разработки, когда ты в душе не ведаешь, насколько могут быть длинными или короткими некоторые строки статическая память оооочень сильно осложняет ситуацию, потому что когда много переменных и ты работаешь над одной областью кода, а тебе выдается segmentation fault, это создает трудности, потому что нужно найти где этот сегментатион и т.д.
> вон под ddd - константа вообще - у
> тебя указатель потерялся же , утечка будет , не ?О каком именно участке кода идет речь?
> О каком именно участке кода идет речь?
> asprintf(&lala, "ddd");
> asprintf(&lala, "%saaa", lala);аллокировал память под ddd , lala на него указывает
потом аллокировал под dddaaa и переписал указатель . ddd утекло .
>> О каком именно участке кода идет речь?
>> asprintf(&lala, "ddd");
>> asprintf(&lala, "%saaa", lala);
> аллокировал память под ddd , lala на него указывает
> потом аллокировал под dddaaa и переписал указатель . ddd утекло
> .Бывает...
>> О каком именно участке кода идет речь?
>> 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
> А если на самом деле.
> Выведет
> 0x7ffff40cfe68
> 0x7ffff40cfe68
> 0x7ffff40cfe68
> dddaaaЭто всё так, но только в академиеских примерах
>> А если на самом деле.
>> Выведет
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> dddaaa
> Это всё так, но только в академиеских примерахА дальше? Подобными изречениями вы создаете образ дилетанта...
>> А если на самом деле.
>> Выведет
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> 0x7ffff40cfe68
>> dddaaa
> Это всё так, но только в академиеских примерахТеперь понял о чём речь и написал об этом чуть ниже.
Мог бы конечно извиниться, но не хочется, потому что сказал А, говори и Б. А если не хочется Б говорить, то не говори и А.
> что сказал А, говори и БЛень и поэтому готов признать себя какашкой :)
> Лень и поэтому готов признать себя какашкой :)У, павлин, теперь ты не отвертишься. В букмарки :)
> а откуда вообще такая тяга к динамической аллокации строк
> ?Ну или например запрос к базе, который может вернуть как 10 байт так и 10000 байт. Можно Можно конечно сделать массив, который будет постоянно занимать в памяти максимально возможную длинну (например 20000 байт), а можно динамически обработать.
> free только делать придетсяalloca(); но с ней всё сложно, особо для серьёзных программ.
>> free только делать придется
> alloca(); но с ней всё сложно, особо для серьёзных программ.экзотичненько , чо
asprintf использует malloc ,
хотя можно и свою имплементацию наваять ..
а зачем пост потерли про указатели ? есть что-то нецензурное в том факте, чтоprintf("%p\n", &lala);
выведет адрес указателя , который не изменится,
но содержимое его перетрется вторым вызовом asprintf-a и доступ к ddd будет таки потерян ?
> а зачем пост потерли про указатели ? есть что-то нецензурное в
> том факте, что
> printf("%p\n", &lala);
> выведет адрес указателя , который не изменится,
> но содержимое его перетрется вторым вызовом asprintf-a
> и доступ к ddd будет таки потерян ?Вы, таки, были правы.
Проблема была в том, что я был абсолютно уверен в 2х вещах. Во-первых, я думал, что если несколько раз на один и тот же указатель вызвать malloc, то будет ошибка. Оказывается нет. Во-вторых, исходя из первого, я думал, что asprintf использует realloc.И в самом деле утекает память. :)
P.S. Извиняюсь за то, что попросил модераторов грохнуть ваши сообщения, ибо посчитал их абсолютным бредом :)
> хотя можно и свою имплементацию наваять ..alloc() надо применять только по месту, никаких библиотек и шаблонов.