LINUX.ORG.RU

си C99

 


2

1

Уважаемые форумчане. Что Вы думаете по поводу использования этого стандарта? Стоит ли его использовать? И использует ли кто либо вообще. Столкнулся с предупреждением вида:

warning: universal character names are only valid in C++ and C99 [enabled by default]
Это из за значения юникода (типа \u2663) в массиве char, обойти(сь) могу, не использовать. Но всё-таки?

★★★

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

вполне являются, особенно когда это правда :)

Надо аргументировать, например, С++ ублюдство т.к.:

- использует убогий препроцессор;
- имеет UB вроде разыменовывания указателей, «i = ++i + i++» и пр.;
- имеет платформозависимые типы, соглашения об экспорте/импорте символов, упаковке данных и пр;
- имеет множество реализаций, не всегда можно собирать под свежий C99 C++14;
- имеет скудную стандартную библиотеку, даже без контейнеров;
- что не мешает имеет всякие небезопасные sprintf и пр, которые легко могут записать что-нибудь в левый участок памяти, но которые никто не собирается выкидывать из стандарта.

Ну и т.д.

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

Все пункты актуальны для Си.

Да ладно...

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

С++ — очень сложный язык. Ты еще с пхытоном сравни... Хотя, пхытон даже сложней, чем С++.

не, бедон простой, он просто наркоманский. а С++ невероятно сложен.

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

Объективно С — наилучший язык программирования.

Объективно у тебя нет аргументов.

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

С, в отличие от долбаных крестов, ещё и компилится со скоростью света практически.

Для любых целей

low-level на сишке золотой, а высокоуровщину – на лиспах.
Меня лично невероятно вставляет кложура (хоть она и отталкивается от жабьей экосистемы). И ClojureScript.

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

дай угадаю,тот же самый школьник strikes back?

Блин, точно, snprintf тоже ж дефективный:

#include <stdio.h>

main() {
    char buf[2];
    int n=snprintf(buf, 2, "%d", 10);

    printf("%s\n", buf );
    printf("%d\n", n );
}

А еще его аргумент и результат имеют разные типы, в том числе не только знаковые/беззнаковые, но и разного размера для популярных платформ. Кстати, а ведь хороше же, что есть еще asprintf, vprintf, vdprintf, vsnprintf, vnprintf, wprintf, dprintf, fprintf, printf, vfprintf, vasprintf, sprintf_s, _snprintf, swprintf, fwprintf, _fprintf_l, fwprintf, _fwprintf_l и пр. и пр. Сразу видно богатый набор возможностей и Ъ-подход. Причем, что крайне удобно - часть функций платформоспецифичные. Это же все не просто так, это для байто%бства без смысла написания эффективного кода. Ну а так как везде поддержка С разная, кто-то еще не умеет С99 и т.д., то в коде просто надо написать:

#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
#  ifndef HAVE_VSNPRINTF
#    define HAVE_VSNPRINTF
#  endif
#endif

#if defined(__CYGWIN__)
#  ifndef HAVE_VSNPRINTF
#    define HAVE_VSNPRINTF
#  endif
#endif

#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
#  ifndef HAVE_VSNPRINTF
#    define HAVE_VSNPRINTF
#  endif
#endif

#ifndef HAVE_VSNPRINTF
#  ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
   but for now we just assume it doesn't. */
#    define NO_vsnprintf
#  endif
#  ifdef __TURBOC__
#    define NO_vsnprintf
#  endif
#  ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
#         define vsnprintf _vsnprintf
#      endif
#    endif
#  endif
#  ifdef __SASC
#    define NO_vsnprintf
#  endif
#  ifdef VMS
#    define NO_vsnprintf
#  endif
#  ifdef __OS400__
#    define NO_vsnprintf
#  endif
#  ifdef __MVS__
#    define NO_vsnprintf
#  endif
#endif

/* unlike snprintf (which is required in C99, yet still not supported by
   Microsoft more than a decade later!), _snprintf does not guarantee null
   termination of the result -- however this is only used in gzlib.c where
   the result is assured to fit in the space provided */
#ifdef _MSC_VER
#  define snprintf _snprintf
#endif

Ну а т.к. нужной функции может и не быть, надо всего-лишь в месте использования писать так:

#ifdef NO_vsnprintf
#  ifdef HAS_vsprintf_void
    (void)vsprintf((char *)(state->in), format, va);
    for (len = 0; len < size; len++)
        if (state->in[len] == 0) break;
#  else
    len = vsprintf((char *)(state->in), format, va);
#  endif
#else
#  ifdef HAS_vsnprintf_void
    (void)vsnprintf((char *)(state->in), size, format, va);
    len = strlen((char *)(state->in));
#  else
    len = vsnprintf((char *)(state->in), size, format, va);
#  endif
#endif

Пример кода взят из zlib.

П.С. С++ в этом плане почти так же уродлив, наследственность как-никак.

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

