LINUX.ORG.RU

Шок от С. Как склеивать строки?

 


13

7

Осваиваю си. Всё шло хорошо пока внезапно не понадобилось склеить строки (константные и переменные). Покурил stackoverflow. Предлагают 2 варианта:

Первый - создать char buf[молись_чтобы_хватило] и делать str(n)cat/sprintf в этот buf.

Второй - использовать asprintf, который расширение, нестандарт и вообще.

Вопрос: как вы склеиваете строки? Может есть какая-нибудь общепринятая либа?

Простите за нубский вопрос

★★★★★

Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от Eddy_Em

Опять какой-нибудь новомодный полуС++?

марш читать стандарт С

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

Кстати, профит UKSM здесь — после calloc() через некоторое время RES упадёт до сравнимого с malloc() значения.

ну если только…

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

А была бы 1024-битная архитектура, можно было бы одной операцией 256 байт обнулять!!!

Eddy_Em ☆☆☆☆☆
()

_Generic
VLA

узнаю для себя много нового, много воды утекло с тех пор как на сях писал, как оказалось

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

Если-бы разрабы какого-нить ФФ юзали-бы calloc

Может, в этом случае они хотя бы думали головой, а не жопой?

Eddy_Em ☆☆☆☆☆
()

Не знаю, будет ли это интересно ТСу, но вот мой вариант. Предупреждаю, что я сам нуб, избалованный Явой, поэтому ни за что не ручаюсь.


#include <stdio.h>
#include <string.h> 

void main(void){
	char * str1 = "Hello, ";
	char * str2 = "World!";
	char str[
		strlen(str1) + strlen(str2) + 4
	];
	strcat(str, str1);
	strcat(str, str2);
	strncat(str, str1, 4);
	printf(str);
}

Вывод:

Hello, World!Hell

Конпелял под Cygwin'ом, изкоробочным gcc. Почитав обсуждение, я сперва впилил strlen(str1) + strlen(str2) + 5, но потом, исправив на 4, разницы не увидел, не знаю, почему. Вот если исправить на 3 — segmentation fault.

--- xDDGx

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

char str[strlen(str1) + strlen(str2) + 4];

в сишке так не принято. Возвращайся в уютное лоно жабы, и больше не лезь сюда.

Почитав обсуждение, я сперва впилил strlen(str1) +strlen(str2) + 5, но потом, исправив на 4, разницы не увидел, не знаю, почему. Вот если исправить на 3 — segmentation fault.

метод тыка тоже не приветствуется.

xDDGx

лолка.

emulek
()
Ответ на: комментарий от i-rinat

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

Да, поспешил я со своим комментом. Нужно было почитать всю ветку :)

andreyu ★★★★★
()

Подскажите, я всё правильно делаю?

 void *_new(size_t size) {
  void *buf = malloc(size);
  if (NULL == buf) {
    puts("Can't allocate memory");
    exit(1);
  }
  return buf;
}
  
#define NEW(type, count) (type *)_new((sizeof(type))*(count))

int *buf = NEW(int, 100)
makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 4)
Ответ на: комментарий от makoven

таких как ты тоже надо убивать. Что тебе мешает написать

int* buf = malloc(sizeof(int)*100);
???

Если ты очень спешишь, и пишешь код в notepad.exe, то используй php.

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

Да ладно тебе бугуртить) Это же умозрительно а не в продакшн

Я тут пытаюсь освоить си методом нахрапа. Попутно возникает множество непониманий. Буду спрашивать тут. Буду рад если кто-нибудь ответит.

Вопрос:

В мане по функции localtime написано, что она возвращает «pointer to a static internal tm object»

Правильно я понимаю, что структура tm создается один раз за всю програму и потом в виде указателя метается по всему коду. И каждый вызов localtime и gmtime в любом месте програмы заполняет эту самую конкретную структуру новыми значениями и возвращает указатель на нее?

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от makoven

Это же умозрительно а не в продакшн

значит тебя надо убивать умозрительно, а не в RL.

В мане по функции localtime

куда ты лезешь?! Это во первых про C++, а ты вроде про C? Во вторых, на кой ляд лезть в интернет?? Там инфа может быть с 1970го года лежит.

Правильно я понимаю, что структура tm создается один раз за всю програму и потом в виде указателя метается по всему коду. И каждый вызов localtime и gmtime в любом месте програмы заполняет эту самую конкретную структуру новыми значениями и возвращает указатель на нее?

да. Это статический объект, он создаётся перед запуском кода, как глобальная переменная. Его структура по POSIX

           struct tm {
               int tm_sec;    /* Seconds (0-60) */
               int tm_min;    /* Minutes (0-59) */
               int tm_hour;   /* Hours (0-23) */
               int tm_mday;   /* Day of the month (1-31) */
               int tm_mon;    /* Month (0-11) */
               int tm_year;   /* Year - 1900 */
               int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
               int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
               int tm_isdst;  /* Daylight saving time */
           };
