LINUX.ORG.RU

Я не знаю как писать на «C» ¯\_(ツ)_/¯.

 , , , ,


2

7

Всем привет, ну начну с того что некоторое время назад решил писать своё поделие, ну вроде сервис в основе которого kore.io и в процессе появились потребности, система тестирования, HTML шаблонизатор, обработка utf-8 под мои потребности ну и то-ли NIH синдром то-ли спортивный интерес (не так важно) пишется всё самостоятельно (не без вашей помощи, за что спасибо), но в процессе так же задумался над переносимостью и... ребят я даже немного потерялся.

Порядок байт. Ну начнём с того что например для обработки utf-8 по всем фронтам побитовые сдвиги и чтение отдельных битов, ну вроде ладно чё, в чём проблема, а проблема например в том что порядок байт разный и что мне определять сначала что у меня sparc64 или i386 а потом уже с учётом этого читать байты с конца или с начала?

Атомарность. Ну хорошо 32bit умирает, но мне пофигу если я пишу библиотеку то я хочу что бы она работала везде, ладно у меня может не быть uint64_t и знание того что где то long 64bit, а где то 32bit и я могу смело (да?) писать unsigned long long и быть уверенным что в 64 битной системе это 64 а в 32 битной это тоже 64 но эмулируется через два 32битных инта и вот тут как бы уже нет гарантий что операции записи переменной или чтения отработают.

Вернусь к типам. Мне нравиться что у меня богатый выбор типов на все случаи жизни и конструкции для создания своих типов, а также смешанные типы (union). ладно я могу «впереди планеты всей» и иметь целевую платформу x86_64, а на остальных... ну ломается логика и х** с ними, но что будет когда придёт x86_128, не ржите я серьёзно если я использую (вынужден) в случае utf-8 использовать битовые операции каков вариант что снова придётся что-то менять. Ах да, касаемо тонны zise_t ptrdiff_t u/int8/16/32/64_t fast хераст и прочих что являются typedef от фундаментальных char/short/int/long/long long/ + signed/unsigned, я правильно понимаю что нет никакой разницы пишу ли я uint64_t или unsigned long long int ?

libc Эмм, с89/с99/с11 где то напрямую отказываются от поддержки стандарта msvc не хочет с99 реализовывать в полной мере, тоесть уже нет гарантий, ладно на дворе почти 2018 надо с11, но и тут glibc не имеет <threads.h> а musl имеет, как при этом всём гарантированно быть уверенным что у меня есть гарантия реализации стандарта. Как жить :D И да в случае если на какой либо системе нет <stdint.h> и я намеренно пишу unsigned long long int подразумевая (на данный момент) uint64_t это нормально?

Ну больше писать не буду хотя есть что, я не профессиональный программист да и просто программистом себя назвать не могу в полной мере, мне нравится «С» и вроде как получается писать что-то что работает на моей машине.Но прихожу к выводу что я не знаю как на нём писать нормальный и переносимый код.

Дайте советы если есть желание или почитать что что-бы просвятиться. У меня есть желание писать железный код, но чем больше я закапываюсь во всём этом тем меньше понимания как собственно его писать железно.

Выдыхаю ::) Ну и по традиции cast сишников i-rinat, beastie, ncrmnt, Iron_Bug, peregrine, xpahos, anonymous_incognito, ncrmnt, DELIRIUM.

Deleted

зачем вы себя насилуете ? не умеете, не нравится, не понимаете ? не пишите и не используйте, займитесь чем то другими в жизни

anonymous ()

Сумбура уйма.

Вердикт простой: не используй C для Web-приложения, это нерациональный выбор инструмента.

Выбери Perl/Python/Java/D/Go/C#, но не Си.

Как минимум, хорошо если в языке будет GC.И тут я на полном серьёзе.

Либо используй C++ и его преимущества, но это тоже не рационально.

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

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

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

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

Давай так: спортивный интерес и переносимость при условии одного разработчика - утопия.

Поиграй с фласком, если хочешь сделать инструмент, за который тебе будут благодарны окружающие, а уже написанные модули потихоньку подключай к питону, раз уж успел написать.

Получишь продукт, а потом будешь страдать оптимизацией.

Deleted ()

что-бы просвятиться

Покушай спагетти с тефтелями и посетит тебя благодать Его Макароннейшества.

redgremlin ★★★★★ ()

читать байты с конца или с начала?

