На мой взгляд, наилучший вариант — возвращать статический буфер. Минусы: в клиенском коде зачастую придется копировать эту строчку, плюс в многопоточном варианте скорее всего будет ой-ой. Варианты возврата динамически выделенного буфера и модификации API отметаем. Говорят, есть вариант получе. Найти не смог, сами ответ мне не дали, сославшись на то, что не комментируют корректность ответов. Кроме этих трех вариантов ничего в голову не приходит, да и не гуглится. Ваши варианты?
Яб вообще поинтересовался что за задача такая. const char * как бы намекает, что менять буфер не нужно извне. Может там захардкоженная строка вообще? :D
Сейчас пришла в голову идея: использовать достаточно большой статический буфер, записывать результат, выставлять \0, возвращать результат на начало, откуда мы заполняли. При следующем вызове начинать записывать после этого \0 и т.д., пока в буфер помещается результат, иначе переходить к его началу. Если размер возвращаемой строк примерно известен, можно оценить размер буфера на, скажем, десять результатов. Это не спасет от проблем с многопоточностью, зато всякие printf(«%s,%s\n», foo(), foo()) пройдут гладко.
Ага, но как только будет переполнение, ты загадишь буфер, который еще кому-то нужен(возможно). Авторы вопроса дураки, скорее всего. А правильного ответа мы не подберем.
Варианты(часть тобой уже перечислена):
- статический буффер
- статический буффер локальный для потока
- динамический буффер
- заранее выделенный большой буффер, аллокация в нем и возврат туда(пишем свой вариант free)
Остальные способы будут некорректны. Подозреваю, что они просто используют какие-то непереносимые штуки ввиду профнепригодности.
Ежели всё так, как ты расписал, то вариантов больше нет. Может, опять что-то упустил, типа void? Про многопоточный вариант ты сам додумал, или это было в условиях?
Вот это вот ломает всю радость от экономии. Мой вариант дубовый, но простой для понимания. Хотя лучше вообще всегда динамически строки выделять, чтобы не париться.
Можно просто добавить еще один if внутри второго. В вашем случае длинна строки вообще ограничена размером элемента. В моем случае длина строки ограничена размером всего буфера.
Нет, строка динамически как-то заполняется (в зависимости от аргументов, которые я для упрощения убрал, суть не в этом).
Если два раза вызывать эту функцию с одинаковым аргументом, она должна ту же строку вернуть?
А если вызвать сначала с одним, потом с другим, присвоив результат разным указателям, указатели будут указывать на разные буфера?
Если на оба вопроса ответ «да» то надо использовать какой-нибудь malloc. Хотя еще можно выделить достаточно большой статический массив и в него уже писать байтики, при этом можно запоминать, какие передавались аргументы в функцию, и при вызове функции с каким-то аргументом, который ранее уже был, можно возвратить указатель на нужный кусок в статическом массиве. Понятно, что никакого освобождения памяти тут не предусмотрено
На мой взгляд, наилучший вариант — возвращать статический буфер. Минусы: в клиенском коде зачастую придется копировать эту строчку
А необходимость копировать строчку разве не нарушает API?
Самый лучший вариант без требования сохранять API это просто передавать указатель на массив, который надо заполнить.
Если два раза вызывать эту функцию с одинаковым аргументом, она должна ту же строку вернуть?
Содержимое строки то же.
А если вызвать сначала с одним, потом с другим, присвоив результат разным указателям, указатели будут указывать на разные буфера?
Я уже плохо соображаю.
А необходимость копировать строчку разве не нарушает API? Самый лучший вариант без требования сохранять API это просто передавать указатель на массив, который надо заполнить.
Да тоже ломает. Но копировать ее нужно далеко не всегда. Такой метод иногда используется в POSIX.
Но я стопудово через полчаса уже про это забуду, поэтому лучше буду и дальше явным образом переменные выделять, нежели полагаться, что этот __thread сработает.
Варианты возврата динамически выделенного буфера и модификации API отметаем.
Скорее всего ты что-то недопонял, либо у тебя там тотальные плахие люди.
Мы берём за api - функцию с возвращаемой строкой, с условием, что следующий вызов функции уничтожает строку из предыдущего вызова.
У такого кода 2проблема - треадсейв и стекожопа. Единственный смысл который я вижу - захреначить туда маллок.
char * fun(void) {
static void * ptr = NULL;//сюда хреначить кастыли, либо как уже выше говорили пацаны треадлокал, но тут штука ещё в том,
//что поидее у норм аллокатора на кадждый тред свой хипец, но говнари это не учитывают, поэтому треадлокала тут не хватит - хреначить надо синх.
free(ptr);
char kokoko[] = "конст в сишке пишут только низкоквалифицированные специалисты, не юзают структуры в сишке только низкоквалифицированные специалисты";// заменил аутисты на низкоквалифицированные специалисты, а то вдруг забанят.
return memcpy((ptr = malloc(sizeof(kokoko) + 16)) + 16, kokoko, sizeof(kokoko));//это даблфри защита от низкоквалифицированные специалиста.
}
А так задача не имеет смысла, такой апи устарел лет на 20. Хочешь возвращать строковое представление какого-то говна не через кучу - вперёд, возвращай строку в структуре.