также интересно:
       The glibc version of struct tm has additional fields

              long tm_gmtoff;           /* Seconds east of UTC */
              const char *tm_zone;      /* Timezone abbreviation */

       defined  when _BSD_SOURCE was set before including <time.h>.  This is a BSD extension, present
       in 4.3BSD-Reno.

       According to POSIX.1-2004, localtime() is required to behave as though  tzset(3)  was  called,
       while  localtime_r()  does  not  have this requirement.  For portable code, tzset(3) should be
       called before localtime_r().

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

В мане по функции localtime

куда ты лезешь?! Это во первых про C++

тред вообще, и ты в частности, продолжает доставлять

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

Зачем-то этот глиб всю стандартную библиотеку переписал в g_*

это часто так делается. Привыкай: придётся тебе юзать ПРАВИЛЬНЫЕ костыли, как в данном проекте принято. В каждом проекте — свои. Только учти, что все они обёртки над glibc(не путать с Glib).

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

да. Это статический объект, он создаётся перед запуском кода, как глобальная переменная.

Вообще-то, сдается мне, у каждого треда будет своя переменная.

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

Вообще-то, сдается мне, у каждого треда будет своя переменная.

неправильно тебе сдаётся:

NOTES The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe. Thread-safe versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are specified by SUSv2, and available since libc 5.2.5.

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

куда ты лезешь?! Это во первых про C++, а ты вроде про C? Во вторых, на кой ляд лезть в интернет??

Лезть следует в man localtime?

да. Это статический объект, он создаётся перед запуском кода, как глобальная переменная.

Ясно, спасибо

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

креститься надо...

posix: This volume of IEEE Std 1003.1-2001 defers to the ISO C standard.

c11: The localtime function returns a pointer to the broken-down time, or a null pointer if the specified time cannot be converted to local time.

при этом ни в одном из источников не упоминается tls

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

Лезть следует в man localtime?

конечно. man 3 localtime точнее. Сразу же предупреждаю, что в разных системах разная glibc(или libc), и соответственно разный мануал. Конечно по большей части там всё уже давно устоялось, но дьявол в деталях.

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

логично

ведь постить чушь — это так весело

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

ты научишь хорошему, да

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

самая актуальная информация — в стандартах (в нашем случае c + posix). при возникновении проблем в man-е можно узнать о глюках версий софта на твоём локалхосте.

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

дело не в реентерабельности, а в тредо-безопасности. Если ты в одном треде запустишь localtime, а в другом треде будешь читать tm, то возможна ситуация, когда ты прочитаешь фигню. Потому есть localtime_r, которую надо кормить своей tm.

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

во-первых, я цитировал c11. во-вторых, по факту он уже много лет присутствует в большинстве компиляторов (стандарт привёл синтаксис этих расширений к общему знаменателю).

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

только в C11 <threads.h> появился, которую еще ни один компилятор не реализовал

треды можно было делать задолго до этого.

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

т.е. ты осилил только первое предложение из цитаты?

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

разговор, вообще-то, про tls.

видимо, у тебя серьёзные когнитивные расстройства. это многое объясняет. в том числе потоки бреда, которыми ты поливаешь этот тред.

anonymous
()
Ответ на: ты научишь хорошему, да от anonymous

самая актуальная информация — в стандартах

она не «актуальная», а правильная. Актуальная как раз в манах. Кроме глюков, в мане есть множество полезных расширений, и уж поверь мне, это не тебе решать, под какую систему писать код. Это в ТЗ прописывается, а не в советах аналитегов ЛОРа.

emulek
()
Ответ на: ты научишь хорошему, да от anonymous

Что-то я запутался. В манах описана GNU версия. В POSIX - общяя для всех, но древняя. И еще где-то есть описания стандартных библиотек для C89, C99 и C11, которые отличаются и от GNU и от POSIX и друг от друга. Так?

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

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

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

В манах описана GNU версия. В POSIX - общяя для всех, но древняя. И еще где-то есть описания стандартных библиотек для C89, C99 и C11, которые отличаются и от GNU и от POSIX и друг от друга. Так?

в манах описана версия, которая на твоём локалхосте. Что-бы там не звиздел анонимус, в мане для каждого расширения указывается, что оно — расширение. Также в мане указана соместимость со стандартами.

А стандартов — да, много разных. Если ты будешь ориентироваться на стандарт, а не на man, то рискуешь написать код, который не заработает даже на твоём локалхосте. Хотя конечно для написания портабельного кода расширения лучше не использовать. Теоретически даже Win POSIX совместимая, а практически — у них своё видение стандартов. И да, POSIX тоже разный бывает.

И да, споры о стандартах тут не редкость, не обращай внимания.

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

Тестовый фреймворк пригодится и для изучения glibc )

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.