Это в каких случаях? UTF-8 от порядка байт не должен зависеть.

Атомарность.

Для этого существуют атомики.

<threads.h>

В glibc вроде грядёт. Есть реализация на pthreads, которую можно за собой таскать.

<stdint.h>

Есть переносимый вариант.

я намеренно пишу unsigned long long int подразумевая (на данный момент) uint64_t это нормально?

Если выхода нет, то не очень, но можно. А можно завалить компиляцию или проверить sizeof().

У меня есть желание писать железный код

В этом и проблема, это не прагматично. Возможность писать переносимый код ограничивается степенью поддержки стандартов. Где работает стандартный код — хорошо, где не работает — написать аналог или не поддерживать этот вариант. Если что-то позже не будет работать, можно исправить. Учесть всё заранее — не вариант.

xaizek ★★★★★ ()

Если у тебя нет какой-нибудь своей проприетарной стандартной библиотеки для Си, то будет очень больно писать на Си с GLib(которая гномовая). Вряд ли у тебя хип будет забиваться до 15Гб, так что бери Java с netty.

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

Это в каких случаях? UTF-8 от порядка байт не должен зависеть.

Касательно utf-8 есть маркер BOM который указывает в каком порядке располагаются байты, но это маркер его может и не быть и «Символ U+FEFF изображается в UTF-16 последовательностью байтов 0xFE 0xFF (big-endian) или 0xFF 0xFE (little-endian)» - Wikipedia Тесть просто данные перевёрнуты, в случае если я просто в utf-8 при операциях надо учитывать что 4 октета могуть быть в памяти вот так 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx или вот так 10xxxxxx 10xxxxxx 10xxxxxx 11110xxx.

В glibc вроде грядёт. Есть реализация на pthreads, которую можно за собой таскать.

Да вот хочется что-то одно, сейчас вариант таскать с собой musl (который тоже вроде не полный) или то что есть в системе + pthreads.

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

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

Касательно utf-8 ...

Many Windows programs (including Windows Notepad) add the bytes 0xEF, 0xBB, 0xBF at the start of any document saved as UTF-8. This is the UTF-8 encoding of the Unicode byte order mark (BOM), and is commonly referred to as a UTF-8 BOM, even though it is not relevant to byte order.

UTF-8 — поток байт, порядок байт в нём всегда один и тот же. BOM там не нужен.

Да вот хочется что-то одно, сейчас вариант таскать с собой musl (который тоже вроде не полный) или то что есть в системе + pthreads.

Там один единственный заголовок вроде для pthreads. Таскать musl кажется overkill, да и там такой код, что я бы не доверял.

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

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

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

Поиграй с фласком

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

Deleted ()

Какого ответа ты ждёшь? Тут вариант очевиден: обмазаться дефайнами по самое не балуйся. Либо писать на более высокоуровневом языке, например, python, perl, ruby. Но если ты посмотришь исходники интерпретатора, то там тоже все уже обмазались дефайнами.

DELIRIUM ☆☆☆☆☆ ()

Говорят в джаве это всё уже сделано и учтено, даже рекомпиляция для запуска на другом процессоре не нужна вообще.

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

Касательно utf-8 ...

Ну значит я не так понял.

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

Да? Задумался, надо глянуть кишки. Спасибо.

Лучше писать как в общем и разногласия между платформами резрешать по необходимости.

Хочется их вообще избегать, только вот есть уверенность что о некоторых вещах я просто не в курсе ну к примеру я в курсе о модели данных LLР64 и ILP32LL и их разнице, а о каких то моментах не в курсе, вот хотелось бы о них банально знать.

а не пытаться сесть на все стулья сразу

Нуууу, так то да =)

Deleted ()

Порядок байт. Ну начнём с того что например для обработки utf-8

...порядок байт не важен.

например в том что порядок байт разный и что мне определять сначала что у меня sparc64 или i386 а потом уже с учётом этого читать байты с конца или с начала?

Нет. Если ты пишешь побайтно, разбивая инты на байты сдвигами и битовыми операциями, порядок байт тебе не важен. (a << 8) & 0xff это всегда второй по счёту младший байт, на любой архитектуре и независимо от размера a. Если же ты пишешь сразу словами, у тебя есть ntohs/htons/ntohl/htonl, и, опять таки тебе не нужно думать об архитектуре. Если ты думаешь об архитектуре, ты просто напросто велосипедишь их аналоги. Наконец, забудь об этом и используй переносимые форматы - json или protobuf.