И если кто-то будет оправдывать подобное уродство производительностью:

https://github.com/nodeca/pako

На JavaScript реализация быстрее сишной. И это логично, как минимум потому-что JIT для конкретной железки сможет сгенерировать более эффективный блоб, чем то, что выдаст компилятор С под среднепофигисткий i386 или amd64, например.

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

С++ в этом плане почти так же уродлив

почему «почти»? libc в С++ тот же самый, просто у мелкомягких он устарел. ну или можно вместо snprintf использовать std::string operator +. javascript станет еще быстрее - все довольны.

кстати, а что, в распоследних вижуалах нет snprintf? звучит дико, если учесть что была обещана поддержка c99...

ps по твоей же ссылке, автор таки пишет, что на js медленнее. пофиксь свой ингриш.

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

почему «почти»? libc в С++ тот же самый

В С++ принято написать так:

of << "Value: " << n << ", " << s << '\n';

Данный метод имеет как свои преимущества, так и недостатки. Ну или используют библиотеки вроде boost format, которая более продвинутая чем printf.

ps по твоей же ссылке, автор таки пишет, что на js медленнее. пофиксь свой ингриш.

По моей ссылке два бенчмарка, для старой и новой ноды. Алсо мнение автора на ЛОР:

скорость JS vs C. Эпизод 3.

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

принято написать

ушел спать

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

В С++ принято написать так:

ни разу не видел, чтобы в C++ кто-то так строки форматировал. но тебе, конечно, виднее.

По моей ссылке два бенчмарка, для старой и новой ноды.

угу, но словами написано: «Almost as fast in modern JS engines as C implementation (see benchmarks).»

а сами бенчмарки я не распарсил. есть где-то описание, что эти циферки значат?

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

ага, вроде разобрал

inflate-pako x 97.52 ops/sec
inflate-zlib x 60.32 ops/sec

очень даже неплохо. скорее всего, в бенчмарке ошибка, типа флаги оптимизации забыли, но все равно забавно.

кстати, почему в 1м бенче сишная версия на 10ops/sec быстрее? другое железо использовалось?

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

ни разу не видел, чтобы в C++ кто-то так строки форматировал. но тебе, конечно, виднее.

Самое банальное:

google://C++ int to string

Увидишь много предложений использовать ostringstream. С С++11 уже неактуально (to_string), но раньше даже такие простые вещи «форматировали» через <<. Про вывод в cout и говорить не стоит.

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

бггг. и почему я не удивлен :))

Странная ирония, ведь ostringstream для этой задачи мало отличается sprintf. И то и другое комбайн используемый от безысходности. Вот только в C++ уже появился to_string, а что там в С, itoa/ftoa уже в стандарте или приходится микроскопом printf пользоваться? Или по старинке - препроцессор + собственная реализация на всякий случай?

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

itoa/ftoa

this

уже в стандарте

нет

или приходится микроскопом printf пользоваться?

упрлс?

Или по старинке - препроцессор + собственная реализация на всякий случай?

по старинке itoa/ltoa/ftoa/... (их есть везде, а там где нету - можно сделать за пару минут)

иногда snprintf, ога, например когда надо hex, или более сложное форматирование, чем просто int->string

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

уже в стандарте

нет

Окай

упрлс?

Что не так?

по старинке itoa/ltoa/ftoa/... (их есть везде, а там где нету - можно сделать за пару минут)

А, ну т.е. как всегда - еще раз обмазаться препроцессором и еще раз написать свою неоптимальную реализацию. Кстати, тут тоже есть свой зоопарк нестандартных функций - itoa, lltoa, ltoa, ftoa, _itoa, _itoa_s, _i64toa, utoa, _ui64toa, ulltoa, itow, _itow, _i64tow и пр. Но это, очевидно, норма, даже для функций, которым не нашлось места в стандарте.

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

их есть везде

Кстати, весьма неожиданное заявление от человека, который рассказывал о недоступности С++11. Вот у меня в glibc нет itoa:

~$ cat ./test2.c
#include <stdio.h>
#include <stdlib.h>

int main ()
{
  int i=0;
  char buffer [33];
  itoa (i,buffer,10);
  return 0;
}
~$ gcc-4.9 -Wall ./test2.c
./test2.c: In function 'main':
./test2.c:8:3: warning: implicit declaration of function 'itoa' [-Wimplicit-function-declaration]
   itoa (i,buffer,10);
   ^
/tmp/cciqlCEq.o: In function `main':
test2.c:(.text+0x35): undefined reference to `itoa'
collect2: error: ld returned 1 exit status

У меня неправильный GNU/Linux, или ты просто не рассматриваешь его как интересную платформу?

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

Зачем itoa, если snprintf удобней?

Удобней, это, например, в rust - n.to_string(), а тут выбор между нестандартной функцией и большим оверхедом на простой операции.

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

ну тогда snprintf

(драматично) Это же жутко неэффективно! Это прямо как..., как... С++!!!

