Третий тред, посвященный прародителю всех С-подобных языков и по совместительству единственному идеальному и всесторонне годныму средству программирования как на системном, так и на прикладном уровне.
- Очевидный GCC. - clang: оче годно, батя рекомендует. Дрочим на --analyze. - Intel C++ Compiler: оптимизации, тысячи их. - Visual Studio 2015 Community Edition: внезапно этим стало можно пользоваться. Поддержка C11 на уровне "есть все, что тебе понадобится в реальном проекте плюс кривая библиотека" (да, в студию в последнее время завезли stdint и stdbool, почти все новые фишки из C11, static_assert и даже юникод). C snprintf все до сих пор плохо. Анализатор кода в комплекте. - Pelles C (шиндоуз онли): поучиться, вкатиться в C11 (в частности, потыкать threads.h и stdatomic.h), но количество багов в оптимизаторе и редкие апдейты напрочь отбивают желание собирать этим что-то сколько-нибудь серьезное. - TCC: очень маленький компилятор с багами и неполной поддержкой C99. - Borl... ээээ...
Stephen Prata "C Primer Plus, 6th Edition" (2014) Свежая знает про C89, C99, C11, описывает различия, объемная около тысячи страниц, годная хотя есть некоторые шероховатости, с вопросами, упражнениями и ответами. Читать после K&R или до.
Samuel P. Harbison, Guy L. Steele Jr. "C: A Reference Manual, 5th Edition" (2002) Ебаный пересказ стандартов C89 и C99 (включая стандартную библиотеку). Для не осиливающих стандарт в оригинале. Читать в качестве подготовки к собеседованиям (есть задачник с ответами) и для ознакомления с масштабами пиздеца перед написанием своего парсера/компилера.
Peter Van Der Linden "Expert C Programming. Deep C Secrets" (1994) "Си: грязные истории". Смехуечки, немного объяснений, чем обусловлены особенности языка, всем известные подводные камни кто там ругал косяки в JS? у нас в сишечке их гораздо больше, просто они лучше спрятаны, немного байтоебли и непонятно откуда взявшаяся глава про старинные плюсы. Читать в качестве сказки на ночь (на пару вечеров хватит).
Ben Klemens "21st Century C: C Tips from the New School" (2012)
Stephen G. Kochan "Programming in C (4th Edition)" (2014)
>>610139 Завезли еще немного юникода (никто не пользуется), многопоточность (никто не пользуется) и костыль вместо шаблонов (погугли _Generic). Ну и еще немного плюшечек туды и сюды. Как-то так.
Проектирование на СиАноним24/12/15 Чтв 04:23:34#5№610977
Кто-нибудь когда-нибудь видел книжки о том, как правильно проектировать на Си? Что-нибудь вроде Александреску или Б4. Всё что удалось найти это обоссаная книжка про эмуляцию ООП, что и без неё ясно.
>>610977 Си, по сути, остается таким же незамысловатым процедурным языком, каким он был в семидесятых. Правда, теперь в нем есть ограниченная поддержка модулей, опирающаяся на два ключевых слова: extern и static. Поэтому старые добрые книжки по структурному программированию тебе в помощь.
Посоветуйте, как продумать архитектуру для такой библиотеки.
Надо строить конечное поле Галуа, в котором определены операции над многочленами. Степень расширения не более чем 32 из-за ограничения встроенных типов. Характеристика базового поля равна 2.
Предполагаю, что основой библиотеку будет функция GF(unsigned polynomial), которая возвращает указатель на таблицу индексов на куче. В функции GF надо определить номер старшего бита в переменной polynomial и снять с нее маску. Она нужна для построения таблицы индексов (определение переполнения разрядной сетки).
Для конкретной реализации конечного поля надо где-то хранить базис этого поля и следы базисных элементов. Думаю, что надо завести структуру gf, в которой будет храниться таблица индексов, таблица базисных элементов, таблица следов и, возможно, что-то еще.
Пусть необходимое поле уже построено, и информация о нем хранится в структуре gf. Как при помощи этой структуры выполнять операции над многочленами типа умножения, возведения в степень, нахождения обратного? Если умножением занимается функция gfmul, то как выглядит ее вызов, если многочлены хранятся в таблице индексов? gfmul(gf->index[5], gf->index[11])? Это же ебаный вырвиглаз. Хранить в структуре gf указатели на функции, которые реализуют арифметические операции над многочленами? То есть, если надо умножить два многочлена, которые представляют собой 5-ю и 11-ю степень порождающего многочлена, я могу захотеть сделать это вызовом gf->mul(5, 11). Поэтому функция mul должна как-то уметь находить в gf->index[] 5 и 11 элемент. Причем она объявлена отдельно, но сама является частью структуры gf и должна уметь пользоваться данными из этой структуры. Выглядит как говно.
На чистом си вообще можно написать что-то сложнее вирусов и консольных калькуляторов?
>>611202 Я имею в виду полезное прикладное ПО, а не говно мамонта. На чем пишутся математические библиотеки? Как люди пердолятся со всем этим говном, не умеющим в архитектуру?
>>611260 Блять эти очки, рубашка и причёска. 100 процентый пидораха нахуй. Наверняка преподаёт в каком-нибудь засраном МГУ и втирает про успешность советской науки даже почти наверняка не читал никаких книг кроме советских. А эта улыбка в конец разозлила. Ещё и линукс ему наверно не угодил по вымышленной причине типа пользуйтесь отечественными аналогами.
> Эндрю Таненбаум также признан как автор учебников для высшей школы по некоторым областям информатики и вычислительной техники, в своих областях книги считаются избранными как стандарт, в частности: > Computer Networks, ISBN 0-13-066102-3 > В переводе: Компьютерные сети, ISBN 5-318-00492-X > Operating Systems: Design and Implementation, ISBN 0-13-638677-6 > В переводе: Операционные системы: разработка и реализация ISBN 5-469-00148-2 > Modern Operating Systems, ISBN 0-13-031358-0 > В переводе: Современные операционные системы, ISBN 978-5-498-07306-4 > Также написал: > Structured Computer Organization, ISBN 0-13-148521-0 > В переводе: Архитектура компьютера ISBN 5-469-01274-3 > Distributed Systems: Principles and Paradigms, ISBN 0-13-088893-1 > В переводе: Распределённые системы. Принципы и парадигмы ISBN 5-272-00053-6 > Книга «Операционные системы: разработка и реализация» (англ. Operating System: Design and Implementation) и Minix [1] вдохновили Линуса Торвальдса на создание ядра Linux. В автобиографии Just For Fun Торвальдс описывает её как «книга, которая подняла меня на новую высоту». Впоследствии Таненбаум написал распределённую операционную систему Amoeba, полностью реализующую идею микроядра.
Только вот Linux взлетел, а профессор со своими микроядрами соснул.
>>611300 > 100 процентый пидораха нахуй. Наверняка преподаёт в каком-нибудь засраном МГУ и втирает про успешность советской науки даже почти наверняка не читал никаких книг кроме советских.
Хотя вообще-то возможно, лол. Вот Вирт к примеру типичный пидорашка, любит рассказывать охуительные истории как американские рептилоиды убили европейскую науку. И СССР ему нравится.
>>611170 >На чистом си вообще можно написать что-то сложнее вирусов и консольных калькуляторов? С в этом плане не так сильно отличается от любого ООП языка, ну наследования нет (бери в руки препроцессор), шаблонов (препроцессор), ну вместо this->yoba(x) надо писать yoba(this,x), нет перегрузки операторов (вместо a+b надо писать add(a,b)), исключений (вместо add(a,b) надо писать Result add(T a, T b, Tab_result), и возврата кортежей (Result add(T a, T b, Tab_result, T result2), и буфер надо выделять вне функции (вместо vector = yoba(a) надо писать vector=malloc(...);yoba(a, vector)). Но так все точно так же, определяешь структуры данных, прячешь имплементацию в .c файл, чтобы наружу торчала только struct yoba;, пишешь конструктор, деструктор, и вперед.
>>611317 Лекция, когда он приезжал в Россию, ЕМНИП в блоге Алены C++ было видео. О том, какая была передовая система Lilith и язык Oberon, но нам навязали Windows и C++.
1. Записывает в переменную setting результат побитового и переменной Code и макроса-маски SET_IOCTL. 2. Обнуляет в переменной Code биты по маске SET_IOCTL.
Чому если я считываю строку с помощью fgets(str, 128, stdin); и использую strcat, например strcat(str, str1); он строки объединяет с переносом т.е. выводить будет не "строка1строка2" а "строка1 строка2" а если использую gets(str); тогда все нормально. В чем подвох?
>>613026 Я б перекресток как граф рассматривал, вершина графа - собственно полоса. Например с правой можно прямо (в идеале не меняя полосы, но можно) и направо только в крайнюю полосу, с центральной только прямо (опять же в свою полосу), с левой только налево в любую полосу (например). Быдлорежим "с левой полосы направо ты тачку мою видел еп" пока не рассматриваем.
В простейшем случае если на ребре графа есть машина, остальные "не занимают" перекресток и стоят за стоп линией, даже если на действие в данной полосе зеленый свет, если посложнее - посчитать, сколько машин вместит одно ребро графа (длина ребра/(длина машины+стандартная дистанция между машинами).
Как-то так, вот такие идеи. По идее рисовать надо, но ломак.
>>613493 size_t - это беззнаковый целый тип. Ну типа натуральное число. Я бы мог еще добавить, что он имеет разрядность, достаточную для хранения указателей, но лучше не буду. В принципе, можешь заменить size_t на unsigned int. В большинстве случаев эти типы совпадают.
asprintf - форматированный вывод в строку. Память под результирующую строку выделяется автоматически. Ты даешь этой функции неинициализированный указатель на строку, а она сама выделит памяти столько, сколько нужно. Эта функция является расширением GNU и не входит в стандарт.
snprintf - почти тоже самое, но есть два нюанса. Память под результирующую строку должна быть выделена заранее (хоть на стеке, хоть в куче, хоть в статической памяти). Функция считывает не более n символов, включая завершающий нуль (n передается в качестве второго аргумента). Есть еще sprintf, но я бы не советовал, ибо она не контролирует количество считываемых символов. snprintf входит в стандарт C99.
>>613506 > Я бы мог еще добавить, что он имеет разрядность, достаточную для хранения указателей Правильнее сказать, что он имеет разрядность, достаточную для хранения размера любого объекта (т.е, для хранения результата sizeof). Размер указателя теоретически может быть как меньше, так и больше размера size_t.
>>613485 > вариант рабов Стандарта В случае отсутствия asprintf, она реализуется буквально тремя строками. Хорошая, удобная функция, как и strdup, которой тоже в стандарте нет. А вот хранить в size_t что-то, не являющееся размером, количеством или индексом - моветон.
>>613522 >Правильнее сказать, что он имеет разрядность, достаточную для хранения размера любого объекта Точно. Спасибо. Это я с D уже путаю. Там по спецификации: size_t is an alias to one of the unsigned integral basic types, and represents a type that is large enough to represent an offset into all addressible memory.
>В случае отсутствия asprintf, она реализуется буквально тремя строками. Если человек спрашивает, что такое putchar, врядли стоит грузить его такими вещами.
>моветон В данном случае некритично, я считаю.
>>613526 Потому, что тупо пишется короче. Можно, конечно, взять какой-нибудь uint32_t, но это же дополнительный хедер подключать надо.
>>613530 > Если человек спрашивает, что такое putchar, врядли стоит грузить его такими вещами. Врать не стану, но про asprintf и snprintf я не очень понял. Как я понял то что они динамически выделяют память. Ты даешь указатель на строку, а она выделит сама столько сколько надо. Но для чего это используется я не понимаю я до конца не понимаю.
>>613562 Вот смотри. Есть функция printf. Она принимает формат и список переменных/констант для вывода. Функция выводит все указанные переменные и/или константы на стандартный вывод (чаще всего в консоль) в соответсвии с форматом. То есть, она все конвертирует в строку.
Функция asprintf делает тоже самое. Только она сконвертированные данные сохраняет в строку, а не выводит в консоль.
>>613565 Да. Чтобы не было утечки памяти. Если тебе уже не нужна строка, сохраненная в s1, то чтобы использовать s1 для хранения другой строки, память надо освободить. Если ты просто вызовешь asprintf второй раз для s1, то функция просто выделит новую память и запишет указатель на новый блок память в эту переменную, но прежняя строка так и останется "висеть в воздухе".
>>613565 Кстати, если тебе это задание дал препод, то мне кажется, он может не принять вариант решения с использованием библиотечной функции. Так что, на всякий случай, иди вот сюда: https://ru.wikipedia.org/wiki/Itoa_%28%D0%A1%D0%B8%29 и списывай реализацию Кернигана и Ричи.
>>613586 Дело в том, что многие вкатываются не по своей воле, а по воле преподов, которые дают такие задания до того, как объяснять что-то про управление памятью. Типа, вот я вам рассказал как объявлять переменные и делать условия/циклы. Вперед! Выполняйте задание. Для некоторых изучение Си - необходимость, которая отнюдь не вселяет в них желание побольше узнать о языке и уж точно не прибавляет энтузиазма для изучения по этой теме чего-то большего, чем рассказывают на занятиях.
>>613592 Хуй знает. 15 лет назад когда мне на 2 курсе преподавали теорию операционных систем, то на сях там был минимум и почти сразу перекатились на кресты. Жаба-примат.
>>613623 Изначальное условие было такое: дано натуральное число. Я это понял как то, что у нас есть двоичное представление этого числа, а не строковое. Но если тебя устраивает строковое представление, то можно и так, если тебя не смущает, что программа фактически работает со строками, а не с числами.
>А почему так лучше? Потому что семантически это означает, что функция strlen должна вызываться на каждом проходе цикла. А естри strlen вынесена за цикл, то и вызываться будет только один раз. У тебя ведь длина строки не меняется по ходу цикла. Так зачем делать одну и ту же бесполезную работу на каждой итерации? Сейчас считается, что большиснтво компиляторов самостоятельно оптимизирует такие вещи. Тем не менее, в данном случае, вынесение функции за цикл выглядит более логично и является примером хорошего стиля. Причем это не я придумал. Можешь Криса Касперски почитать, например (серия статей "Сишные трюки").
>>613991 Нет. Они могут и в регистрах быть. Вообще сишечку создавали в качестве абстрактного ассемблера, где намеренно замалчивается конкретная реализация регистров и памяти.
>>613990 Но вообще, тебе нужно выделять каждому потоку свой ip, и пробрасывать его через pthread_create если уж ты каждому подключению отдельный тред выделяешь. Алсо, адрес весьма просто инкрементируется одним циклом, а не этим безобразием.
>>614000 У тебя ip = NULL, туда пишет sprintf, это нормально? Алсо, после создания потока туда снова пишет sprintf, хотя поток мог еще не успеть воспользоваться значением из буфера.
>>614007 Еще как быстрее. Сейчас увидишь. Хули там, wsa стартуешь, инкрементируешь ecx и через ustr$ переводишь в текст, потом добавляешь в пременную, добавляешь точку и еще так 4 раза, потом обновляешь и все ок. В поток отправляешь всю хуйню, тот быстро копирует и все. Ну короче элементарно бля. Там ебли намного меньше, чем с сишкой. кстати зря многие говорят, что масм - язык низкого уровня. он высокоуровневый, как и другие языки ассемблера. Более высокоуровневый fasm, но мне масм больше нравится
Юзер дает нам 2 слова, наша задача определить сколько раз встречается буквосочетание заданной длины с заданной позиции, во втором слове. Вот мое решение, но оно не верное. И не до конца правильное в плане поставленного условия.
>>611310 Да что вы вспоминаете срач более чем 20-летней давности! Сам Таненбаум с тех не критикует линуксы. Линуксы с давних пор уже не монолитные, а по большей части модульные. Да и с микроядрами он не соснул, так как сделал надежную ОС (правда для учебных целей и встроенных систем). Просто данную идею сложно реализовать, так как найдется немного людей, которые будут создавать с нуля ОС, опираясь на архитектуру.
>>613769 Почитай об указателях. Попробуй сам попрактиковать. А то, что на пике - абсолютно бессмысленное дерьмо. Ярчайший пример говнокода. Такое вряд ли часто пишут. Но хорошо понимая логику работы с памятью и собственно сами указатели, даже это можно понять за пару минут.
Супец громисты! Есть один проект и этот проект писан под линуксы с использованием пары либ, в т.ч. libusb. Взял я значит его, сунул в проект кодблоксов под виндами, скачал прекомпиленные mingw либы, положил рядом, настроил в кодблоксах опции сборки (build options -> search directories -> compiler/linker, сунув туда, соответственно пути к директориям include и lib библиотек). И соснул большого, получив целый ворох undefined reference'ов, например: > undefined reference to `libusb_get_bus_number
Что я сделал не так, кроме использования виндов? Дайте советов мудрых. В гоголе, стеке и прочем уже искал.
>>614608 > сунув туда, соответственно пути к директориям include и lib библиотек Так же, как инклуды нужно использовать в исходнике, так и используемые либы нужно явно указать линкеру, а не только место, где их искать. В командной строке ты можешь сделать -lusb, поищи подобное в Code::Blocks.
Здравствуйте. Есть строка вида 12345,6789,x,0123,"xyi, pizda",333,"333-33",,,,"",,,"",0,98,"",,,, ну и так далее. Нужно вытаскивать строки между запятыми и кавычками(если они есть) для дальнейшего использования. Реализовать это получилось в теле main, а в отдельную функцию, возвращающую очередную строку между запятыми не получается: вылезает ошибка сегментации. Причём первые строки вытаскиваются и возвращаются нормально, а вот последняя вообще никак. Сама функция:
char NextstrField(char buf, int posbuf) { char str=NULL;
if (!(str=(char)malloc(sizeof(char)BUF_SIZE))){ printf("Out of memory\n"); system("pause"); exit(-1); }
int i; unsigned short QwoteActive=0;
for (i=0,memset(str,0,sizeof(str));i<445;++i,(posbuf)++){
if (buf[(posbuf)]=='"'){ // если встречается кавычка (posbuf)++; if (QwoteActive) QwoteActive=0; else { if (buf[(posbuf)]=='"') break; QwoteActive=1; } }
if ((str=buf[(posbuf)])==',' && !QwoteActive || buf[(posbuf)]==0x0A || buf[(*posbuf)]==0x00){ str='\0';
break; } } return str; }
Кусок кода в main: for (posbuf=0;str1[posbuf]!=0;posbuf++){ if (str1[posbuf]=='\0' || str1[posbuf]=='\n') break; str2=NextstrField(str1,&posbuf); puts(str2); }
Привет, Анон! НИд халп! Ситуация следующая. Есть функция, в которой создается массив типа char - db и массив указателей на char, указывающие на каждое отдельное слово в db. В первом цикле определяется длина текущего слова strlen(ptr_arr+i) и прибавляется к l - общей длине массива db. В db передается строка: "1;qwe;asd;zxc;2;cvb xc vbc;1823;12;3;m". strtok выделяет лексему в соответствии с разделителями(';' и '\n'), следующая инструкция находит длину l. Ну, и суть, собсно, проблемы: во время трассировки на нулевой итерации внешнего цикла вместо, ожидаемого мной l=2, я, сука, получаю l=4!! Где моя ошибка, подскажи Анон? На пикче код и отладчик. ( использование средств языка весьма ограничено, не обращайте внимание на реализацию )
>>615980 В ДНК, очевидно же! l = l+... вместо l+=... *(ptr_arr+i) вместо ptr_arr Входные данные у тебя не "1;qwe.." a "1\0qwe...". И самое главное: ptr_arr + i это указатель на указаель на строку, а не указатель на строгу, уебок, блядь. Когда ты ptr_arr + i его передаешь в strlen, strlen считает "длину указателя", ВНЕЗАПНО оказывается, что это там 4 ненулевых байта подряд...
Привет, няши. Передо мной стоит такая задача: принять по UART несколько пакетов, описание протокола есть, осталось понять, как эффективнее это сделать. Когда приходит байт - вызывается прерывание. Как более эффективно складывать в буфер байты и далее находить в нем пакеты? Вижу 2 варианта, поясните за плюсы и минусы: 1. Кольцевой буфер, вот такой вариант: http://microsin.ru/content/view/1098/44/ как только в нём появится новые данные, в главном цикле забираю байт, прогоняю через конечный автомат, который ищет начало пакета, данные и конец пакета. 2. Кольцевой буфер, который работает так: если массив заполнился, смещает в цикле все элементы буфера (цикл в том же прерывании выполняется), добавляет ноль в конец массива. Далее можно уже в главном цикле при помощи привычных функций из string.h и stdio.h найти пакет и т.д. Вот тут походу минус в том, что в прерывании крутится цикл.
>>616229 >2. ... Допустим ищешь ты пакет в главном цикле, работает какой-нибудь scanf и тут БАЦ! приходит новый байт и весь буфер смещается на один элемент. Что случится?
>>616229 >Как более эффективно складывать в буфер байты и далее находить в нем пакеты? Конечным автоматом. > смещает в цикле все элементы буфера Каким образом? Копированием? Чем это лучше простого сдвига указателя в случае кольцевого буфера? Хуита какая-то.
>>616235 >Каким образом? Копированием? Чем это лучше простого сдвига указателя в случае кольцевого буфера? Хуита какая-то. Да, копированием. >Конечным автоматом. Это хорошо. >Какого типа протокол? >Запрос-ответ, или потоковый асинхронный? Потоковый асинхронный. На некоторые пакеты надо отправить что-то в ответ. В основном только принимаю.
>>616246 Да, DMA есть. Сейчас вот смотрел про DMA: в циклическом режиме заполняет половину буфера, генерируется прерывание, далее заполняется вторая половина и генерируется прерывание. Т.е. мне надо поставить флаги в прерывании, что типа пора обрабатывать, в главном цикле запустить обработку, при помощи конечного автомата?
>>616240 Зависит от железки, протокола и требуемого размера буфера, вестимо. Если тебе не лень реализовывать FSM - делай на кольцевом буфере, будет быстро и красиво. Если лень - делай это свое копирование, будет медленно и понятно.
>>616250 У меня протокол не сложный, с FSM не заебусь. Вариант с копированием я увидел у одного старого погромиста с опытом, думал - во как красиво то сделано. Оказалось, что сделано максимум хуево.
>>616248 Тогда делай кольцевой буфер с DMA, если там есть регистр с текущим адресом, то на прерывания можно забить: в главном цикле смотришь, разницу между текущим и прошлым значением регистра, - разбираешь соотв. число байт, разбирать лучше всего автоматом.
Для ответов сделай пинг-понг буферизацию через DMA, один пакет отправляется, - второй пишется в свободный буфер, дальше меняешь буфера местами.
>>616262 >в главном цикле смотришь, разницу между текущим и прошлым значением регистра, - разбираешь соотв. число байт, разбирать лучше всего автоматом. Классный подход, мне нравится.
Можно ли делать так: char F(char s1,char s2) { / тут делаем что-то со строкой s2, используя s1, при этом s1 не изменяется, а s2 - да / возвращаем s2; }
int main() { / где-то тут выделяем память для s1 и s2 */ s2=F(s1,s2); }
Просто мне хочется, чтобы возвращалась именно строка, а не через void. Терзают сомнения, что может что-то случиться плохое.
>>616980 Если ты возвращаешь s2, то можно не принимать его в качестве аргумента. Конечно же в случае, если s2 полностью выводится из s1 (допустим измененная копия строки). Ты просто можешь вернуть указатель на s2 без выделения памяти для нее в функции main, выделив ее в F(char \*s1).
>>617443 char \F(char \s1) { / объявляем и выделяем память под s2 / тут делаем что-то со строкой s2, используя s1, при этом s1 не изменяется / возвращаем указатель на s2; }
int main() { /объявляем s2 / где-то тут выделяем память для s1 и заполняем ее чем-то */ s2 = F(s1); }
>>617717 Может тебе еще программу сделать, которая за тебя пишет код и рассказывает охуительные истории? >Ищу книгу по С, не такую нудную, как K&R >но и не такую объемную, как у Прата. Не осилил или слишком скучно, тогда программирование - это явно не твое. >Желательно коротенькую, описывающую актуальные методы с примерами. https://learnxinyminutes.com/docs/c/ >>617722 Двачую. Ньюфаги совсем охуели. Я K&R в десятом классе читал и мне было интересно. Особенно задания выполнять.
Мне тоже было очень интересно выполнять задания из кнр.
Вообще Си уютный язык. И ламповый.
К сожалению программирование меня всё больше и больше печалит засильем скриптовых языков, которые порождают такие программы как Firefox, при открытии с пустой вкладкой сжирающий 350 мегабайт оперативки. И всех всё устраивает: докупим ещё планочку на 8 гигов оперативы и норм.
Может я старею, но меня всё больше тянет на что-то старое доброе, чем на ту парашу, которую остервенело клепают обезумевшие рынки, которым кровь из носу нужно расти каждый год.
>>618093 На неё ссылались некоторые источники, хотелось бы ознакомиться. Я модифицирую игру для PS1, приходится ковырять экзешники, читая много mips кода. А игры писались на сишечке, хотел упростить себе жизнь.
>>618103 Замени её «Архитектурой компьютера» Эндрю Таненбаума.
Ничего особенного там скорее всего нет, кроме оптимизаций, т.е. рассказа о том, что вычислительные действия вроде: A + B + X + Y могут быть выполнены не за три команды, а за две, как: (A + B) + (X + Y) где действия в скобках займут один такт процессора, и сложение между скобками займёт ещё один такт, MIPS это умеет.
Похожим образом ускоряются и операторы условия, т.к. процессор вместо флажков состояния ("conditional flags") использует обыкновенные регистры.
Взято из книги «Understanding and Writing Compilers», Richard Bornat.
>>618126 А где мне задавать вопросы? Ну, понимаешь, это такая сфера деятельности, где некоторые ответы можно вечность искать. Живого ассемблер треда нет, а самостоятельно понять "какой код на си мог при компиляции привести к ЭТОМУ" я не всегда могу.
>>618136 Как я его оживлю, если я не могу отвечать, а могу только спрашивать? Вернее, я уже и отвечать могу, но вопросы никто не задаст моего низкого уровня, ибо людей нет в сфере.
>>618072 Согласен. Я хоть не профессионал, но на Си, как любителю мне очень нравится писать. Все прозрачно, как напишешь так и будет. Теория заключается в понимании работы железа. Можно написать абсолютно все, что пожелаешь. Радует, что замену сишечке так и не нашли. >Firefox, при открытии с пустой вкладкой сжирающий 350 мегабайт У меня съедает примерно 90Мб на старте(это под линем). Что я делаю не так? >которую остервенело клепают обезумевшие рынки, которым кровь из носу нужно расти каждый год. Нужны же ИННОВАЦИИ!!! Даже если эти инновации представляют из себя пропиаренную переделку уже давно известной технологии.
>>617249 >>617448 >можешь вернуть указатель на s2 без выделения памяти для нее в функции main, выделив ее в F Всё-таки мне этот момент непонятен. Если я возвращаю указатель из функции, программа крашится. Там же неизвестно что хранится по адресу, после завершения функции? Получается, нужно объявлять в самой функции как static или что?
>>618414 >Там же неизвестно что хранится по адресу, после завершения функции? Известно. Функция возвращает указатель на участок памяти, с которым ты работал. При завершении работы, функция самостоятельно не освобождает память.
>Получается, нужно объявлять в самой функции как static или что? static необходим только для того, что значение переменной, отмеченной как static, сохранялось до следующего вызова функции. Как просто пример использования static, можно взять подсчет количества вызовов этой самой функции.
Поясните за сборку пакетов, допустим HTTP. Я правильно понимаю, что необходимо просто отправлять строку в которой различные поля разделены при помощи \r\n? Или можно как-то иначе это делать? И есть ли готовые библиотеки для работы с протоколами?
Я тут хотел спросить. Допустим есть у меня набор каких-то неизвестных данных. Мне необходима возможность по-разному их интерпретировать (допустим как int, char, double, struct smth). Как мне это сделать? Допустимо для этого выделить динамически память под void (звезда) или char (звезда) и затем при помощи указателей(int, char, double, struct smth) пройтись по этим данным? Или это будет плохим способом решения?
>>619834 Стандарт запрещает любые подобные выебоны (в том числе и >>619969 union). Чтобы все было пиздец как кроссплатформенно, нужно читать побайтово и вручную собирать многобайтовые типы (сдвигами и т. д., что особенно весело для какого-нибудь double).
Если ты нормальный человек, то указатели вполне ок, озаботься только выравниванием и endianess - будет достаточно переносимо.
>>620075 Советую взять любой понравившийся ассемблер (nasm, fasm), писать ассемблерный код отдельным модулем (файлом) и потом линковать к основной программе. Когда ты осознаешь, что код на ассемблере можно заменить интринсиками, проще будет его найти и переписать. Алсо, в tcc дохуя неисправленных багов и напрочь отсутствующий оптимизатор. Единственное, за что его следует любить и уважать, так это за -run.
>>620081 > нужно читать побайтово и вручную собирать многобайтовые типы Это как раз то, что я и имел ввиду. > то указатели вполне ок, А это как раз то, что я хотел сделать. Спасибо за ответ.
>>620081 >Алсо, в tcc дохуя неисправленных багов и напрочь отсутствующий оптимизатор. Единственное, за что его следует любить и уважать, так это за -run. Тогда посоветуй еще какой-нибудь компактный компилятор, который генерировал бы маленькие экзешники. Хеллоуворлд, скомпилированный tcc, весит всего 2.5 кб, почти как на ассемблере. Другие компиляторы даже с оптимизациями меньше 25 кб не генерят.
>>620288 >Другие компиляторы даже с оптимизациями меньше 25 кб не генерят. $ clang -O3 helloworld.c -o helloworld && du --apparent-size -b helloworld 6600 helloworld $ gcc -O3 helloworld.c -o helloworld && du --apparent-size -b helloworld 6720 helloworld >почти как на ассемблере $ clang -O3 helloworld.s -o helloworld && du --apparent-size -b helloworld 6568 helloworld $ gcc -O3 helloworld.s -o helloworld && du --apparent-size -b helloworld 6704 helloworld Ты ведь понимаешь что эти 6 кб это всякие таблицы релокаций и прочая ELF-хуйня? От нее не избавишься.
>>620288 tcc просто динамическая линкуется к рантайму. Рантайм в Windows весит 400 КБ (используется древняя MSVCRT.DLL, что само по себе плохо). Можно взять Pelles C из шапки, с -MD он тоже сгенерит 2 КБ плюс 300 КБ рантайм (если статически линковать рантайм, будет что-то около 30 КБ минимум) . Можно взять Visual C++, он генерирует 4.5 КБ плюс рантайм (со статической линковкой 50 КБ). А можно перестать загоняться по поводу размера файла.
//ну кроме того, что с типом функции объебался. Ну похуй. Это насрать. Компилируется без ошибок и прочей хуйни. У меня в принципе ни одна программа скомпилированная не запускается. Я писал сканнер портов и нихуя. Написал другой. опять нихуя. Включил kdbg и там у меня показывает ошибку сегментации ДО входа в майн. Что за нахуй? Компилирую gcc -pthread [sourcename].c
>>620288 Можно дос стаб удалить и будет еще меньше. А так да. я под венду пишу на масме, потому что ебал я писать на сишке там. У меня там MessageBox по 64кб выходит. Я помнится, писал под DOS когда-то, так с тех пор я вообще каждый байт блядь пытаюсь сэкономить. Даже в сишке ассемблерными вставками пользуюсь. Вообще, используй __imp_MessageBoxA@16 и не еби себе мозг. Хотя лучше, конечно, пиши на масме под венду. Под прыщами на нем не попишешь.
>>620322 int strcmp(char s, char t){ while(s++ == t++) В цикле while указатели убери. У тебя это итак указатели. Ты просто адрес инкрементируй, а не то, что находится в указателе, киса. >>620324 Долбоеб. 16 - это кол-во байт передаваемых в MessageBoxA(dword hwnd, dword capture, dword text, dword status(или как там)); дебильный блядь. А ты думал это под дос, сука, мессадж бокс блядь? Охуеть не встать. Иди блядь мсдн читай, уебок.
>>620322 Потому что внутри while и s, и t уже инкрементировались и указывают на следующий символ. Ты, кстати, хуйней какой-то занимаешься, нормальные компиляторы все равно обнаруживают эти паттерны и заменяют на вызовы библиотечных функций (которые быстрее потому что реализованы через sse.)
>>620333 Кто тебе сказал, что через регистры, уебок? А ты не слышал о том, что можно передавать адрес операнда, который находится в переменной? Ты не слышал про макро среду языков ассемблера различных? Не? И если что в таблице экспорта именно так обозначается все. Ебать ты даун, хуево быть тобой. Не надо ему мсдн читать, бля. Охуеть не встать, с какими ебланами я на борде сижу.
>>620315 >Почему я долбоеб? Тебе все перечислить? 1. Не проверяешь возвращенный malloc-ом результат на NULL. 2. Не освобождаешь память. 3. А нахуя ты ее вообще выделил-то? 4. Массив t не инициализирован перед использованием, привет undefined behavior. 5. Первый аргумент pthread_create - не просто какой-то произвольный указатель. По этому указателю будет записан ид созданного потока. Собственно, у тебя падает как раз потому что этот ид записывается в рандомное место памяти. 6. print кастуется к несовместимоу типу. 7. После создания потока его надо где-то либо join-ить, либо detach-ить. 8. main должна возвращать int, но return нигде не видно. 9. print неправильного типа - она не принимает аргументов, а должна принимать один типа "указатель на void". 10. i не атомарная, поэтому в i++ возникает race condition между потоками. 11. print должна возвращать указатель на void, но return опять нигде нет. 12. Компилируй gcc -Wall -Wextra -Werror -pthread yoba.c -o yoba, тогда гцц тебе сразу все это укажет.
>>620335 >Кто тебе сказал, что через регистры, уебок? Я и говорю, какой мудак в 2016 на 64-битном хуе86 передает не через них? Шиндовсбляди, видимо. >А ты не слышал о том, что можно передавать адрес операнда, который находится в переменной? Это тут вообще при чем? >Ты не слышал про макро среду языков ассемблера различных? Ты не слышал про си?
>>620350 >64-битный fastcall Во-первых он называется System V ABI. Во-вторых в шиндовсе опять свой стандарт. Он, кстати, довольно интересный - первые 4 аргумента передаются через регистры, но 32 байта на стеке под них все равно выделить надо (но не надо заполнять), причем даже если функция принимает меньше 4 аргументов. Остальные аргументы идут над этими 32 байтами.
>>620355 > pthread_t t[0x7fffffff]; Всегда так делаю.
> ЧЯДНТ Не прочитал ничего про многопоточное программирование. Например, у address все шансы затереться раньше, чем поток им воспользуется. И я тебе уже об этом писал в середине треда.
>>620365 А если требуется брать много памяти, а система и так загружена? Будто что-то плохое, предусмотреть такую ситуацию. Тем более, она вполне реальна.
>>620371 > предусмотреть такую ситуацию И свалиться не просто, а успев выругаться в консолечку. Потому что в программе серьезнее хелловорлда выругаться в логи может не получиться, и показать уведомление может не получиться, и даже завершиться красиво может не получиться. Поэтому если программа не сервис, мелкие аллокации проще всего вообще не проверять и в том редком случае, когда память кончится, просто свалиться.
>>620376 >Потому что в программе серьезнее хелловорлда выругаться в логи может не получиться, и показать уведомление может не получиться, и даже завершиться красиво может не получиться. А может и получиться. Гвидон вон вполне нормально бросает MemoryError в таких случаях.
>>620378 Да и сваливаться ведь не обязательно. Иногда же бывают случаи, когда невозможность выделения памяти не является критической ошибкой. В таком случае, можно просто залочить возможность на некоторое время или же просто выделить меньше памяти, если это возможно.
>>620322 У тебя же есть реализованный strlen if (strlen(s)<strlen(t)) return -1; if (strlen(s)>strlen(t)) return 1; if (strlen(s)==strlen(t)) return 0;
>>620423 Да, а что? Если что это >>620375 не мой пост. Мне от браузера данные надо получить, у меня SSL соединение устанавливается нормально, а заголовок дождаться не получается.
>>620429 В древней опере тестирую, всё почти нормально. Хотя бы первый запрос обработать получается, а keep-alive по таймауту завершаю. А с хромом ни в какую. Он пересоздаёт подключение, запрашивает одну страницу, а остальные отваливаются на select с нулём байт и не срабатывает таймаут.
Поясните по поводу assert(). Я правильно понимаю, что его стоит использовать только на этапе отладки? То есть оттестил программу, а когда релизишь, то надо ставить #define NDEBUG?
>>620341 >Не освобождаешь память. Если память используется на протяжении всей работы программы, какой смысл её освобождать по завершении программы? Она будет автоматически освобождена операционной системой.
>>620513 >Если память используется на протяжении всей работы программы Как часто такое бывает? Если маленькое приложение, ладно. Но вообще, всегда рекомендуется это делать явно для обеспечения все той же переносимости. Да и разве сложно сделать это?
>>620421 > нет больше данных Да, например если удаленный хост закрыл соединение (сделал shutdown(..., SD_SEND)), по TCP уйдет FIN, select на другой стороне прервется, а в сокете будет 0 байтов. Может быть, у тебя в реализации протокола проблемы, и оно просто не хочет с тобой разговаривать?
>>620450 Да, именно так. Если не нравится, можешь сделать общий хедер и инвертировать в нем условие (#ifndef DEBUG #define NDEBUG ... #endif). И потом собирать с -DDEBUG, а релиз без. Ну а оставлять ли ассерты в релизах - дело твое. Только не используй их по назначению - для проверки соблюдения контракта, а не вместо обработки ошибок.
>>620553 Такое бывает часто, в любой мелкоутилитке. При нормальном выходе рантайм обязан сделать и flush файлам, и закрыть их потом, и память освободить.
>>620377 >сырые сокеты А они разве нужны для сканера портов? Если я не ошибаюсь, сырые сокеты просто позволяют тебе собрать свой пакет, со своими параметрами, не прибегая к помощи ядра. А для сканера портов не будет достаточно, просто слать TCP и/или UDP пакеты и просто ждать ответа? Или есть нюансы?
>>620781 Ладно. Попробую почитать на досуге подробнее о сырых сокетах. Пока мне на голову приходит только: 1) отправить SYN; 2) дождаться SYN/ACK; 3) перейти к следующему порту, не отправляя ACK.
>>620792 Да, именно так. Только желательно на SYN/ACK отвечать RST, чтобы все были счастливы а то мало ли, хост решит, что это у тебя SYN flood такой и обидится. Алсо, у нас тут тредик про сишечку. А про хакеров где-то рядом тонет.
>>621005 Спасибо. Собственно, проблема в том, что пока-что программа работает в диалоговом режиме - я ввожу команды протокола, а сервер мне отвечает. Вот тут и появляются проблемы. Или программа виснет на recv() после отправки первой же команды, или при использовании неблокирующего сокета recv() как-то странно данные возвращает, с запаздыванием на пару отправленных команд. Скорее всего, это я накосячил, но как поправить - непонятно.
>>621018 Покажи код, может быть? Попробуй написать простой телнет-клиент для начала и потестить на локалном netcat - сразу увидишь, где и как у тебя что отправляется. Потом этим же телнет-клиентом уже к ftp вручную коннектиться попробуй.
>>621138 В си с юникодом традиционно все плохо (до C11). Конкретно не так ты указываешь format specifier - 'c' - это char, а чтобы был wchar_t, надо '%lc'. Дальше тебе стоит кодировку исходника. Например, в гцц -finput-charset по умолчанию UTF-8, другие компиляторы не будем показывать пальцем могут ожидать какую-то другую. А если у тебя шиндоус, тебя ждут проблемы в MSVCRT, баги в реализации консоли и прочие радости. В определенный момент ты решишь написать свой велосипед для вывода в консоль под виндой, я гарантирую это.
>>621173 gcc rus_alpha.c -finput-charset=UTF8 Так? Если да, то мне вместо символов выводит знаки вопроса. Кодировка в терминале (xfce4-terminal) также UTF-8.
>>621188 Хуй знает. По идее, да. Зачем тебе это вообще? Выводи UTF-8 через printf, это работает и не требует усилий.
>>621192 С '%c' оно берет из аргументов int и преобразовывает к signed char. А если из юникодной кириллицы отбросить старшие биты, ничего похожего на нормальный результат получиться не должно в принципе.
>>621197 А, ну если тебе с символами работать, то конечно так не получится разве что делать работу %lc вручную, wctomb, все дела. А просто вывод строк работает если терминал UTF-8.
>>621579 Чтобы дождаться данных select(0, ..., ..., ..., &timeout); Если возвращает >= 1, то данные есть. Если ты передавал больше 1 сокета, то используй макрос FD_ISSET. Если только один, то пришли данные на этот сокет. Если < 0, то отвалилось по таймауту или какая-то ошибка.
Чтобы узнать, сколько на данный момент доступно данных ioctlsocket(bind_socket, FIONREAD, &read_byte);
А если ты мне ответишь на вопрос, почему select возвращает 1, а ioctlsocket ноль, буду очень благодарен.
>>621588 Сначала инкрементируется, затем сравнится. Если префиксная форма, то инкрементируется перед операцией, если постфиксная — после выполнения операции над i.
>>621588 Что именно у тебя вызывает сложности? Префиксный инкремент/декремент выполняется до обращения к переменной, постфиксный, соответственно, после. В твоём примере произойдёт увеличение i на единицу и сравнение его с len, поэтому ты не обработаешь последний символ. Здесь надо постфиксный. Или местами поменять условие, т.к. у тебя i будет указывать на следующий символ за нужным тебе. Ещё неплохо бы inq изменять каким-то образом в сторону увеличения.
>хочу организовать такой крутой цикл в одну строчку Оно, конечно, круто while (∗s++ = ∗t++), но, как по мне, лучше избегать таких конструкций.
>>621713 > ∗s++ = ∗t++ > лучше избегать таких конструкций Это идиома, ее поведение абсолютно прозрачно, зачем ее избегать? Другое дело, что конкретно в примере >>621588 лучше сделать нечто вроде: while (i < len && !isalpha(inq[ i ])) ++i; или в крайнем случае пустой for а еще лучше функцию типа skip_non_alpha, тогда будет одновременно читаемо и красиво.
>>621690 > как в winsock узнать, есть ли данные, которые сокет принял и можно их оттуда забирать Это целиком и полностью неверный подход: это очень медленно, и это неудобно, когда у тебя много сокетов. Правильнее попросить систему уведомить тебя, когда можно будет читать/писать. И вот тут появляются варианты. Если уже есть окно, и нужно передавать медленно и немного - WSAAsyncSelect хватает с головой. Если скорость важна - overlapped IO или IOCP. Если не осилишь такое, WSAEventSelect. Если нужно кроссплатформенность - select. Если не осилишь ничего из описанного вообще, тогда блокирующие сокеты. А про существование FIONREAD лучше вообще пока забыть.
>>621690 > почему select возвращает 1, а ioctlsocket ноль select возвращает общее число выбранных дескрипторов (во всех наборах), а ioctlsocket - код ошибки.
>>621777 >Это идиома Просто привёл пример "крутого цикла в одну строку". Хотя мне всё равно не нравятся такие конструкции.
>Это целиком и полностью неверный подход А если у меня на каждое подключение создаётся отдельный поток? Не >>620375
>Если уже есть окно У меня нет виндового окна. Жду до таймаута с помощью select, потом читаю/закрываю, смотря что вернулось. >Если нужно кроссплатформенность - select Не сказать, что нужна. Но с помощью select и жду, когда данные придут. >overlapped IO или IOCP WSAIoctl, WSARecv, WASSend? Или что? >А про существование FIONREAD лучше вообще пока забыть. Что с ним не так? >ioctlsocket - код ошибки Не нашёл, как с помощью неё узнать код ошибки. Сделать неблокируемым, доступное кол-во байт и некое SIOCATMARK. Ошибка же через WSAGetLastError.
Грамотные примеры реализации можешь посоветовать, где посмотреть?
>>621852 > WSAIoctl, WSARecv, WASSend? Или что? Все функции, где есть lpOverlapped.
>> FIONREAD > Что с ним не так? А зачем лишний сисколл, если можно сразу прочитать, когда одна из функций ожидания сказала, что данные есть (или получить WSAEWOULDBLOCK без ожидания, если состояние сокета по какой-то причине неизвестно)?
> Не нашёл, как с помощью неё узнать код ошибки. Она сама возвращает SOCKET_ERROR, если ты ей неверные аргументы скормишь, и 0, если отработала нормально. А select возвращает SOCKET_ERROR (-1) или количество дескрипторов. Вопрос >>621690 вроде об этом был, разве нет?
>>621962 Разбираю даташит и атмеловские библиотеки, замечаю запись такого вида: var1 = (uint_8)(var2 >> 8); или просто: var1 = (unsigned char)var1;
Беглый просмотр по объявлению переменных объяснения не дал, что это за запись такая?
Также есть вопрос по поводу объявления функций, что такое inline разобрался, но почему очень часто функцию объявляют как static inline разобраться не могу.
>>621968 (имя_типа) переменная — это такое явное преобразование типов из одного в другой. static кажется и в случае с inline ограничивает ее область видимость до файла, в котором она находится. То есть, это функция будет видна только в том файле, в котором она объявлена.
>>621968 > но почему очень часто функцию объявляют как static inline разобраться не могу
static здесь говорит, что функцию снаружи вызывать никто не будет. Поэтому в объектный файл она может вообще не скомпилироваться, если компилер ее везде заинлайнит. Если просто inline, то компилер попытается инлайнить функцию везде, где может, но все равно дополнительно в объектник положит копию функции, которую можно вызвать снаружи. А она может и нахуй не нужна.
>>621971 Вот для примера: static inline a(int i) { return i + 1; } int b(int i) { return a(a(a(i))); }
Если положить в 1.c и компилировать с помощью `gcc -Os -c 1.c`, то на выходе в объектнике нет символа `a` (можно посмотреть с помощью `readelf -s 1.o`). Если же static убрать, то символ есть, то есть функция `a` теперь тоже есть в объектнике и ее можно вызвать снаружи.
>>621968 Когда не знаешь, попробуй гуглить. https://gcc.gnu.org/onlinedocs/gcc/Inline.html >When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option -fkeep-inline-functions.
Как читать проекты на сишке? С чего начинат? Как определять "main" файл, который может носить произвольное название? С какого конца раскручивать? Мб лучше сначала хедеры читать, а потом *.c?
Просто я наткнулся на проект на ncurses, принцип работы которого хотел бы понять. А именно, как "прибит" интерфейс к самому приложению.
>>622007 Python/PHP/Java конечно На роутерах бэкенд иногда на сишечке, иногда на плюсах. За фреймворки не скажу, всё, что видел - велосипеды.
>>622009 Потоки, чуть лучший юникод, выравнивание в памяти, static_assert, анонимные структуры (как у MS было), _Generic, эксклюзивный доступ к файлам, ну и еще что-то по мелочи.
Товарищи, заметил непонятную ересь у себя. Сам я новичок, пишу на сях меньше пары месяцев. Есть код вида eoucheck = fgetc(DB_table); while (!feof(DB_table)) { while (eoucheck != '\n') { while (eoucheck != '|') {
который не работает. Он и не должен работать, или это я такой аутист?
>>622097 Дабы внести ясности (хотя, скорее всего, вам и так это ясно), не работает именно переход от строчки на другую строчку по завершению оной. При том варианте в посте, и >>622105 одинаково не работает именно это.
>>622112 Согласен, поэтому и спрашиваю. Окей, рассказываю поподробнее. Есть файлик DB_table с содержимым вида: S | himpanze G |orilla M | akaka Необходимо пройтись по строчкам и в переменную w1 вписать до |, а в w2 соответственно после. В общем, с этим все ясно. Я пришел к выводу, что можно пройтись по строчкам и до | с помощью fgetc() записать необходимые символы в переменную, и после | соответственно тоже. Код получился таким, каким я указал выше.
>>622123 Да, я думал о таком. Но как указать максимальный размер строки? Писать условный 1024? А если выйдет так, что строчка равно 1025? Или плевать на них, и сказать, мол, у меня запрещено так делать?
>>609376 (OP) Здраствуй анон, помоги нублу. Учу основы кодинга по пику, однако встал вопрос, который даже стыдно задавать, не могу понять как работает простейшая программка. Есть одна функция, которая выводит на экран строку в обратном порядке. void print_reverse(char s) { size_t len = strlen(s); char t = s + len -1; while(t >= s) { printf("%c", t); t = t - 1; } puts(""); } * Помоги, задать вопрос больше некому.
>>622128 Ну затратный он или нет, зависит от того, как ты будешь увеличивать. Куда затратней, статику большую использовать. Но в твоем случае, это вообще не существенно, так как у тебя больше нескольких кБ вероятно не будет.
Хм. Это нормально, что для массива структур, состоящей из ~70 указателей на char + несколько массивов char хватает только 75 плюс-минус 1 элемент? Дальше программно тоже нельзя для такой структуры выделять память... Система Debian, сборка с помощью CMake, если что.
Ну вот. Потом идёт Record Table[RNUM]; Где RNUM - количество читаемых строк из некоего файла, это число нельзя поставить больше 75. Может, нужно выделять память через malloc?
>>622795 Адрес имеет значение вида 0x0c4233dd. Число, которое сравнивается с указателем в том цикле является длинной строки. Сам подумай, есть ли в этом смысл.
>>622796 Уточнение: Было бы правильно, если бы сравнивался указатель на начало строки с указателем на начало строки + длинна строки. Тогда было бы нормально.
>>622797 Но как тогда "передвинуть" указатель первого символа строки на Nый символ оной? Видимо я недопонял саму концепцию операций над указателями, лол
>>622799 Ты передал первый элемент массива через аргумент. Создай в той же функции указатель, который будет указывать на то, что ты передал (начало строки), Это для того, чтобы не потерять саму строку. Затем, ты можешь делать со строкой все что угодно. Для того чтобы передвинуть указатель, тебе нужно добавить целое число. Допустим есть у тебя указатель на char. Прибавляя единицу, ты сдвинешься на один байт. Если указатель будет на double, добавив единицу, ты сдвинешься на 8 байт, так как double = 8 байтам. Естественно, размеры char, int , double - не фиксированы и зависят от платформы. Но я взял к примеру amd64.
>>622803 Да. Перечитай и попрактикуйся. Указатели лишь поначалу кажутся сложными и непонятными, но если приловчится, начинаешь без проблем работать даже с самыми сложными конструкциями. Ага. Если ты про книги, юникод и комментарии.
>>623088 Нет. Возьмем этот https://ideone.com/xixkIN пример (не обращай внимание, что код в не абсолютно не правильный). Здесь на строке 17 и 33 у нас определения функций. Аргументы, которые они принимают — формальные. То есть на не обязательно, передавать аргументы с теми именами, которые указаны. Главное чтобы тип совпадал. А вот вызовы этих функций, на строке 39 и 49 — принимают фактические аргументы.
>>623090 А, ясно короче, блин. Лол. а так описано ФОРМАЛЬНЫЕ ФАКТИЧЕСКИЕ, лол, я думал там сложно А это оказывается принимаемые параметры и объявляемые в фцункции, спасибо.
>>623095 Небольшое уточнение.Это параметры объявляемой и вызываемой функции. >int huy (int govno)//формальный {..} Здесь именно int govno - формальный параметр >huy(huy_pizda) - фактически huy_pizda - фактический параметр.
>>622219 Опять я выхожу на связь. Портирую свою программу на виндовс. Через тот же Qt и CMake. И тут вылезает такая segmentation fault в следующем участке:
char buf=((char)malloc(sizeof(char)10BUF_SIZE)); <- если использовать такую конструкцию, то для буфера хватит аж целых 10 кБ, и никакой ошибки не возникает
char buf; <- если использовать такое объявление и прикрутить проверку на выделение памяти, вылезает segmentation fault и пишет Out of memory: not enough space (причём здесь выделяется всего лишь 1кБ. if ((buf=((char)malloc(sizeof(char)*BUF_SIZE)))==NULL){ perror("Out of memory"); system("pause"); exit (-1); }
>>623144 А я по твоему должен думать о нищебродах, у которых меньше 8Гб ОЗУ? Да я не он. Просто вспомнил многопоточный сканер портов, который был сотней постами ранее.
>>623184 Хм. Возможно, стоит отказаться от использования этой функции. Дефайн вот: #define BUF_SIZE 500 Если поставить, к примеру, 1000, то программа не выдерживает. Пробовал объявить и глобальную size_t BUF_SIZE=1000; Проблема та же.
>>623197 Не нужен ему memset, он всё равно буфер заполняет из файла. >>623200 Не поленился и проверил твою функцию. Как и ожидалось, всё нормально выполняется. Ошибка не в ней.
>>623212 А, тогда норм. QtCreator ещё почему-то не завершает программу, которая запустилась нормально и завершилась нормально, и если не убить её вручную, то следующий запуск будет с фейлом.
>>623266 Не совсем понятно, зачем там add esi,24 и прочие shr до dec. В остальном все ок же. Я бы сделал fldz и цикл из нужного количества fadd. Как-нибудь так: http://pastebin.com/LUPasL1Z
программач, вот я, допустим, угорел по С и подучив немного теорию захотел реализовать свои новоприобритенные навыки - стоит лезть на гитхаб в относительно простые проекты со своими предложениями? свои велосипеды писать не хочется тк быстро надоедает написание программ бесцельно, а тут какая-никакая польза вред для сообщества. Или есть места более для этого подходящие? Или вообще стоит порешать задачи университетские (методички и прочее)?
>>623372 Гитхаб норм же. Можешь какого-нибудь инди-разработчика найти с проектом, который тебе интересен - и он будет рад внезапным помощникам, и тебе опыт.
это потому что такие значение линкером помечаются как экспортируемые, а для каждого экспортируемого символа должно быть ровно одно значение на все файлы.
еще можно в cpu.h просто пометить переменные как static, тогда на самом деле main.c и cpu.c будут использовать разные копии.
>>625237 Во-первых, это всего лишь потому, что fclose делает fflush, а во-вторых, ОС может с тобой не согласиться, а накопитель тем более может не согласиться.
Ну какой может, да лишь потому. Есть описание - по нему и нужно думать. А как там внутри - сёдня так, завтра сяк - и только линус будет возникать в защиту говнокодеров.
>>625245 Ну всякие part of speech tagger (проставлялка частей речи, допустим в английском), какие-нибудь библиотеки для автоматизации рутинной ебли с указателями на массив символов. Регекспы устраивают, но не совсем. Да и медленновато ими.
>>625247 Ну это уже совсем новый уровень не слышал про такое никогда лол, вряд-ли это к "программированию" прям вопрос, хотя я и других библиотек не знаю, более приземлённых.
Можно попробовать погуглить "C библиотека распознавания частей предложений" Забавно, если добавить в запрос "C" то часто по теме ищет... Хотя 1 символ то. - но наверно ты это сделал уже, и спросил за опыт пользования.
>>625475 Ну как бы это сказать, треды ты же про них?, сильно платформо-зависимы. Например, под линь можно почитать боровского - коротенькие статейки с примерами.
>>613522 >так и больше размера size_t Карнавал продолжается. Хотя с числовыми эквивалентами указателей дикий наёб (вспомнить хоть ptrdiff_t к тому), тут только строго c99 (со своими модными intptr_t и uintptr_t) иначе не как .
>>619834 В чём проблема то? Бери да кастуй, не нравится - определяй юнион, если там есть массивы переменной длины - объявляй структуру прям внутри функции, где укажешь какой размер массивов в данный момент. А вообще, я не понял что хочешь ты.
>>620081 >Стандарт запрещает Стандарт определяет тебе за щеку. Какая хуйня разница на порядок байт, если это не внешние данные, например Или с чего ты взял что это не так?
>>620297 Мелкомягие тоже могут, оказывается )) C:\TEMP\1>cl /GS- 2.c /link /NODEFAULTLIB /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE /IGNORE:4254 kernel32.lib Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved.
2.c Microsoft (R) Incremental Linker Version 8.00.50727.42 Copyright (C) Microsoft Corporation. All rights reserved.
Есть два массива c[j ... q-1] и a[k ... p + q - 1]. Как скопировать c в a проще всего? Есть какая-нибудь функция? Индексы могут быть любыми, т.е. мы отрезок одного массива копируем в отрезок другого массива.
>>626278 Я уже погуглил memcpy. Как его правильно использовать, если массив C создан на куче? Есть указатель на его начало. Как с его помощью копировать диапазон элементов из данного массива в другой?
>>626286 Считаешь, сколько тебе элементов нужно скопировать. Копируешь: memcpy(&dest_array[dest_index], &source_array[source_index], sizeof(source_array[0]) ∗ num_elemets); Где созданы массивы, значения не имеет. Разве что, если диапазоны хотя бы частично перекрывают друг друга, нужно использовать memmove. Выражение &array[index] можно заменить на array + index, это вопрос личных предпочтений. Я считаю, что с & и индексом нагляднее.
>>626314 Я вот что пишу. Видимо, я неправильно использую memset, потому что даже спижженное откуда-то копирование при помощи двух циклов дает мне некоторое подобие отсортированного списка. У меня же получается просто мусор.
>>626407 Вот моя окончательная реализация, господа. https://ideone.com/quzyJ8 В процедуре mergesort выделяется память для двух массивов даже когда не выполняется условие n > 1, то есть будет утечка памяти. Как это исправить? Можно освобождать память внутри mergesort, но ведь логичнее это делать после слияния, когда массивы стали больше не нужны.
>>626554 Почему? Он как раз всё по Линусу предлагает: [CODE] The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas must not overlap. Use memmove(3) if the memory areas do overlap.[/CODE]
Анон поможи. [code] printing_str = int_data % 10 + '0'; [/code] Каким образом это работает? Остаток от деления int на int будет int и к нему прибавляют char '0'. Ничего не понятно. Тут какое-то хитрое преобразования типов?
>>626937 char - беззнаковый целочисленный 1-байтный тип данных. То есть [0; 255]. В стандартной кодировке числа идут по порядку, поэтому можно из '0' сделать '1', прибавив единицу. Или из 'a' сделать 'b'.
>>626937 Про типы данных в выражениях тебе нужно знать одно: если они меньше чем int они неявно кастуються в int, если больше, например безнаковый int, то кастуются в большое, понятно, по приоритетам операций. Всё, например, просто.
>>626963 >char - беззнаковый целочисленный 1-байтный тип данных. То есть [0; 255]. Блять, вы же тралите так? Как вас земля носит. Знаковость он определил, ещё и диапазон вместимости чара, ну ахуеть.
Лол, нашёл писанину, что я писал когда вкатывался, тогда я в це++ залез, и потом быстро вылез на ц.
class os_vzai .... DWORD, WORD я писал на винапи...какой шквар .... Методы заебись: void fu_cp_001(u_char bb) { //Просто пишим символ bool fu_cp_002(WORD beck,WORD fore) { //Устанавлеваем цвет от 0-15 void fu_cp_002(WORD beck) { //Устанавлеваем цвет от 0-15 void fu_cp_003(u_sint xz,u_sint yz) { //Размер консоли ....
Потом я видимо на структуру и функции переписал: struct OSVZAIM ....
OSVZAIM O1488=OSVZAIM(); - Что это в спп значит, помнит кто? #define CRE_ALL_CON_SHIT(); \ ({ \ O1488.CON_HAN_VIVO=GetStdHandle(STD_OUTPUT_HANDLE); \ O1488.CON_HAN_VVOD=GetStdHandle(STD_INPUT_HANDLE); \ ....
Короче это обёртка для вывода на виндавс консоль....
>memcpy acts randomly (and differently) with overlapping areas >It's a common bug to use memcpy() instead of memmove() >So from a pure Quality-of-Implementation standpoint, just make glibc implement memcpy() as memmove() >However, I still don't understand why you guys can't just admit that you might as well just do memmove() and be done with it.
Я тут хотел задать вопрос по поводу буфера. Правильно ли я делаю: 1) Задаю начальный размер буфера; 2) Выделяю память при помощи malloc; 3) Делаю цикл для считывания введенных символов с клавиатуры до тех пор, пока символом не станет '\n'; 4) В цикле есть счетчик, с помощью которого узнаю, не превышаю ли размера буфера; 5) В случае, если запись текущего символа превысит размер буфера будет превышен, удваиваю размер буфера при помощи realloc; 6) После цикла, выставляю '\0' в качестве значения для последнего элемента строки; 7) Если буфер заполнен не полностью, усекаю размер буфера до размера строки при помощи realloc. Все правильно делаю? Или можно как-то иначе и лучше сделать это?
>>627432 > В случае, если запись текущего символа превысит размер буфера будет превышен, посылаю нахуй пользователя, потому что 1кб на строчку должно хватать.
> realloc Не пользуйся этим говном. Память не нужно реалацировать, память нужно выделять и связывать.
>>627515 >посылаю нахуй пользователя, потому что 1кб на строчку должно хватать. >память нужно выделять и связывать. А если вместо пользователя файл? 1KB не хватит. А заранее выделить необходимое количество не выйдет.
>Не пользуйся этим говном. А вот здесь по-подробней. Что не так с этой функцией?
>>627522 > А если вместо пользователя файл И что, там будут строки больше 1кб? Вот ты прочитал строку, дальше ты с ней что делаешь?
> Что не так с этой функцией? Всё так, я просто боевой школьник, и иметь кучу вызовов алока/реалока - странно, суть всегда в том, чтобы сразу выделить много и этим пользоваться. Усекать уж точно не нужно, как и давать возможность пользователи запросить бесконечно много памяти.
Язык с++ Одну из ниже перечисленных ПРОШУ, ПОМОГИТЕ. ЗАВТРА ВЫЕБУТ 1. Программа, подсчитывающая, в какой день недели родились. Входные данные - дата рождения. 2. Программа, считающая количество полных дней с даты рождения. Входные данные - дата рождения и текущая дата. 3. Программа, определяющая, високосный ли год. Входные данные - год.
>>627677 Просто char в функциях с переменным числом аргументов автоматически преобразуется к int. Спецификатор %x предназначен как раз для вывода int, и этот самый int он и выводит. Но размер типа char от этого, конечно же, не меняется, поэтому второй спецификатор выводит 1.
>>627731 Если функция принимает char (есть формальный параметр), то на x86 компилятор может сделать push eax, не обнуляя старшие биты eax. Если функция с переменным числом аргументов, компилятор обязан будет сначала сделать movsx.
>>627508 Он пишет про workaround для решения проблем, вызванных некорректным использованием memcpy() разработчиками софта. >заебись так сделать memcpy как memmove По факту там хуйнули патч для x86 архитектуры, что заместо memcpy() вызывался memmove(), т.к. он работает нормально с overlapped буферами. Каким макаром замечание, что >если диапазоны хотя бы частично перекрывают друг друга, нужно использовать memmove противоречит Линусу, я не понимаю. Хотя о чём с тобой говорить.............
>>627759 Проиворечит линусу то, что он допускает неправильное использование memcpy, при перекрывающихся (и пошёл хуярить именно на либу), а ты предлагаешь человеку делать "как надо" - но ты нихуя не улавливаешь ни связи, не смысла - уёбок, что с тобой сделать................................
>>627787 >>627759 Вы уже надоели! Читаю вас и не могу понять, о чем вы спорите. Какие-то последователи Линуса или что-то еще. Просто объясните мне. Читаю я значит в мане, что рекомендуется использовать вместо memcpy, memmove в случае, если одна область (в которую копируем) накладывается на другую. Что не так?
Не напомните, GTK3 имеет обратную совместимость с GTK2. Или они все сломали? Просто думаю вкатиться по этому протухшему мануалу https://developer.gnome.org/gtk-tutorial/2.90/ , так как других не вижу.
>>627800 Тоже не могу понять, о чем спор. То, что в каких-то линуксах реализация memmove практически идентична по быстродействию memcpy, не означает, что так будет в других реализациях на других платформах. Поэтому правила остаются теми же: 1) memmove, если области перекрываются или есть сомнения. 2) memcpy в остальных случаях.
>>627841 Понятно. Очередной Qt фанатик. А я надеялся ты аргументируешь как-то. На линуксах оно живее всех живых ведь. GNOME 3 хоть и утратил популярность, но держится на плаву. А крыса и вовсе сейчас процветает (вероятно скоро самой популярной станет), так как у нее многие пользователи — это беженцы с тех же KDE и GNOME, в которых от релиза к релизу все ломают. Также есть множество людей, которые предпочитают чистый Си, а не кресты (я не из таких). Впрочем, это уже тема для срача.
>>627851 Я не фанатик, я просто реалист. Когда даже такие крупные проекты как, например, Wireshark валят с гтк (или скорее валят на qt), это о чем-то говорит.
>>627850 У меня складывается такое впечатление, что они начитаются статей от васянов на какой-то хабре или прочем ресурсе и принимают сказанное за истину, вместо того, чтобы самостоятельно разобраться в теме.
>>628047 Они еще тестируют его. И пока у них две версии (Qt, GTK), рано еще говорить о чем-либо говорить. Есть вероятность, что они и в Qt найдут какой-нибудь фатальный недостаток, коих у обоих тулкитов достаточно.
>>628628 Да это не я, просто тредами как-то не баловался ещё, буду базу данных писать, запилю её на тредах, чтоль, один обработчик ввода, другие - выполнение. Ввод/вывод - пайпы, или сокеты, хмм....
>>609376 (OP) Ребят, кстати, почему в рекомендациях нет "Искусства Эксплойта" второго издания Эриксона? Там же охуенное введение, как в С, так и сразу же на наглядных примерах его применение. Там даже с отладчиком сразу показывают, как работать надо. http://www.ozon.ru/context/detail/id/4833854/ хотя по любому уже и так в сети есть
>>628629 Почитай про мнопоточность лучше. В случае с серваками, если я не ошибаюсь применяют две модели: 1) поток на соединение; 2) поток управляемый событием (то есть потоки используются по мере надобности); Не расходуй ресурсы процессора впустую. На ввод/вывод требуется очень мало ресурсов процессора. Оно там не нужно.
>>628634 Не стоит. Ты видишь какой здесь контингент? Лучше пусть изучают принципы программирования, а не то каждый ньюфаг сразу будет хватать это и задавать глупые вопросы.
>Оно там не нужно Что значит не нужно, а кто будет рождать потоки на выполнение? Я хочу чтобы можно было, например параллельно вести поиск чего-то по базе. Да и её саму (базу) в отдельный процесс.
>>628644 >Я и так вкурсе вопроса. Сомневаюсь, если ты собрался на I/O выделять отдельные потоки. Или может я тебя не правильно понял, В любом случае, то что ты просил уже нет. Да и не нужно оно, так как не было сделано нормально (массив потоков в 4Гб).
>>628657 Очень давно его не читал. Но честно говоря год назад наткнулся на его вью и как-то он имхо, как человек, дико испортился. Видимо после визита ФБР.
>>628659 Здесь вечный срач. Интелловский самый распространенный, так как интел его продвигает. AT&T многие считают очень удобным и более логичным. Но он настолько мало распространен.
>>628666 А, нет, там, вроде, интеловский. Зря я сиранул на синтаксис. Посоветуйте, как проще всего смотреть код сишных функций в дизассемблере, и я пойду обмазываться. До этого изучал в отладчике только проги на чистом асм.
>>628736 Ну ладно, ладно, убедили, скачаю. пойду memcpy использовать как memmove - хакирь же. Напишу плагин к браузерам, что-бы можно было красивую и мелковесную рекламу вешать - вот будет заебись
>>628736 С одной стороны, если учить Си и сразу смотреть, что творится на ассемблерном уровне, все становится простым и понятным. С другой стороны, потом нужно будет потратить много времени, чтобы избавиться от плохих привычек и начать писать кроссплатформенный код.
>>628752 > начать писать кроссплатформенный код Я бы хотел добавить, платформы и их популярность меняются достаточно часто, относительно того, что у новичка да и у других бывает в голове. Вот перешли все на 86-64, и охуели c того, что int может быть не равен размеру void*, да и стандарты до, были не полны, щас с11 - это реально глыба, и самое правильное на чём нужно писать в С. И так-то правильно понимать что ты пишешь, но не забывай что стандарт - это то в чём пересекаешься ты и те кто реализуют этому коду работу. Остальное - чёрная дыра.
Такая задача в ЕГЭ. Опишите на русском языке или одном из языков программирования алгоритм подсчета максимального количества подряд идущих четных элементов в целочисленном массиве длины 30. Вот мое решение. Правильно? алсо, как сделать проверку на пустой элемент массива? http://pastebin.com/xJGMMST1
>>628982 Тебе разве здесь не нужно найти максимальное количество подряд идущих элементов? У тебя сейчас ищется общее количество подряд идущих. А по поводу пустого элемента — никак. В элементах, которые у тебя есть, могут быть любые числа. Даже если ты инициализируешь их каким-то числом, это может быть неправильно, так как придется зарезервировать одно число для этого. По поводу кода. Зачем тебе sdafx, iostream и locale? Они не нужны. locale может пригодится, разве чтобы на кириллице писать. Зачем тебе system? Это тоже излишне.
>>628993 Ты еблан даже не знаешь зачем sdafx нужен. Это блядь файл с прекомпилированными блядь заголовками, для проекта уровня laba2 они не нужны, потому что он и так за пару секунд компилиться.
>>629008 Лично мне, лень рассматривать внимательно твой быдлокод. У меня есть и другие дела. Думаю у других, здесь находящихся, все так же. У тебя простейшая задача. Сделал? Работает? Иди сдавай! Эффективно сделаешь когда ума наберешься.
>>628736 >>628634 Так ли хороша эта книга? На одном книжном сайте писали, что программы там суперхуевы, а другой каментатар ответил, что реальные программы пишутся так же, и поэтому изучение говна дает понимание того, как говно хекать.
>>629091 >bool Сам без понятия нахуя оно нужно, вот еслиб он конвертировал возврат из функции (из стандартных) как "получилось", "не получилось" - это другое дело, только это не С. Но а так то - прост)
> Что-то странная система Она логичная, есть диапазоны положительного исхода, есть отрицательного. Выявить принадлежность просто, >0 или <0. Что тут странного?
>Что тут странного? Все нормально. Просто я не выспался и перемешалось все в голове.
>>629395 > всю еблю с указателями, памятью, переполнениями буферов и, Это в K&R есть.
> сетевая стекоебля. А это, уже не имеет прямого отношения к самой Си, но есть в различных источниках. Точкой входа можно взять "Компьютерные сети" Таненбаума.
>>629409 > "Компьютерные сети" Таненбаума А чё не снайдер? Чтобы вкатится сходу, можно накатить статейку шаргина на рсдн Программирование сокетов в Linux.
>>629430 Павильно. В случае, если где-то в середине массива условие не будет соблюдаться, submax'y опять присвоится 0, и дальше твой if if(max<submax) будет False, в следствие чего и max будет считаться не правильно.
>>629423 Может лучше сначала изучить как работает сеть, перед тем, как йписать приложения для работы с ней? Таненбаум дает фундаментальные знания просто.
>>629424 >Только там все с крайне наглядными примерами в отличие от K&R Не осилил примеры из K&R?
>с чего это не имеет? Потому, что это сторонние API, а не стандарт Си.
> Елси ты уже такой охуенный парень, что освоил C по K&R Ну охуеть теперь.
>>629440 >Может лучше сначала изучить как работает сеть Лучше, всё-же, сходу иметь работающий код, а потом сидеть понимать как он работает, модифицирую его там, переписывая на более низкий уровень, итп. Хотя это всё, например, дискуссионно.
Платиновый вопрос: как программы на сишке взаимодействуют с другими (внешними) программами на ней же, допустим из ГНУшных утилит? То есть, допустим, я могу вызвать grep из сишки? Могу скормить вывод ls?
>>629482 >Платиновый вопрос: как программы на сишке взаимодействуют с другими (внешними) программами на ней же Посредством: 1) Перенаправление вывода другой программы; 2) FIFO; 3) Сигналы.
>>629494 >То есть, допустим, я могу вызвать grep из сишки? Могу скормить вывод ls? Перенаправление потоков. То есть stdout одной программы (ls) перенаправляется на stdin grep. В качестве теста, можешь в цикле, прогнать getchar.
Интересно, откуда здесь взялся pop ecx? Ведь мы ecx до этого не сохраняли, а сохраняли ebp, который здесь вытаскиваем. Зачем? Эта инструкция повторяется десять раз, хотя мы ничего не кладем на стек кроме адреса возврата, который после выполнения call сам оттуда извлекается.
Что читать:
- Классика от Отцов: http://www.ime.usp.br/~pf/Kernighan-Ritchie/C-Programming-Ebook.pdf
- Годное пособие для гуманитариев: http://c.learncodethehardway.org/book/
- Немного примеров хорошего стиля: http://www.oualline.com/books.free/style/index.html
- ООП, например: http://www.cs.rit.edu/%7Eats/books/ooc.pdf
- Стандарт ISO/IEC 9899:1999 (он же C99): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf (драфт) не драфт ищем на торрентах
- Стандарт ISO/IEC 9899:2011 (он же C11): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (драфт)
- man/Dash/zealdocs
Чем конпелировать:
- Очевидный GCC.
- clang: оче годно, батя рекомендует. Дрочим на --analyze.
- Intel C++ Compiler: оптимизации, тысячи их.
- Visual Studio 2015 Community Edition: внезапно этим стало можно пользоваться. Поддержка C11 на уровне "есть все, что тебе понадобится в реальном проекте плюс кривая библиотека" (да, в студию в последнее время завезли stdint и stdbool, почти все новые фишки из C11, static_assert и даже юникод). C snprintf все до сих пор плохо. Анализатор кода в комплекте.
- Pelles C (шиндоуз онли): поучиться, вкатиться в C11 (в частности, потыкать threads.h и stdatomic.h), но количество багов в оптимизаторе и редкие апдейты напрочь отбивают желание собирать этим что-то сколько-нибудь серьезное.
- TCC: очень маленький компилятор с багами и неполной поддержкой C99.
- Borl... ээээ...
Что еще почитать:
http://c-faq.com/
FAQ из comp.lang.c. Древний, но все еще актуален.
Stephen Prata "C Primer Plus, 6th Edition" (2014)
Свежая знает про C89, C99, C11, описывает различия, объемная около тысячи страниц, годная хотя есть некоторые шероховатости, с вопросами, упражнениями и ответами. Читать после K&R или до.
Samuel P. Harbison, Guy L. Steele Jr. "C: A Reference Manual, 5th Edition" (2002)
Ебаный пересказ стандартов C89 и C99 (включая стандартную библиотеку). Для не осиливающих стандарт в оригинале. Читать в качестве подготовки к собеседованиям (есть задачник с ответами) и для ознакомления с масштабами пиздеца перед написанием своего парсера/компилера.
Peter Van Der Linden "Expert C Programming. Deep C Secrets" (1994)
"Си: грязные истории". Смехуечки, немного объяснений, чем обусловлены особенности языка, всем известные подводные камни кто там ругал косяки в JS? у нас в сишечке их гораздо больше, просто они лучше спрятаны, немного байтоебли и непонятно откуда взявшаяся глава про старинные плюсы. Читать в качестве сказки на ночь (на пару вечеров хватит).
Ben Klemens "21st Century C: C Tips from the New School" (2012)
Stephen G. Kochan "Programming in C (4th Edition)" (2014)
Прошлые треды:
- https://arhivach.org/thread/106153/
- https://arhivach.org/thread/131949/