Атомарность. Ну хорошо 32bit умирает, но мне пофигу если я пишу библиотеку то я хочу что бы она работала везде, ладно у меня может не быть uint64_t и знание того что где то long 64bit, а где то 32bit и я могу смело (да?) писать unsigned long long и быть уверенным что в 64 битной системе это 64 а в 32 битной это тоже 64 но эмулируется через два 32битных инта и вот тут как бы уже нет гарантий что операции записи переменной или чтения отработают.

Нет никаких гарантий ни на размер, ни на атомарность. Более того, если ты используешь обычную переменную из разных потоков - это однозначное UB. Для размеров есть типы из stdint.h гарантирующий размер, и stdatomic.h обеспечивающий атомарность. Без него у тебя не будет атомарности вовсе.

ну ломается логика и х** с ними, но что будет когда придёт x86_128, не ржите я серьёзно если я использую (вынужден) в случае utf-8 использовать битовые операции каков вариант что снова придётся что-то менять

Ещё раз, для работы utf-8 никаким образом не нужны знания о размерах типов и порядке байт. И если ты будет использовать least типы, у тебя ничего не сломается на архитектурах с большими размерами слов.

я правильно понимаю что нет никакой разницы пишу ли я uint64_t или unsigned long long int ?

Неправильно.

Дайте советы если есть желание или почитать что что-бы просвятиться

Совет - не суй свой нос в низкий уровень если не знаешь как он работает. Тебе не только не нужны проценты которые ты получишь задрачивая руками байты и используя атомики, но ты их даже не сможешь получить, и скорее всего сделаешь медленнее и точно криво. Используй готовые инструменты, например icu для юникода и protobuf для сериализации, а лучше сразу и более высокоуровневый язык.

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

Касательно utf-8 есть маркер BOM который указывает в каком порядке располагаются байты, но это маркер его может и не быть и «Символ U+FEFF изображается в UTF-16 последовательностью байтов 0xFE 0xFF (big-endian) или 0xFF 0xFE (little-endian)» - Wikipedia Тесть просто данные перевёрнуты, в случае если я просто в utf-8 при операциях надо учитывать что 4 октета могуть быть в памяти вот так 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx или вот так 10xxxxxx 10xxxxxx 10xxxxxx 11110xxx.

Ты сам это придумал. Последний вариант - это не utf-8. Порядок байт для utf8 строго один, BOM там ни на что не влияет.

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

Однозначного ответа нет, не жду, обсуждения, критики, вот этого всего ::)

обмазаться дефайнами по самое не балуйся.

Да я уже вижу что где кросс там ifdef/endif/define занимают порой 30% кода :D Но есть же альтернатива, писать дублирующий код под каждую платформу если в них различное поведение/возможности. Да код пухнет, но хз что их этого большее зло. Как я сказал я не профи мне надо чтобы было «красиво» )) Я конечно прифигел и слишком много хочу, но, но :D

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

А почему нет? В большинстве своём там никаких вычислений логика на логикой логику погоняет, не вижу фундаментальных проблем, какая разница на чём её писать и почему не писать на том что приятно и быстро работает? Проблема вообще не в этом проблема в работе на разных платформах, даже не в платформах в принципе, а стандартной библиотеке. Это не проблема «С», пиши ты хоть на чём ты всегда в выборе того или иного, только тут затык в желании иметь гарантию и увереность. Возьми тот же питон, перейти с 2x на 3x тривиально? Я не буду его судить, но то тут то там у всех что-то ломается вот и всё )) Так же и у меня, но с той лишь разницей что одна версия стандарта на разных системах реализована в той или иной мере, где то да, а где то нет.

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

Ну почему же, я могу на всё закрыть глаза, нет тредов везде ну хорошо значит использую pthread, хочу программной переносимости то сижу в рамках POSIX и не сую нос куда не надо, а если сунул сам виноват и будь любезен поддерживай свои костыли сам. Не хочу проблем с побитовым доступом, нечего его использовать, а если используешь учитывай разрядность и порядок. Я не говорю что можно спокойно и беспроблемно писать что нужно, я про то что может есть какие то общие правила, архитектуры, принципы, документация где явно обозначено мол вот эти штуки программно и аппаратно переносимы, а вот эти нет потому что бла бла бла (грубо говоря). Ну интересно мне ::)