П.С. а, если серьезно sprintf сливает версии itoa на sse2 на порядки:

https://github.com/miloyip/itoa-benchmark/raw/master/result/corei7920@2.67_wi...

Что как-бы грустно.

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

Ну там где нужно много чисел в строки перегонять с макс скоростью - лучше спец функцию и написать, даже с фиксированным основанием, а не в стиле atoi.

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

Btw, ты ведь понимаешь, что у крестового tostring оверхед еще больше чем у snprintf?

Посмотри на ссылку выше - sprintf имеет очень большой оверхед сам по себе, он явно больше, чем создание std::string. Но, учитывая, что в том же glibc разработчики забили большой половой орган и реализовали to_string через *printf - да, в GNU/Linux с libstdc++ оверхед будет больше. В Visual надо смотреть, может они не схалтурили.

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

Ты эту жесть видел вообще? Ну и как ее переносить, скажем, на ARM? Писать другой велосипед? Аппаратно-зависимые части — это плохо. Я вот, например, с полчаса убил как-то, когда пытался понять, какого черта один мой велосипед не заводится на ARM, а оказалось банально: я для вычисления log2 использовал чисть i386 ассемблерную команду. Поменял на то, что есть и там, и там, все ОК, но на i386 теперь она работает на несколько тактов дольше.

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

С++ — очень сложный язык

Не очень. А большая часть проблем у него от Си.

Хотя, пхытон даже сложней, чем С++

Мда...

Объективно С — наилучший язык программирования.

Это как раз твой субъективный взгляд. Что тут объективного ты нашел? Аргументов от тебя так и не видно.

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

А большая часть проблем у него от Си

Нет, это у плюсеров проблемы, т.к. многие из них считают, что знают С++, а фактически пишут на сях с классами!

Что тут объективного ты нашел?

Ты хотя бы статистику изучи. На чем подавляющее большинство софта написано? Ну и давай, поищи модули ведра на бидоне или плюсерах.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Hertz

С, в отличие от долбаных крестов, ещё и компилится со скоростью света практически.

Скорость компиляции крестов зависит от кода на крестах. Если ты будешь писать без шаблонов, скорость компиляции будет сопоставима.

low-level на сишке золотой, а высокоуровщину – на лиспах.

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

Меня лично невероятно вставляет кложура

Неплохая штука. Но речь не о ней сейчас.

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

минимальные средства абстракции (которых в Си практически нет)

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

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

А большая часть проблем у него от Си

Нет

вот тут анон приводил уже

Ты хотя бы статистику изучи. На чем подавляющее большинство софта написано?

Точной такой статистики нет. И многие вещи написаны на сях, потому, что когда их начинали писать, С++ не был стабилен.

Ну и давай, поищи модули ведра на бидоне или плюсерах.

Зачем мне это? Скорее всего, я бы писал модуль ядра на С.

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

А нет их потому, что они не нужны. Тебе тяжело скопипастить код, если макрос лень писать?

Ты серьезно? Копипастить код?

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

Скорее всего, я бы писал модуль ядра на С.

Вот. Ты и признал, что С лучше!

Ты серьезно? Копипастить код?

Ну, если макросы не хочешь... Я обычно стараюсь макросами выходить из положения. Скажем, нужна нам функция, работающая с double, uint8_t и int32_t. Делаем макрос, не зависящий от типа и три раза его вставляем с разными типами. Все, получаем аналог плюсерских шаблонов, которые в конечном итоге и разворачиваются в три разных функции.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Deleted

-std=gnu99, однако там ничего С99-специфичного, вроде, нет.

будет. Vendor lock-in оно такое. Будет собираться лишь с gcc пропатченым в RH.

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

так нельзя использовать?

ну можно. Можно и так

const char* s = "♠";

Твой warning возникает в случае

char c = '♠';
Если я правильно путаю. Такого присваивания вообще лучше избегать, даже без UTF-8, т.к. знаковость char вообще говоря не определена.

а c99 это массивы переменной длины и однострочные комментарии.

от однострочных комментариев вреда нет. А вот с массивами переменной длинны на стеке ты можешь сесть в лужу. Лучше не шути со стеком, если не понимаешь, как он устроен.

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

А что с ними не так?

в сишке и без этого грабли на каждом шагу.

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

Можно в заголовке цикла for создавать переменную счётчика, к примеру

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

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

if (*ptr < 0x80 || *ptr > 0xBF)

а теперь иди и проверь свой нерабочий говнокод. (он заработает тогда, и только тогда, когда компилятор догадается, что 0x80 это unsigned int).

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

Это неправда. Пример выше посмотри. unique_ptr ничего лишнего не делает.

на самом деле делает: плодит лишнюю сущность «auto p» на стеке для эмуляции управления памятью.

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

Ты не только клоун, но и дегенерат. Размер void* p (в первом случае) и std::unique_ptr<void> p (во втором случае) одинаков.

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