Deleted ()

ЯННП, честно.

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

нет тредов везде

где это нету

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

проблем с побитовым доступом нет, разрядность и порядок для него пофиг, тебе же объяснили уже в этом треде

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

У тебя установлены FreeBSD, Linux, OpenIndiana и Windows, в которых ты регулярно тестируешь свой код на работоспособность? Проверяешь на AIX, HP UX и прочих? Есть железки на чём-то кроме x86 и ARM, на которых ты всё это пускаешь? Если нет, как можно вообще верить, что ты пишешь кросс-платформенный код?

Без этого всего попытки писать кросс-платформенно не имеют смысла. Имеет смысл не завязываться на особенности конкретной платформы. Либо стоит изолировать эти завязки в коде, чтобы если понадобится портировать, сделать это проще. Но заморачиваться на это не надо.

Поэтому я и говорю, что ты страдаешь фигнёй. Убавь количество вещей, о которых ты переживаешь, и кодить станет легче.

i-rinat ★★★★★ ()

Порядок байт. Ну начнём с того что например для обработки utf-8 по всем фронтам побитовые сдвиги и чтение отдельных битов, ну вроде ладно чё, в чём проблема, а проблема например в том что порядок байт разный и что мне определять сначала что у меня sparc64 или i386 а потом уже с учётом этого читать байты с конца или с начала?

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

Атомарность. Ну хорошо 32bit умирает, но мне пофигу если я пишу библиотеку то я хочу что бы она работала везде, ладно у меня может не быть uint64_t и знание того что где то long 64bit, а где то 32bit и я могу смело (да?) писать unsigned long long и быть уверенным что в 64 битной системе это 64 а в 32 битной это тоже 64 но эмулируется через два 32битных инта и вот тут как бы уже нет гарантий что операции записи переменной или чтения отработают.

#include <stdint.h> и типы uint64_t и т.п. тебя спасут. Для атомарных операций либо защищать мутексами, либо использовать интринсики типа __sync_fetch_and_add()

я правильно понимаю что нет никакой разницы пишу ли я uint64_t или unsigned long long int ?

Для компилятора - никакой. Но если нужна гарантия размера типа везде - только (u)intxx_t.

И да в случае если на какой либо системе нет <stdint.h>

Он есть везде, даже на вантузе, sdcc, newlib'е и стремных DSP'шниках ;) Новинки завезут, ясен пень не сразу. Для тредов я бы все рекомендовал бы pthread's, а для венды pthread обертку над виндовыми вызовами. Это уже покрывает 99% сценариев, за исключением изысков.

msvc поддерживать смысла большого нет - на С конпелятор они забили болт, оно много чего не умеет, да и смысл юзать это убожество, когда есть gcc?

Дайте советы если есть желание или почитать что что-бы просвятиться. У меня есть желание писать железный код, но чем больше я закапываюсь во всём этом тем меньше понимания как собственно его писать железно.

По началу не слишком загоняйся переносимостью на изыски, ибо premature optimization. Закопаешься. Если все же решил выбери 2-3 платформы, подними CI для автосборок на них на все, и попробуй хотя бы переносимость win/lin/mac обеспечить. Ну и не забудь про тесты и кавередж. Многие моменты, где будут проблемы переносимости тебе может подсказать coverity (см. scan.coverity.com)

У меня стандарт золотой: cmake + ctest для сборки и тестов, jenkins для CI, gcov->cobertura для сбора покрытия (можешь и хипстерский coveralls), проверка кода - clang-analyze, coverity, cppcheck.

ncrmnt ★★★★★ ()
Последнее исправление: ncrmnt (всего исправлений: 1)

Я могу тебе разве что предложить прекратить страдать по кривостям си и использовать его там где надо. Лепить web-framework, если ты не находишься в жёстких рамках embedded системы - это пример где не надо использовать си.

Переносимый код - это всегда некоторый компромисс между тем что есть в стандарте и тем как это реализуют на target системе. Костыли и ифдефы - печальное следствие сишной природы. Нет, можно изгаляться и делать раздельные реализации для каждой платформы и разруливать системой сборки, но это не только лишь для всех.

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

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

devalone ★★ ()

Если кратко, надо тестировать код под каждой целевой платформой, чтобы он нормально работал.

peregrine ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

Интересная штука, спасибо.

Ну или питон - неужто много выжрет?

Я его не знаю, но у меня отвращение от форматирования отступами, тут уже проблема не в питоне, а моём его восприятии,чё уж там,он мне не нравится, пишу же большей частью в своё удовольствие, поэтому прагматичный выбор инструмента тут как бы важен, но не определяющее ))

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

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

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

Я его не знаю, но у меня отвращение от форматирования отступами, тут уже проблема не в питоне, а моём его восприятии,чё уж там,он мне не нравится

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

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от Dark_SavanT

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

В случае если подобные места единичны и сведены к минимуму это серебряная пуля как по мне. По крайней мере это выглядит хорошо, да нужно помнить что мы имеем две/три реализации, но это меньшее наверное зло чем лапша ifdef/define/endif. Но это если лапша конечно в ином случае всё наоборот.

Лепить web-framework

Ну я бы не звал прямо фреймворк, да отчасти есть его признаки, но мне не нужен полноценный фреймворк, мои потребности скромны, даже будущий шаблонизатор можно смело выкинуть, его наличие лишь вопрос удобства некого. Ну некоторые пишут для nginx модули и всё замечательно. Разница лишь в том что я использую kore.io как основу вот и всё )

Deleted ()
Ответ на: комментарий от I-Love-Microsoft

но это иллюзия

Может быть, может быть. Ну тут надо просто пересилить себя и какую нибудь штуку которую требуется написать, просто взять и попробовать написать на python (изучая его в процессе уже естессна) и там уже может быть шаблон сломается и взгляд другой будет. Это надо просто брать и писать, ну это как получиться уже.

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

Убавь количество вещей, о которых ты переживаешь, и кодить станет легче.

Да вот к тому и прихожу ) Просто хочется заранее иметь понимание о камнях и нюансах. Но да, в целом согласен.

Deleted ()

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

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

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

где это нету

Сорян, неверно выразился имел в виду отсутствие реализации <pthreads.h> с11. А не вообще тредов как таковых.

проблем с побитовым доступом нет, разрядность и порядок для него пофиг, тебе же объяснили уже в этом треде

Да нууу, можно упороться вот так, это конечно просто пример, но всё же. )

dron@gnu:~$ cat test.c
#include <stdio.h>

int main(int argc, char *argv[])
{
    long int a = 0;

    for (int i = 0; i < 63; ++i)
    {
        a=(a<<i)|1;
    }

    printf("%li\n",a );
    return 0;
}
dron@gnu:~$ gcc -Wall -std=c11 -pedantic test.c
dron@gnu:~$ ./a.out 
4611686018427387905
dron@gnu:~$ gcc -Wall -std=c11 -pedantic -m32 test.c
dron@gnu:~$ ./a.out 
1073741825
dron@gnu:~$ 

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

Да я знаю, я же сказал что это просто упоротый пример.

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

Ну так то да, я разогнал повозку впереди коней,по остальному согласен возможно заморачиваюсь раньше времени.

Deleted ()

У тебя просматривается 2 проблемы:
1. Неверный выбор языка. Си изначально был заточен на то, чтобы использовать специфику платформы, и исключить всякие неявные преобразования. В этом плане я рассматриваю Си как «прокачанный» ассемблер. Нужна переносимость - бери C++ (или другой высокоуровневый язык, благо их нынче наплодилось). C++, правда, тоже нужно уметь пользоваться. И, поверь, поначалу ты им будешь пользоваться неправильно: скажутся Си-шны привычки.
2. Недостаточное использование средств языка/библиотек. См про типы ниже.

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

знание того что где то long 64bit, а где то 32bit

Для этого используются константы: https://stackoverflow.com/questions/2053843/min-and-max-value-of-data-type-in-c

И вообще я периодически просматриваю код, и стараюсь чтобы чисел не было нигде кроме #define, const, constexpr , ну, кроме самых тривиальных случаев.

libc Эмм, с89/с99/с11 где то напрямую отказываются от поддержки стандарта msvc не хочет с99 реализовывать в полной мере, тоесть уже нет гарантий, ладно на дворе почти 2018 надо с11, но и тут glibc не имеет <threads.h>

А поэтому, если ты озаботился переносимостью, нужно либо писать на самом «низком» стандарте, либо оборачивать нововведения в свои функции. Ни то ни то не является приятным вариантом, поэтому лучше с самого начала определить под какие компиляторы/платформы будешь писать.

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