Это копия, сохраненная 1 августа 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ https://wandbox.org/ или https://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Brian Kernighan, Dennis Ritchie "The C Programming Language": http://www.cypress.com/file/56651/download
- Stephen Prata "C Primer Plus, 6th Edition" (2014): относительно свежая, знает про C89/C99/C11, описывает различия, объемная (около тысячи страниц), годная, с вопросами, упражнениями и ответами. Читать после K&R или до.
- Zed A. Shaw "Learn C the Hard Way" (2015): годное пособие для гуманитариев для гуманитариев!
- Немного примеров хорошего стиля: http://www.oualline.com/books.free/style/index.html
- ООП, например: http://www.cs.rit.edu/~ats/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 (драфт)
- Черновик стандарта ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf (февраль 2020, с диффами)
- Последний черновик ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf (декабрь 2020)
Чем компилировать:
- Очевидный GCC.
- clang: оче годно, батя рекомендует.
- Intel C++ Compiler: оптимизации, тысячи их.
- Visual Studio Community Edition: внезапно этим стало можно пользоваться, особенно с тулсетом clang/C2. Поддержка C11 на уровне "есть все, что тебе понадобится в реальном проекте плюс кривая библиотека". Анализатор кода в комплекте.
- Pelles C (шиндоуз онли): поучиться, вкатиться в C11 (стандарт полностью реализован, имеются в том числе threads.h и прочие stdatomic.h), но количество багов в оптимизаторе и редкие апдейты напрочь отбивают желание собирать этим что-то сколько-нибудь серьезное.
- TCC: очень маленький компилятор с багами и поддержкой C99. С ключом -run умеет компилировать код в память и запускать его, что позволяет писать скрипты прямо на сишечке.
Что еще почитать:
http://c-faq.com/
FAQ из comp.lang.c. Древний, но все еще актуален.
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? у нас в сишечке их гораздо больше, просто они лучше спрятаны, немного байтоебли и непонятно откуда взявшаяся глава про старинные плюсы. Читать в качестве сказки на ночь (на пару вечеров хватит).
Richard M. Reese "Understanding and Using C Pointers. Core Techniques for Memory Management" (2013) - почитать, вкатиться в указатели.
Ben Klemens "21st Century C: C Tips from the New School" (2012)
Paul Deitel, Harvey Deitel "C for Programmers with an Introduction to C11" (2013)
Stephen G. Koch@n "Programming in C (3rd Edition или 4th Edition, если найдется)" (2014)
MISRA Ltd. "Guidelines for the Use of the C Language in Critical Systems" (2013)
Набор рекомендаций по написанию надежного кода на C (промышленный стандарт). Читать - однозначно, следовать - вдумчиво и без фанатизма. Также можно посмотреть https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard и http://web.archive.org/web/20190213011655/homepages.inf.ed.ac.uk/dts/pm/Papers/nasa-c-style.pdf
Еще более длинный список: http://www.iso-9899.info/wiki/Books#Learning_C
https://github.com/kozross/awesome-c
Онлайн-утилиты:
- https://godbolt.org/ - Compiler Explorer позволяет посмотреть выхлоп компиляторов для введенного куска кода (больше полусотни разных версий компиляторов).
- http://cdecl.org/ - С Gibberish ↔ English помогает читать сложные сишные декларации.
Прошлые треды:
- №66: http://arhivach.net/thread/637469/
- №67: http://arhivach.net/thread/667170/
- №68: http://arhivach.net/thread/667171/ >>1958625 (OP)
да плевать, удобнее пока ничего не придумали
Кыш отсюда, зеленокожий.
Люди серьезные. Си требует дисциплины, отваги, вагона знаний, твердости и четкости ума. Пишутся вещи непростые, для реализации коих требуется и смекалка, и немеренные знания предметной области, изучение лоулевел-программинга — это тебе не паддинги править, сынок, ты тредом ошибся.
Здесь тебе не питонотред или жс, обсуждать целыми тредами примеры из начала сраного byte of python не намерены, здесь люди ебашат K&R в одиночку без лишних вопросов, в их сторону достаточно кинуть парочку книг, все остальное лежит на их плечах, без лишнего пиздежа свое дело сделают.
576x1024, 0:25
Я хотел делать чтение, останавливать поток на сон (правда, на c++, но итт пацаны знают работу операционки), и через заданный интервал считывать значение заново. Короче, рилтайм. Я знаю, что есть системный high resolution clock, и как-то система потенциально знает, сколько прошло времени.
Нет, как раз потому что линукс не реалтайм. Он может провести хоть секунду в системном вызове, если захочет, и твой слип сработает гораздо позже, чем ты того хотел бы. Более-менее точно попасть в нужное время ты можешь так: выставить себе приоритет повыше, выставить affinity, и таким образом, отожрав целое ядро у процессора, крутиться в цикле безо всяких снов.
Хорошо. А есть какой-то подход о блокировке ядра (типа nop вставлять) на известное количество времени, а не тактов, с учётом плавания частоты ядра? Чтобы не выжирал энергию в простое?
Алсо, unix овский nanosleep() тоже не гарантирует микросекундную точность?
Здесь регистрами фонит по низам.
Нанослип ничего не гарантирует, он может округлять время вверх. Искользуй цикл с clock_gettime CLOCK_MONOTONIC. Может потребоваться что-то подкрутить в настройках ядра, чтобы таймеры работали точнее.
Ты spinlock хочешь сделать и не с NOP, а с PAUSE, если речь про xuy86.
Достаточно сложно, если ты хочешь серьезное что-то, а не поиграться. Для начала man setjmp, но вообще есть всякие готовые либы для green threads.
лол, ну если тебе нужна многопоточность в духе эрланга, может тебе прост оэрлангом и воспользоваться?
если нужна сишная многопоточность - гугли pthread, там, в принципе, ничего недоступного нету, есть какая-то старая книжка, есть годный мануал от почившего sun.
чё там, защищаешь общие ресурсы мьютексами, синхронищируешь кондишн-переменными. хуё-моё.
сложность - дело относительное. но многопоточность требует немного иного понимания, иного взгляда, там memory order'ом фонит по низам. Знаешь, один великий спец сказал, что распределённые вычисления есть наука о том, как на нескольких процессорах решить задачу, для которой достаточно одного.
Есть ли разница и как лучше возвращать структуры из функции? Например есть код, в котором мне нужно получить заполненную структуру данных просто struct с переменными. И вот я могу сделать функцию, которая будет возвращать MyStruct/const MyStruct&, или сделать воидовую функцию, которая будет принимать MyStruct& и там его заполнять. Я чёт пытался сам пример себе собрать, но не понимаю до конца, что конкретно происходит с структурами, когда я референсы на них возвращаю из функций? В первых двух вариантах с пикрила в функции и в вызывающем коде адреса у структур разные. Это типа что, на return'е функции структура копируется в памяти и в вызывающем коде референс уже на копию? При этом у struct3 в вызывающем коде адрес такой же, как и в создающей функции
Возвращай по значению. В современных крестах возврат оптимизируется по стандарту и функция реально работает внутри с той памятью в которую типа как эта структура вернётся из функции.
Возврат по значению быстрый только если у тебя размер не больше 8 байт (или 16 для 64-битного кода), и даже в этом случае есть подводные камни. Если тебе нужна скорость - функция с явным указателем/ссылкой лучше, при этом ты можешь заодно еще и статус вернуть нормальным способом.
>>033424
чо вы несёте, если компилятору меньше 20 лет, то он оптимизирует возврат любой структуры. это будет почти гарантированно быстрее доступа по указателю. при возврате структуры по значению получается более простая семантика для человека, и для компилятора, второе позволяет лучше делать кросс-оптимизацию. далее, для возврата структуры по значению, ты её наверняка будешь маллокать где-то - дополнительный вызов функции, потенциально кэш-локальность идёт по пизде.
На самом деле можно писать и так, и так.
Это зависит от того, чего тебе нужно достичь. Если, например, ты пишешь код для сдачи лабораторки какой-нибудь, то пиши так, как в методичке. Если же код для чего-то более серьёзного, то...
Я в подобных случаях смотрю на то, какой смысл у этой структуры данных.
Если это какая-то не очень большая временная структура либо если это какой-то не очень большой математический примитив фиксированного размера (например, вектор или матрица из трёх или четырёх float'ов - частые примитивы в компьютерной графике), то лучше возвращать целиком. Потому что вот такая запись
> mat4 c = Mat4xMat4(a, b)
гораздо приятнее и органичнее, чем
> mat4 c;
> Mat4xMat4(&c, a, b);
А ещё она позволит тебе перемножать много матриц по цепочке.
С другой стороны, если твоя структура олицетворяет собой некий объект "реального мира", даже если она очень небольшая, например, это частичка от огня или взрыва в той же компьютерной графике, описываемая тремя координатами и парой чисел сверху, то тут уже лучше работать с ней как с полноценным объектом.
> particle p;
> CreateFireParticle(x, y, z, &p);
Потому что этот код банально лучше масштабируется, ты можешь дописать к нему в будущем код возврата и тому подобное.
В плюсах есть свои способы сделать это, разумеется: классы, конструкторы, перегрузка операторов и всё такое, но это плюсы. Насчёт оптимизации же - я не думаю, что тебе оно надо, ведь сегодня машины слишком мощные, чтобы печься о каждом такте. А даже если и надо, то при вменяемых ключах оптимизации современный компилятор всё равно подставит (inline) твою короткую функцию куда надо, и разницы в производительности не будет в принципе.
стандарт ничего не говорит про детали реализации
Порекомендуйте oss статический анализатор, а то у меня ад выбора.
> даже без флагов оптимизации вызываемая функция будет писать в структуру на стеке
А ты и рад.
Шта?
Анонасы, кто умеет в OpenMP, нужна ваша помощь. Можно ли каким-то образом "открепить" паралельную секцию от основного потока и, не дожидаясь её завершения, продолжить выполнение дальше?
Open-Source Software
Очевидный cppcheck же, не? С ключами по типу
> --enable=warning,style,performance,portability
Единственное - не совсем очевидно отключаются предупреждения там, где он выдаёт ложное срабатывание.
Сама суть задания, с помощью структуры найди самую старую книгу и сколько книг из области физики
Ошибку нашел, там изи, ответ в личку отправил
Почему нет - используй на здоровье.
Но есть одно "но", а именно - выравнивание.
> struct s {
> uint8_t a;
> uint32_t b;
> };
Занимает в памяти не 5 байт, а 8. Это происходит из-за того, что процессор умеет обращаться к переменной b только если её адрес можно поделить на 4. В связи с этим после переменной a компилятор тебе добавит три байта, которые не будут использоваться в принципе. Ты можешь легко проверить это в духе:
> printf("%lu\n", sizeof(struct s));
Примечание: x86 может работать с невыровненными данными, но медленнее, из-за чего по умолчанию выравнивание всё равно применяется. А другие архитектуры могут тебя с такими запросами вообще напрямую послать, выдав address error и отказавшись работать.
>>036887
> if (p.obl == 'Физика')
if (!strcmp(p.obl, 'Физика'))
>>036946 (Del)
Катись к хуям.
> Примечание: x86 может работать с невыровненными данными, но медленнее, из-за чего по умолчанию выравнивание всё равно применяется.
Разница в бенчах на x86 была почти незаметна, а сейчас и вовсе сошла на нет:
https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/
Про armv8a тоже пишут, что в большинстве случаев разницы нет:
https://www.nxp.com/docs/en/application-note/AN12628.pdf
Кроме поддержки simd смысла выравнивать уже как-то и нет.
В структурах (если экономишь память) - да. Если хочешь переполнение по модулю 2n- тоже можно. В остальных случаях нарвешься на сравнение знакового с беззнаковым или внезапно неэффективный код.
Сап сисеры. На связи бумерок, надрачивающий на олдфажные игори. Занимаюсь моддингом Return to castle Wolfenstein. Столкнулся с тем, что на современных компах игра вылетает частенько в процессе загрузки миссии из сохранения (если загрузка происходила во время игры). Отловил в Оле. Пишет якобы access violation. Но схуяли там пустая переменная, если в норме этот код постоянно работает? Предполагаю, что это связано с тем, что в ходе завершения миссии игры из памяти выгружается много переменных, а из-за криворукости кодеров, какой-то параллельный поток на быстрых компах успевает снова попытаться прочитать уже выгруженную переменную.
Исходник есть. Место локализовано. Строка 84. Чтение одной из этих переменных во время выгрузки миссии приводит к крашу.
Вопрос собсно такой: как это лучше всего пофиксить? Не хочется отрубать функцию полностью. Как программно предотвратить access violation на уровне сишного кода? Есть ли аналог try-catch? Или не поможет????
вдогонку
ну по честному, наверное, стоит добавить семафорчик, если ты правильно описываешь ситуацию, заблокироваться перед чтением, пока не подгрузится корректный объект.
Ну чего ты обзываешься-то сразу? Ну не знаю я толком С. А за совет спасибо
Тип короче надо нормально пгавить, почему не написать автору подробный bug report?
Ну кстати, gentity не равно 0. Придется включить мозг и смотреть, кто выставляет gentity, а потом освобождает память.
А вообще мне вот от чего бомбит. Там выше по коду на 77 идёт чтение точно тех же самых переменных и почему-то они не вылетают. Как это возможно???
А блядь нет, извините, понял. Та проверка сразу не прошла по первому условию
> Разница в бенчах на x86 была почти незаметна, а сейчас и вовсе сошла на нет
О как.
Значит, мои данные слегка устарели.
Впрочем, тест по ссылке производился на локализованных данных.
Невыровненное слово может всё равно попасть на границу двух кэш-линий, и тут уж как ни крути, а придётся грузить две линии вместо одной.
Но это уже такое. Больше теоретическое, нежели практическое.
>>037381
Дело не в многопоточности, как я понимаю.
Шанс того, что в условии
> if (g && g->something)
произойдёт переключение потоков сразу после проверки g, но перед g->something, ничтожно мал, никак не "частенько". И действительно, глянь в отладчике, у тебя там [EAX+248], но при этом в EAX лежит нифига не ноль.
Вероятно, в client->gentity лежит какой-то мусор.
Я бы проверил, инициализировано ли это поле, и не испорчено ли оно где-нибудь.
Мне конечно стыдно спрашивать, но как проверить инициализированность поля не читая его???
Ты должен смотреть, чтобы у тебя неинициализированных полей в программе вообще не было.
Но, как мне кажется, у тебя дело в том, что где-то gentity портится. Может быть, в другом потоке, или в твоём же.
Либо память, на которую ссылается gentity, была уже где-то освобождена, но в NULL поле gentity после free() установлено не было.
Блин. Ну правда, я не знаю как это делать безопасно, я никогда не кодил на чистом С.
Вот там есть несколько подполей.
gentity
gentity->r
gentity->r.svFlags
Как последовательно каждое из них проверить на инициализированность без риска получить вылет????
Ты фигнёй маешься, бро.
>как проверить инициализированность
В общем случае на твой вопрос ответ - никак, если речь про указатели, то обычно проверка против 0. Пиши отчёт автору, ну или кинь ссылку на исходники, у тебя там выше анон правильно сказал, что некий use after free (судя по виндовому сообщению) как минимум.
Ты с ума сошёл? Это компьютерная игра. Там десятки тысяч строк. client это указатель на протагониста, а gentity - на его состояние. gentity меняет чуть ли не каждая воида во всех проектах.
>>037731
>кинь ссылку на исходники
лови
https://github.com/id-Software/RTCW-SP
Почитал немного есходнегов, там вообще global entities статическое хранилище, проверь, что указатель client живой, отпиши и дальше подумаем.
Ну тип сделай лоад по этому адресу, посмотри будут ли пинки от ос, заодно, да, проверь чё там по значению.
Я не обсирал. Оно само стало обсираться. Вообще-то я там итак нихуёвый баг изначальных разрабов в своё время пофиксил
Я ещё завтра на более свежую голову гляну, если не отпишу - ничего не нашёл. А так, пиши в спортлото автору.
Надеюсь на тебя хуле. Потому что в Id Software мне скорее всего у виска покрутят.
далее буду учить стартовый буткод распозновать сигнатуру лини и попробую загрузить бут ядра.
асло если кому-то понадобится - http://www.ctyme.com/rbrown.htm (тут всё "апи" бивуса).
Как починил? Я выше дропнул смотреть, когда увидел, что там код виртуальной машины, возможно, ебашит не туда.
Это функция отправки сообщений клиентам сервера. Смысл проверки (gentity->r.svFlags & SVF_CASTAI) в том, чтобы выяснить, является ли данный клиент ботом. Потому что ботам отправлять сообщения не нужно, и поэтому нужно сделать continue. Но у нас сингл-плеер игра, т.е. на сервере могут быть либо боты, либо протагонист. Я нашёл, что отличить игрока от бота можно ещё одни способом. В структуре gentity есть поле name в котором хранится имя клиента и оно всегда инициализировано. Я сделал проверку, что если gentity->name равно WolfPlayer (так сервер называет протагониста), то вот эту ёбаную проверку на вылетающем r.svFlags я перепрыгиваю.
Тоже вкатываюсь в осдев, сделал вывод для себя что асм в пользовательском пространстве даже рядом не стоял с асм в режиме ядра. Если будут какие успехи пиши тут, интересно понаблюдать до чего дойдешь, а лучше линк на гитхаб с своим загрузчиком скинь
Си живее всех. Это скорее русскоязычное сообщество мертво. Это и не удивительно, что с такой культурой дискуссии все давно разбежались по англоязычным платформам. Зашёл тут на /pr/ со скуки, а тут Си-тред валяется в самом конце, при этом в топе JS, бугурт-тред и чьё-то нытьё. Позорище.
А я помню времена, когда тут постоянно апался ассемблер-тред.
Мда, доска реально выродилась, причем за последний год.
>А я помню времена, когда тут постоянно апался ассемблер-тред.
Он был довольно активным, просто в бамплимите.
А ты точно тредом не ошибся? Поверхностно, слегка устарело, но лучше, чем ничего.
Но не старая ли она в 2021? Например пикрил, сейчас же пишут int main(), да и компилятор ошибку выдавал когда я без инта вводил. И таких примеров я заметил несколько за первые 100 страниц.
Мнение тредика какое? Мб стоит схавать для начала пикрил 2? >C Programming: A Modern Approach
Это старый стандарт, там int считался дефолтным, поэтому его можно было не писать. Если очень надо, то посмотри доки к компилятору, там должно быть написано про включение поддержки старых стандартов.
>Но не старая ли она в 2021?
Сам язык в 2021 году старый.
>Сам язык в 2021 году старый.
Ну хз. Всяко отличный для вката. Ассемблер я уже чуть познал, так что си кажется раем.
Мой вопрос был про актуальность книги и ты на него ответил, так что спасибо и удачи. Я мухожук
А нет, оказывается во втором издании ничего не поправили, почему-то думал что там все нормально
По С кстати есть годный короткий плейлист от Хирьянова https://www.youtube.com/playlist?list=PLRDzFCPr95fLjzcv6nNdjMu_9RcZgIM9U, тут не только сам Си но и смежные к нему области вроде алгоритмов, теории компиляции рассматривают
main(argc, argv)
char *argv[];
{...}
Что это за хуйня ?
Реализация функции по старому стандарту языка
Загугли и почитай
Да, я его тоже смотрю. Спасибо тебе!
>сделал вывод для себя что асм в пользовательском пространстве даже рядом не стоял с асм в режиме ядра.
Ну я пока только пару строк вывел; и с текстовыми и графическими модами немного поигрался. А разницу лишь в сегментной модели реального мода увидел, ну и вместо сисколлов - слой биоса.
>Если будут какие успехи пиши тут, интересно понаблюдать до чего дойдешь,
Я напоролся на архитектурную диллему в чейн-лодинге, сродни про яицо и курицу.
В некоторый момент неизбежно потребуется загрузить второй стейдж (очевидно чем раньше - тем лучше).
Вопрос, где хранить второй стейдж? На одном из разделов - плохая идея, так как инсталяция загрузчика потребует запиливание нового раздела, что не есть адекватно хотя вроде загрузчик NT так делает.
В /бут/ ? Тогда потребуется вскрыть файловую систему на разделе, загрузить соответствующие дровишки (опять же, откуда?) и уже через них искать бинарь со вторым стейджем; причем все эти действия могут и не уместиться в 446 байт.
Есть правда такая штука, VBR (volume boot record), то же что MBR только на разделе, а не на диске. В ней же инфа о файловый системе. Можно делать следующим образом:
1. смотрим следующий раздел
2 если он активен, тупа (как БИОС) грузим его VBR в другую локацию и передаем контроль туда
3 смотрим файловую систему
4 смотрим 2stage грузим его и благополучно передаем контроль
Если что-то не так - откатываемся к п.1 (т.е. возврат к 1 стейджу)
Но во-первых согласно osdev, VBR "не совсем стандартен".
И во-вторых, прописаться в этот верхний кусок раздела во время инсталяции возможно тоже не самая адекватная идея.
Одним словом подсказки бы не помешали.
>>050336
>Через APM небось?
Через ACPI. А если честно, то нужный int на стэк-оверфлоу нашел и просто копировал наудачу. Асло где-то слышал, что ACPI - точное надмножество над APM.
>сделал вывод для себя что асм в пользовательском пространстве даже рядом не стоял с асм в режиме ядра.
Ну я пока только пару строк вывел; и с текстовыми и графическими модами немного поигрался. А разницу лишь в сегментной модели реального мода увидел, ну и вместо сисколлов - слой биоса.
>Если будут какие успехи пиши тут, интересно понаблюдать до чего дойдешь,
Я напоролся на архитектурную диллему в чейн-лодинге, сродни про яицо и курицу.
В некоторый момент неизбежно потребуется загрузить второй стейдж (очевидно чем раньше - тем лучше).
Вопрос, где хранить второй стейдж? На одном из разделов - плохая идея, так как инсталяция загрузчика потребует запиливание нового раздела, что не есть адекватно хотя вроде загрузчик NT так делает.
В /бут/ ? Тогда потребуется вскрыть файловую систему на разделе, загрузить соответствующие дровишки (опять же, откуда?) и уже через них искать бинарь со вторым стейджем; причем все эти действия могут и не уместиться в 446 байт.
Есть правда такая штука, VBR (volume boot record), то же что MBR только на разделе, а не на диске. В ней же инфа о файловый системе. Можно делать следующим образом:
1. смотрим следующий раздел
2 если он активен, тупа (как БИОС) грузим его VBR в другую локацию и передаем контроль туда
3 смотрим файловую систему
4 смотрим 2stage грузим его и благополучно передаем контроль
Если что-то не так - откатываемся к п.1 (т.е. возврат к 1 стейджу)
Но во-первых согласно osdev, VBR "не совсем стандартен".
И во-вторых, прописаться в этот верхний кусок раздела во время инсталяции возможно тоже не самая адекватная идея.
Одним словом подсказки бы не помешали.
>>050336
>Через APM небось?
Через ACPI. А если честно, то нужный int на стэк-оверфлоу нашел и просто копировал наудачу. Асло где-то слышал, что ACPI - точное надмножество над APM.
Есть условие
if (click==3)
{
x=y+10
}
Как мне увеличивать значение х на 10 при каждом выполнении условия click=3? Обернуть это дело в цикл?
Новый стандарт Си не так чтобы очень сильно отличается от старого. Это же не плюсы, где наворотили кучу хипстерских приблуд.
В чём проблема помимо моей необучаемости? Как сделать, чтобы всё работало так, как я хочу? Нужно, чтобы внутри программы test существовал объект (или ссылка на него) foo_list из моей библиотеки без его явной декларации (чтоб красиво было), состояние которого можно было бы менять через соответствующие функции. У меня, насколько я понимаю, получается, что он где-то в загруженной в память библиотеке существует без возможности его изменения.
Я в C полный нуб, сильно палками не бейте.
Подскажите, каким образом можно на си+линукс реализовать такой обработчик сигналов извне (наподобие прерываний), который бы обрывался на следующем приходящем сигнале?
Я попробовал через signal(..) - получилось, что он ждёт полного выполнения кода обработчика, что неприемлемо. Однако выгружать программу нельзя - просядет производительность из-за сервисных издержек.
Мне нужно, чтобы клиент отправил всем строку, а сервер, прочитавший и понявший, что это к нему стучатся, начал общение.
Вот, но я не понимаю, как это широковещательное сообщение от клиента отправить.
Блин, может я чего-то недопонял.
Это за тебя уже придумали, отправляй на широковещательный адрес твоей сети, это самый последний адрес в сети, но он вычисляется в зависимости от маски. Проще воспользоваться сетевым калькулятором.
Например - https://ipcalc.co/ вставляешь какой-то адрес из твоей сети вместе с маской, в результате смотришь broadcast.
Если тебе нужно отправить в другую сеть, то там уже нужна маршрутизация, маршрут до другой сети прописывается на роутере.
Какой стандарт самый-самый?
Из-за компактности и совместимости.
Даже если не часто, а всего один раз и всего лишь на полшишечки — возвраты надо проверять у любой функции, которая может закончиться не очень успешно.
Старый то старый, но до сих пор активно используется минимум в паре сфер.
И, помимо этого, есть еще куча аматоров в Linux и MCU (настоящих MCU аматоров, не соевых письтеров пердуинщиков), которые этот самый язык юзают.
> А если честно, то нужный int на стэк-оверфлоу нашел
Значит через APM.
> ACPI - точное надмножество над APM
Никаким местом. Мало того, на новых компах, особенно ноутах, CSM в APM не умеет. Есть только APM installation check, который говорит, чтобы ты шел нахуй.
> 446 байт
У нас EFI давно, на разделе дохуя места под любой лоадер, который ты только можешь себе вообразить.
Плюсую тебя. Ещё добавлю, что половина софта в обычном дистрибутиве GNU/Linux точно написана на Си. И разные *bsd системы тоже сюда же.
И эти вещи кто-то поддерживает, и софтины по типу mesa, wine, которые цветут и развиваются. А значит и какой-никакой спрос на толковых разработчиков на Си будет.
https://habr.com/ru/company/skillfactory/blog/531360/
Я конечно понимаю, по сравнению с убогим C++ сишка ахуенна да и вообще низкоуровневый язык.
Как у вас тут дела, что программируете, работаете ли?
Одно огорчает, что в вакансиях обязательно всякий мусор, как вышка и знания ОПП(его вообще кто-то не знает?). Зато все такие тру программисты. Выделяете память, следите за ядром линукса, работаете с системной поебенью и костылями.
Мимо зашел студент год назад бросил c++, начал учить джаву
>Как у вас тут дела, что программируете, работаете ли?
Переписываю сейчас один микросервис с питона на Сишечку. Вообще-то кабанчик хотел С++, но я ему по красоте пояснил, что плюсы там как собаке пятая нога.
- Поступает информация потоком (с файла или с клавиатуры).
- Из этой информации нужно извлечь только double, а прочий мусор игнорировать
- Триггер прекращения чтения: EOF или последовательность символов "end"
Как реализовать это более элегантно?
Вроде бы ничего сложного, можно читать даблы с помощью fscanf'a, но всё портит "end" который нужно детектить чтобы прекратить чтение
как?
мб read()?
Понравилась мне идея подучить си, балуясь с железками, а то просто так неинтересно после высокоуровневых языков.
Там тип рекомендует девборды от каких-то американских хипсторов, но они за любую хуйню дерут втридорога. Я посмотрел на али, там полно копеечных штук и досыпают ведро всяких проводков, лампочек и датчиков заодно.
Но хуй знает, что конкретно брать. Есть у кого опыт?
Если речь идёт именно про элегантность, то подобные вещи лучше всего решаются при помощи конечного автомата.
Погугли, что такое конечный автомат и как он работает.
Это прямо то, что тебе нужно.
Разумеется, реализация КА довольно массивная, и если тебе это нужно на один раз, то проще и впрямь через fgetc() сделать и пару костылей.
А если у тебя такие задачи возникают постоянно, подумай о том, чтобы подключить библиотеку регулярных выражений.
Но самое элегантное решение, на мой взгляд - это конечный автомат.
Там и этих оригинальных ардуино дохуя на разных архитектурах, а клонов в сто раз больше. Как выбрать?
Я бы предложил построчно читать и парсить строки (fgets). Проверяешь (switch) на 'e' -> проверяешь (strncmp) на "end"; проверяешь на цифру, плюс, минус, точку -> делаешь strtod, он либо вернется с ошибкой, либо даст новый указатель; если что-то сфэйлилось, инкрементишь указатель. Будет одновременно читабельно и не слишком медленно.
>>072134
На девборде уже все распаяно, отлажено и документировано. Периферия именно та, с которой ты захочешь поиграться (экранчики, тачи, кнопочки-крутилки и светодиоды, само собой). У китайцев нормальных отладок с периферией нет, будешь собирать на dupont-кабелях с бредбордой и гадать, почему у тебя не заводится - то ли контакт плохой, то ли модуль тебе дохлый прислали, то ли подключил не туда или не так (нужен какой-нибудь подтягивающий резистор, а ты проглядел), то ли дело все же в коде. На первых порах такое часто встречается. В первом варианте ты получаешь удовольствие, во втором - опыт.
>>072649
А что в книжке советуют? Вот подобное и ищи.
Допустим есть вызов макроса
M(1,5);
Можно ли
#define ARG 1,5
M(ARG)
Или каким то другим образом замакрить пару параметров.
Хорошо бы это паре одно имя.
Да нет, решение уже принято. Все корпорации активно начали топить против Си. К 2025 Си станет нишевым языком для энтузиастов, а к 2030 отомрет вовсе.
Goвнарь незаметен
Можно, разрешаю.
>>073935
> К 2025 Си станет нишевым языком для энтузиастов, а к 2030 отомрет вовсе.
Да он прав тащемта. Си никогда не был хорошим языком, а сейчас он к тому же устарел и плохо подходит для современной разработки. Даже на микроконтроллерах его активно вытесняют. Исправить Си нельзя, не сломав совместимость, без совместимости он нахуй никому не нужен. Но к обеим датам лет десять я бы смело прибавил.
>Си никогда не был хорошим языком, а сейчас он к тому же устарел и плохо подходит для современной разработки.
А что тогда хороший язык для этих целей? Я думаю, что Сишка даже условный раст переживет, который через пару лет на мусорку отправится.
>Даже на микроконтроллерах его активно вытесняют.
Это чем же? Питоном, жабаскриптом, растом? не смеши пожалуйста.
> Питоном, жабаскриптом, растом
Да, да и да луа забыл, лол. А главным образом крестами.
> Сишка даже условный раст переживет, который через пару лет на мусорку отправится
Вот это как раз очень возможно. Хотя про пару лет ты загнул.
> А что тогда хороший язык для этих целей?
Это такой, в котором чуть меньше UB, чуть больше неймспейсов и есть что-то хотя бы чуть-чуть получше _Generic. Ах да, и в который настоящий const завезли, а не вот это самое.
По этой логике отомрут компьютеры, останутся веб-страницы в проприетарных корпоративных сетевых терминалах это такие мониторы с кклавиатурами, подключенные удаленно к мейнфрейму в датацентре. Только Си тут ни при чем.
В /ra/ есть тред по ардуинам. Попробуй там спросить.
Есть функция, внутри которой создаётся определённой длины массив структур.
shape shapes[10]
И после заполняется данными.
Внутри функции все данные заполнены корректно, и всё отображается как надо.
Мне нужно вернуть этот массив, но когда я возвращаю указатель массива return shapes*. Если попытаться обратиться к любому полю любого кроме первого элемента массива - то там какая-то нёх (мусор в памяти)
Вопрос: как мне правильно вернуть массив?
Вопрос отменяется, я просто сделал массив в глобальной области
>disk space: OK
>disk space: 16K
Апхахпха, проигрямсь
Спасибо, заработало.
Пацаны а шо будет в возвращаемом значении, если скастить void функцию к int?
наверное по конвенции будет то, что завалялось в контрольном регистре. а скорее всего ещё на конпеляции транслятор в ебло харкнет за такие дела
Ато есть подобное типа write(1, &n, 1) что это значит и можно ли пропускать параметры?
Ну и как они его используют, он же пустой
include/linux/types.h
> Ну и как они его используют
Точно так же, как в крестах, только вместо наследования - композиция:
struct myobject {
struct list_head list_of_something;
int mydata;
}
И сразу гугли CONTAINING_RECORD, чтобы понять, как из list_head сделать myobject.
void UART(void)
{
X_sample = (int) ReadFromRXBufFL(RXBufAddrParsing+14);
Max_sample= (int) ReadFromRXBufFL(RXBufAddrParsing+18);
}
Которая принимает данные из буфера.
В заголовочном файле UART.h она указана как
void UART (void);
Как мне в файле programm.c заполучить содержимое переменных X_sample и Max_sample
при выполнении цикла for(i=0;i<10;i++). Я объявлял переменные extern'ом в заголовочном файле programm.h, но данные из этих переменных приходят одни и те же.
> ReadFromRXBufFL
Моя карманная ванга намекает, что данные ты либо не получаешь вообще, либо этот буфер надо poll-ить. В любом случае надо знать, что за МК, что за либа, как она работает.
LPC 2138, uart написан каким-то васяном и он работает, когда надо получить одно значение, в program.c я делаю вещь типа tempX=X_sample (X_sample - глобальная переменная, объявлена как extern в program.h, но как только я оборачиваю это дело в цикл, то весь цикл пишется одно и то же значение X_sample. В связи с этим и возник вопрос, насколько я всё делаю неправильно.
Не уверен что тебя понял, но:
>объявлена как extern в program.h
volatile не забыл? Либо компилируй с -O0.
>весь цикл пишется одно и то же значение
Если в цикле нет значительной задержки, то все логично. По UART данные приходят сравнительно медленно.
из за переносимости?
Не договорились, что возвращать для терминала.
Смотрел на код представленный тут:
https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/olcPixelGameEngine.h
Прикол этого движка в том, что можно выставлять значения толщины и высоты пикселей, что используется при ретро гейминге.
В частности, в этой строчке:
Construct(int32_t screen_w, int32_t screen_h, int32_t pixel_w, int32_t pixel_h, bool full_screen = false, bool vsync = false, bool cohesion = false);
Как я не пытался, не смог найти связь между этими значениями и вызываемой WinAPI (или OpenGL?) функцией для "зернистости" физических пикселей.
Гугление pixel scaling, pixel resolution, pixel ratio, custom pixel size ничего не дало. Использование brush и pen не помогает, так как в вышеприведенном файле во-первых они не используются, а во-вторых не позволяют установить неквадратные пиксели.
Помоги пожалуйста.
Спасибо.
Бляя, ну понятно же что речь идет о низкоуровневых вызовах, какая разница как вызывается конструктор класса?
Я, например, понятия не имею, где искать низкоуровневые вызовы из конструктора класса. В С, я бы увидел объявление Construct() в .h файле, открыл .c файл, и прочитал бы определение, и там были бы все вызовы. В каком .cpp это искать здесь?
А кто тогда долже определения функциям давать? В этом единственном .h файле только объявление. Я так понял, что это я не смог найти определения для Construct(), а ты утверждаешь, что его вообще нет?
Блядь, просто не пиши, если не можешь понять простой абзац на русском языке. Мигрант ебучий.
Здорово. Определение-то где? Оно же не макросом генерируется, чтобы это header-only library была.
Ок, закину в C++ тредю.
>>084197
Пиздец - это тред Си или аутистов?
>>Оно же не макросом генерируется, чтобы это header-only library была.
Что ты такое и что ты блядь такое несешь?
>>083995
>В этом единственном .h файле только объявление.
Иди книжку по си почитай чтоли?
в h может быть что угодно - хоть поэма Пушкина в строках. Уж сишнику не знать про компиляцию кода, это конечно пиздец полный
А, я обосрался, искал с пробелом в начале, а там "::".
Кароче есть старая карта 7 серии нвидиа и так получилось что её нужно воткнуть в систему с 10 виндой. Дрова под карту есть только для 8.1 винды. Собственно что делать? Почитал что можно конвертировать проект для 8.1 до 10 винды автоматически, но для этого ведь исходники нужны, а нвидиа проприетарные. В общем есть какие-нибудь предложения у анона?
ну ты и лалка
на линух есть дрова? их конвертировать может?
https://github.com/engineer-man/youtube/tree/master/062
$ sudo make
Получаю:
make -C /lib/modules/5.12.14-arch1-1/build M= modules
make[1]: Entering directory '/usr/lib/modules/5.12.14-arch1-1/build'
scripts/Makefile.build:43: arch/x86/entry/syscalls/Makefile: No such file or directory
make[2]: No rule to make target 'arch/x86/entry/syscalls/Makefile'. Stop.
make[1]: [arch/x86/Makefile:223: archheaders] Error 2
make[1]: Leaving directory '/usr/lib/modules/5.12.14-arch1-1/build'
make: * [Makefile:4: all] Error 2
Алсо, пикрил (проверил в /usr/include/linux, файла там и правда нет), но пакет с заголовками накачен:
$ sudo pacman -Qe linux-headers
linux-headers 5.12.14.arch1-1
ЧЯДНТ?
что это за ошибка? void create нормально создает матрицу и выводит её, а void print выдает эту ошибку
Если код void print'a засунуть в void create, то всё выводится и параметр x виден
В main'е тоже код print'a выдает ту же ошибку
Ошибка работы с памятью.
Если быть точнее - ты передаешь int ××a в функцию аргументом, как int ××x, по сути ты NULL копируешь в функцию, и там его уже в стек фрейме заменяешь, не меняя значение самой ××a.
Тебе надо в create передавать тройной указатель и a передавать как &a в него.
>ls -l /usr/lib/modules/`uname -r`/build/include/linux/init.h
Так, вот здесь имеется, значит. Тогда получается всё правильно. И как тогда заставить его работать?
Или не правильно. Он вообще должен быть там, или это на арче навасянили так?
Сори, не могу понять:
Изначальный вариант
https://pastebin.com/bdvTU1Dq
Попытка исправления
https://pastebin.com/QpgvM1bb
Надо либо так:
https://ideone.com/NId5CR
Либо сделать правильно и адекватно:
https://ideone.com/HYOK3y
(Просто возвращать из функции создания int××)
Спасибо.
ГЦЦ пишет, что LLONG_MAX udneclared. Хотя limits.h подключен, в самом хидере этот макрос тоже есть.
Не стандартных хидеров неподключено. Пробовал включать limits.h последним, тот же результат (хотя было бы странным, если какие-то другие хидеры раздефайнили).
Также если поставить другой лимит, например LONG_MAX, то всё работает.
>signed long long int
>Specified since the C99 version of the standard
Грустно, что сказать. Странно, что с -std=c89 гцц даже не ругнулся на этот тип
> И как тогда заставить его работать?
Обеcсудь. sudo убери, нахуй тебе sudo для сборки? Да, просто make.
И еще скажи, что у ты любишь мозоли: MODULE_LICENSE("gpl"); куда-нибудь в конец rickroll.c.
>с -std=c89 гцц даже не ругнулся на этот тип
Потому что что указание стандарта не для ругательства? Для ругательства -pedantic
https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
Разобрался с этой проблемой, оказывается, что предыдущие данные сдвигаются в области памяти из-за чего я подумал, что они потерялись.
Не знаю зачем, но интересно
> Что он может сломать
Мозг читающего код. С указателем видно сразу, указатель ли он, или вот объект лежит туточки. Со ссылкой - нет.
На чем вы бля дебажите в 2021? Это же пиздец, нужно посмотреть память и стеки вызовов, накатил Visula Code, какое то говно для пориджей нихуя не показывает, стер. Накатил Code::Blocks это говно сыпет программные ошибки. Vusula Sdudio этого ебаного монстра даже ставить не буду. Остался Eclips он точно работал...
>От книжек в пользу фильмов уже отказался?
Поридж, твои Трансформеры и Супермены никому не интересны.
>Остался Eclips он точно работал
Eclips как всегда топчик, остальное идеобразное говно для пидоровпориджей.
QtCreator еще оказывается С проекты поддерживает
Ого а как регистры смотреть в студии? У меня чё-то пишет Нет данных если зайти в отладка окно регистры
>в студии
А студия то при чем? Хотя раньше в Вижуалстудии с майкрософтовским конпелятором все отображалось.
char ()(int) a[10];
Даже так, чтобы убрать любые неоднозначности
(char ()(int)) a[10];
Почему, блять, во всех остальных ситуациях, я слева пишу тип, потому пишу имя переменной и в квадратных скобках размер массива, а тут так не могу? Ебаный в рот. Указатель на функцию, возвращающую чар и принимающую инт - ЭТО И ЕСТЬ ТИП, БЛЯТЬ. Почему он должен подчиняться иному синтаксису?!
Сделай тайпдеф и пиши нормально.
> когда придумывали синтаксис объявлений указателей на функции
Никто ничего не придумывал специально. Объявление отражает использование.
> я слева пишу тип, потому пишу имя переменной и в квадратных скобках размер массива, а тут так не могу
Ты неправильно об этом думаешь. Например, у тебя есть char ∗abc[10] (десять указателей на char): ты берешь имя переменной abc, индексируешь его квадратными скобками abc[10], дереференсишь указатель ∗abc[10] или с явными скобками ∗(abc[10]), получаешь char. Да, я знаю, что 10 за пределами массива, суть не в этом.
То же самое с функциями: берешь имя abc, индексируешь abc[10], дереференсишь указатель ∗abc[10] или ∗(abc[10]), получаешь функцию, вызываешь (∗abc[10])(int), возвращается char. Полная декларация: char (∗abc[10])(int) или с избыточными скобками, более явно показывающими последовательность действий: char (∗(abc[10]))(int). Дереференс ∗abc[10] приходится класть в скобки из-за приоритетов операторов, чтобы char не отожрал звездочку себе: иначе получится массив из 10 функций, возвращающих char ∗, но массив функций (а не указателей на них) в сишке сделать нельзя по определению, и компилятор пошлет тебя нахуй.
Алсо, двачую тайпдефы. Если тайпдефать не указатель на функцию, а сам тип функции, то даже скобки не нужны, и все получается максимально читаемым, точно таким же, как и для объявлений данных. Тот же самый процесс, что и выше, но два шага:
typedef char MyFuncType(int);
MyFuncType *xyz[10];
Когда отдереференсим xyz по полной, получаем значение типа "функция принимающая int, возвращающая char", ее и вызываем. И вот только здесь могут возникнуть сишкопроблемы и некоторое недопонимание: вызовы (∗xyz[n])(k) и его аналог с избыточными скобками (∗(xyz[n]))(k) абсолютно очевидны, но xyz[n](k) и (xyz[n])(k) работают ничуть не хуже. И это последствия неявного каста объекта типа "функция" к указателю на него и того, что оператор вызова функций () работает именно с указателями на функции. К сожалению, это правило работает в выражениях, но не работает в декларациях, поэтому MyFuncType xyz[10], как я уже говорил выше, написать нельзя.
> когда придумывали синтаксис объявлений указателей на функции
Никто ничего не придумывал специально. Объявление отражает использование.
> я слева пишу тип, потому пишу имя переменной и в квадратных скобках размер массива, а тут так не могу
Ты неправильно об этом думаешь. Например, у тебя есть char ∗abc[10] (десять указателей на char): ты берешь имя переменной abc, индексируешь его квадратными скобками abc[10], дереференсишь указатель ∗abc[10] или с явными скобками ∗(abc[10]), получаешь char. Да, я знаю, что 10 за пределами массива, суть не в этом.
То же самое с функциями: берешь имя abc, индексируешь abc[10], дереференсишь указатель ∗abc[10] или ∗(abc[10]), получаешь функцию, вызываешь (∗abc[10])(int), возвращается char. Полная декларация: char (∗abc[10])(int) или с избыточными скобками, более явно показывающими последовательность действий: char (∗(abc[10]))(int). Дереференс ∗abc[10] приходится класть в скобки из-за приоритетов операторов, чтобы char не отожрал звездочку себе: иначе получится массив из 10 функций, возвращающих char ∗, но массив функций (а не указателей на них) в сишке сделать нельзя по определению, и компилятор пошлет тебя нахуй.
Алсо, двачую тайпдефы. Если тайпдефать не указатель на функцию, а сам тип функции, то даже скобки не нужны, и все получается максимально читаемым, точно таким же, как и для объявлений данных. Тот же самый процесс, что и выше, но два шага:
typedef char MyFuncType(int);
MyFuncType *xyz[10];
Когда отдереференсим xyz по полной, получаем значение типа "функция принимающая int, возвращающая char", ее и вызываем. И вот только здесь могут возникнуть сишкопроблемы и некоторое недопонимание: вызовы (∗xyz[n])(k) и его аналог с избыточными скобками (∗(xyz[n]))(k) абсолютно очевидны, но xyz[n](k) и (xyz[n])(k) работают ничуть не хуже. И это последствия неявного каста объекта типа "функция" к указателю на него и того, что оператор вызова функций () работает именно с указателями на функции. К сожалению, это правило работает в выражениях, но не работает в декларациях, поэтому MyFuncType xyz[10], как я уже говорил выше, написать нельзя.
Да. ANSI (США) стандартизировали в 89, ISO (Европа) в 90.
Read 16: 0x7a 0x5 0x14 0x0 0x4 0x0 0x0 0x0 0x0 0x0 0x6d 0xfa 0xe1 0xf3 0x1e 0xc
Read 16: 0x7a 0x5 0x14 0x0 0x4 0x0 0x0 0x0 0x0 0x0 0x6d 0xfa 0xf3 0x0 0xc 0xff
Read 16: 0x7a 0x5 0x14 0x0 0x4 0x0 0x0 0x0 0x0 0x0 0x6d 0xfa 0x43 0x3b 0xbc 0xc4
Read 16: 0x7a 0x5 0x14 0x0 0x4 0x0 0x0 0x0 0x0 0x0 0x6d 0xfa 0x3b 0x0 0xc4 0xff
Могу ли я как-то из него извлечь 0xe1 0xf3 0x43 0x3b и объявить их переменной типа float?
Или делаешь через union, как человек, без UB:
union { uint8_t as_bytes[4]; float as_float } myvar;
Спасибо, получилось, упаковал в новый массив. Нужно ли мне под этот массив[512] делать malloc?
Все по офсету ноль. А type punning упоминается в примечании к C11 6.5.2.3.
Слышал что c99 сломан в сравнении с c89, а с11 исправил его, но никаких подробностей не было в источнике этого утверждения.
Шарящие, поясните что там к чему и как родилось такое утверждение?
Только не оспаривайте, блядь, это утверждение, я его не защищаю, мне просто интересно.
> Только не оспаривайте, блядь, это утверждение
Как же не оспаривать? В C11 не так много нового появилось, и ничего коренным образом не изменилось по сравнению с C99. Хуй знает, может быть, это про какие-то детали формулировок? Вот C17 тоже вышел без фич, просто всякие мелочи поправили. Стоит ли утверждать, что C11 тоже был сломан?
Короче там просто хуйню спороли и ничего не сломалось?
Нахуя пикрилейтеды делают? Сишка реально такая конченая, что приходится из макросов собирать не просто костыли, а шагоходы с креслом?
Во-первых, это Microsoft, у них отношения с Си всегда непросто складывались, несмотря даже на то, что ядро на Си написано. Они постоянно пытались что-нибудь хорошее выбросить или не поддерживать, а какое-нибудь свое говно наоборот притащить. Во-вторых, в семидесятых ни про какие аннотации не слышали. Тем более в языке, который недалеко от ассемблеров ушел. Так что да, приходится костылями, хотя нормальные люди пишут подобные проверки в теле функции в assert. Вместо in/out пишут const и иногда restrict, и в C2x атрибуты появятся, можно будет их использовать, если очень охота.
Чет проорал с этих _наи__МеноВаний_
> в C2x
Вот бы получить сахар из крестов, но без анальных ограничений...
Заебали пилить языки либо без производительности с зумерскими GC, либо ржавый кал с проверками всего что можно, не дающий раскрыться полёту фантазии.
>не дающий раскрыться полёту фантазии
Сырыми указателями и unsafe можешь отстрелить себе хоть 40 ног!
Он бы ещё стабильным был бы. Прямо сейчас 650 открытых багов. Писать что-то серьезнее калькулятора на нем невозможно, о чем в доке и пишут.
Мы все равно верим. Я вот джвадцать лет без преувеличений хотел comptime в сишке, и, наконец, оно есть хоть где-то.
Время от времени приложение написанное на gcc падает с ошибкой Segmentation fault (core dumped), гугл говорит что это из-за неправильной работы с памятью. Вопрос можно ли как-то совладать с этой ошибкой или нужно урезать размер буфера?
Не вижу проблемы в размере буфера, скорее ты где-то за его пределы ходишь. Кидай код, или сам осваивай валгринд.
У тебя offset не инициализируется никогда, а используется в куче мест. Мусор какой-нибудь прибавляется к индексу в массиве, и он улетает за груницы и в sigsegv.
Понял принял, а разве при создании переменной int offset; она не создается по умолчанию равной нулю?
Нет.
есть точно такие же спецификации, только для ext?
Точно таких же нет, есть спека в doc-формате, первым же результатом в гугеле по очевидному запросу.
>>094372
Извиняюсь, протупил. Есть статья про ext4: https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
Есть про ext2:
https://www.nongnu.org/ext2-doc/ext2.html
ext3 это просто ext2 + журнал, на него спеки в ext4
Предлагаю книжку для гуманитариев заменить на свежий "C for Dummies" за авторством Dan Gookin.
Открыл рандомное видео (v7OcOW7NrLs), тыкнул в рандомное место: sockaddr.sin_addr не присваивется вместо этого куча мемсетов везде, ну ладно INADDR_ANY как раз ноль, повезло; TCP, но код возврата send/recv не проверяется отправили 200 байт, ушло 100; буфер размером 200 символов распечатывается после recv без обработки, просто printf("%s\n") т.е., если отправить 200 символов без единого \0, получим выход за пределы буфера. И это только несколько секунд одного видео. Закрыл. Это точно-точно нужно в шапку?
В студии не работает просто так этот код. Надо пердолится
Кто-нить юзал/ет http://libcello.org/
вот случайно наткнулся, вроде прикольно, но там какой-то рантайм добавляют (по сути уже не си), курить дальше эту либу, или это шляпа какая-то?
блядь, этих ноунейм языков уже наплодилось
zig, odin, nim, beef, v, crystal ...
когда уже нормальное че появится не раст, как бы си люблю, но реально уже морально устарел. Да и виден запрос общества на модернизацию сишечки, раз столько япов развилось, которые до нормального продакшна все никак не дойдут
когда ты в 2000-х был мелкий, наверное с тамогочиком ходил, или лизуном-сасуном каким-нибудь.
ну это другое совсем, твое поколение явно умней было, а сейчас зумеры эти - дегенераты.
Мимо не зумер
Рот бы тебе мылом вымыл
Дваждую.
Сам считаю odin наиболее интересным из всего что ты перечислил, жаль наиболее хайповый из них zig.
Так то к сишке многого не нужно, нормальные дженерики и может еще несколько стандартных контейнерова и все впрочем, по желанию трейты добавить еще можно.
там в том-то и прикол что не надо там что-то супер новое.
даже синтаксис не надо менять
просто мб методы для структур как в го
интерфейсы как в го
дженерики
как-то продумать обработку ошибок
и инфраструктуру нормальную запилить, что-то типо cargo
ну и мб как-то отказаться от .h файлов
ну и неймспейсы тоже неплохо было бы, хотя не настаиваю
Crystal и Zig заслуживают ознакомления, но Crystal - это не про сишку.
>>095689
> и инфраструктуру нормальную запилить, что-то типо cargo
Это провоцирует лефтпады. Диды вон писали без карги, и нам она не нужна.
> как в го
Возьми го и пиши в го, как в го. Тут должна была быть шутка про продумывание обработки ошибок.
> не надо там что-то супер новое
Надо. Современное программирование сильно отличается от того, как писали раньше. Даже тупо железо отличается. А в сишке вон многопоточность только-только появилась.
> Возьми го и пиши в го, как в го.
не хочу го, пробовал - хуйня
> А в сишке вон многопоточность только-только появилась.
не понял прикола, ты про что?
системными вызовами создаешь свои потоки, что значит недавно в си появилось? если че - да, я нуб в си, чисто для души вкатываюсь
шаблоны, лямбды, корутины, модули, наймспейсы, скоро еще завезут pipeline-operator и pattern matching
все твои любимые сишные библиотеки работают без танцев с FFI
что еще нужно?
>скоро еще завезут pipeline-operator
Уже завезли в стандарт, а раньше можно было библиотеками подключать.
в расте тоже допизды всего, я же не дрочу на раст, хотя пытался
Ага, оно работало примерно как 1 << 31. Все знают, что получится, но у стандарта другое мнение. Та абстрактная машина, под которую пишется сишный код, ничего не знала о потоках. Соответственно, ни сам язык, ни стандартная библиотека ничего не гарантировали, были только местные фокусы, работавшие на честном слове.
так подожди, а что тогда поменялось?
> А в сишке вон многопоточность только-только появилась.
я не гуру, но знаю только pthread, если еще какие-то имплементации, есть даже кроссплатформенное решение какое-то.
А че у же в стандарт си завезли потоки?
> а что тогда поменялось?
Да ничего, в общем-то. Наука официально признала, разрешила и все такое. Атомики вот завезли наконец.
это норм что в h файле я определяю структуру, ну прям полностью, с полями?
просто иначе если я объявляю ее в h файле но определяю в .с, у меня сыпят ошибки разные типо storage size of ‘point’ isn’t known.
оно и понятно что файл видит только то что в хедер файле.
Но раве в хедер файле что-то определяют?
надо и плюсы еще поднимать
точнее даже можно хуй забить на си и учить только плюсы
С/С++ должен знать каждый
> это норм что в h файле я определяю структуру, ну прям полностью, с полями?
Это зависит. Вообще норм. Но есть способ скрыть реализацию, когда ты в .h говоришь:
struct yoba; // тайпдефы по вкусу
а в .c ты уже объясняешь, что:
struct yoba { int fileno; char ∗somename; };
И да, в этом случае тебе нужно будет сделать свой "конструктор", struct yoba ∗yoba_create(void), потому что код снаружи не будет знать ни размера, ни каких-либо других деталей о структуре, кроме того факта, что она такая есть. Класть ли структуру в .h как есть, или прятать детали - дело твое, зависит от того, где и как будет использоваться эта структура.
> Но раве в хедер файле что-то определяют?
Да. Даже код кладут, когда это inline-функции, например.
Тебе же написали: запускать сначала Developer Command Prompt от вижуал студии (консолька с выставленными переменными окружения), а потом из нее VS Code. Алсо, после этого ты можешь спиздить переменные окружения, и выставить их либо глобально, либо как-нибудь в этой вашей VS Code наверняка можно для билда указать.
Так я об этом и спрашиваю. Как починить чтобы не пердолиться через консольку каждый раз, это же пиздец какой-то. 2021-й на дворе.
Там переменных окружения столько, что ты охуеешь. Пару десятков. И все они с консольки этой выставляются пачкой bat-ников. Сука, ощутил на собственной шкуре за что индусов ненавидят.
Да. Мне совершенно не на чем проверить, но на самом деле нужно что-то вроде PATH/LIB/INCLUDE плюс VisualStudioVersion/VCINSTALLDIR, чтобы оно смогло задетектить наличие студии.
>Как починить чтобы не пердолиться через консольку каждый раз
Установить луникс и погромировать на нём, очевидно же!
Ты че, ебанутый. Там постоянно придется с консолькой пердолиться, каждый день, блджад, а я хочу жить активной и полноценной жизнью.
Если не хочется, можно ни разу после первой установки её не открыть. Зато вскод работает по ярлычку!
C gcc и шлангом он и под виндой так работает. Но я захотел полноценный IntelliSense с документацией и шлюхами и теперь страдаю.
>IntelliSense
Я так понимаю, он работает на линуксе? Вот статья
https://devblogs.microsoft.com/cppblog/improvements-to-accuracy-and-performance-of-linux-intellisense/
>статья
Или она про кросс компиляцию. Не хоче больше 5 слов за раз читать, поэтому не понятно.
Вот это, видимо, что локально работает
https://code.visualstudio.com/docs/cpp/cpp-ide
Вроде много всего. Достаточно?
Тому что так сложилось. Ты уверен, что тебе не хватает точности даблов? Ты уверен, что хочешь медленно считать 80 бит на FPU, а не 64 бита быстро на SSE?
Я хочу контроль. double когда нужна скорость и long double когда я сам решил, что мне нужна повышенная точность. Оправдания виндовому поведению просто нет. gcc в MinGW ведет себя правильно, но я боюсь что там в качестве workaround вообще программная реализация, а не просчет на FPU.
Если тебе не хватает аж 52 битов мантиссы для вычислений, то, вероятно, тебе стоит задуматься об использовании более устойчивого алгоритма.
Я уверен практически на 100%, что если ты пришёл с таким вопросом на сосач, значит, оно тебе на самом деле не нужно.
> Оправдания виндовому поведению просто нет
Оправдание есть: из существующего и распространенного железа только x87 из 1980 года умеет в хардварные 80 бит. Повторюсь, современный софт на x86 считает плавающую точку на SSE (даже если это обычные, не векторизованные вычисления), в x87 ходят только по большой нужде.
> боюсь что там в качестве workaround вообще программная реализация
Нет, там честные 80-битные даблы с выравниванием (лежат в 96-битных переменных), математика естественно на FPU, все ∗l() функции реализованы.
Алсо, я вот не понимаю, когда int и long int синонимы в 32-битном коде, тебе почему-то норм, а вот когда double и long double, так сразу оправданий нет.
Алсо, не сразу увидел и поэтому не сразу проиграл:
> double когда нужна скорость
Посоны-то не знают, не флоаты, ХАЛФ-флоаты используют (там, где завезли), а он даблы, скорость.
>Алсо, не сразу увидел и поэтому не сразу проиграл:
> double когда нужна скорость
>Посоны-то не знают, не флоаты, ХАЛФ-флоаты используют (там, где завезли), а он даблы, скорость.
Кек, теперь и я проиграл, тоже не сразу увидел.
Какого хуя ёбаный CMake, при сборке под MinGW Makefiles генерирует мне сука makefile в котором все пути указаны с \ а не с / (пикрил 1)? В итоге при попытке запустить этот makefile, вызываемый make'ом cmake эти слеши не правильно обрабатывает и удаляет их нахуй (пикрил 2).
Я просто не могу понять это я так обосрался или все эти системы сборок и системы сборок для систем сборок тупое ебаное костыльное кривое говно?
make из состава MinGW, CMake качал с оф. сайта.
Собираю libTMX библиотеку (https://github.com/baylej/tmx), всё это результат следующей команды https://pastebin.com/VjnpSREQ
Буквально вчера тоже с этим столкнулся. Нихуя не понимаю. И как под виндой библиотеки собирать?
>а я хочу найти работу в айти(
Проще и быстрее будет выучить JS за полгода и идти работать низкосортной макакой за копейки.
Ну а лучше подсуетись кабанчиком и устройся куда нибудь охранником или грузчиком, нервы сбережешь
К посту выше, после этого я понял что мне нужен допинг и нашёл кое какие ноотропы, заказал и в случае успеха отпишу тут через месяц
Я стану твоим конкурентом!
>Проще и быстрее будет выучить JS за полгода
Никак ты не научишься программировать быстрее от того что будешь учить синтаксис джаваскрипта вместо синтаксиса си — это просто так не работает. А то может быть и дольше будешь пердохаться с дохуя управляемыми языками, ведь там где си даёт понимание того, как работает компьютер, динамические языки заставляют ньюфага с собой работать как с чёрными ящиками разумеется компьютер тоже в какой-то степени чёрный ящик, но чем эта степень ниже тем лучше для обучения.
Дед, пей таблетки
Программирование это на 70% дизайн, и только на 10 попердольки (в среднем по индустрии но не суть). Научиться программированию можно только погружаюсь в проблематику домена. Чем ближе к юзкейсам и чем высокоуровневей — тем лучше.
>понимание того, как работает компьютер
Тут учиться надо, время тратить, мозги напрягать. Человеку вон, надо поскорее "вкотиться в ойти и рубить бабло", а ты ему про Си загоняешь
Да си как раз-таки довольно простая хуйня, как и ассемблер. А вот войти в айти с сей действительно не получится, особенно если нет опыта даже в сопутствующих областях
Это ты сначала сам
там в шелле винды есть модификатор который заставляет шелл воспринимать \ как /
вроде бы
не программировал 10 лет просто, все забыл уже,
Пол дня нахуй мучался, не понимая почему у меня undefined reference на функции из libxml2, а оказывается сука, вопреки законам логики, библиотеку вызывающую libxml2 надо ставить ДО линковки libxml2.
Какая же хуйня боже просто пиздец
А, хотя да, всё правильно ты предположил.
https://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking
>Note that after the linker has looked at a library, it won't look at it again. Even if it exports symbols that may be needed by some later library.
спс, братик
ответ очевиден - у меня НИХУЯ не получилось
я открыл Кернигана и Ричи, стал всё читать, пробовать, компилировать. и что вы думаете??? ХУЙ!!!! нихуя у меня не получилось
а я могу даже пояснить почему я не могу скодить ДА ПОТОМУ ЧТО Я НЕ ВИЖУ В ЭТОМ СМЫСЛА
делаем типа переменные lower upper obosrupper и типа хуярим переводчик из фарингейта в цельсий, НАХУЯ МНЕ ЭТИ ЦЕЛЬСИИ ЕСЛИ У МЕНЯ В ГУГЛЕ ЕСТЬ ПЕРЕВОДЧИК В ЛЮБУЮ ЗАЛУПУ БЛЯТЬ ГОТОВЫЙ
может я странный человек?? я не знаю. всем удачи с этим ёбаным си
> ЕСЛИ У МЕНЯ В ГУГЛЕ ЕСТЬ ПЕРЕВОДЧИК В ЛЮБУЮ ЗАЛУПУ БЛЯТЬ ГОТОВЫЙ
Я так понимаю си это твой первый язык? Потому что любые другие языки преподают на таких же простых и сто раз решённых примерах.
Andre Lamothe Tricks of the 3d Game Programming Gurus: Advanced 3d Graphics and Rasterization
Nvidia GPU Gems
Game Engine Architecture
Так надо с Праты начинать.
Да, ты очень странный человек
Это от того, что принципы, на которых построен Си, более или менее явно встречаются во всех промышленных языках. При этом, в отличие от Scheme и Smalltalk (принципы которых составляют >80% принципов "современных" интерпретируемых языков), он всегда был популярен в мейнстриме.
Под эмбеддед на асме пишут только уебки, школьники на ютубе "я так могу" и старперы, которые выучили в 90-х архитектуру какого-то 8-битного PIC и там застряли.
В эмбеддед давно царствуют плюсы или сишечка, но для особо упоротых оптимизаторов, если надо ебать много байтов и регистров с очень маленькой памятью.
Вот например int a = ananas;
Если разделение будет между командами то без проблем, а если я хочу разделить вот так:
int a = ana
nas;
или так:
in
t a = ananas;
Что за йоба символ использовать?
не работает
вот например https://www.youtube.com/watch?v=KJgsSFOSQv0 вроде норм объясняет последовательно и интересно. а Керниган и Ричи сразу начинают ебать мозг и приходится не обучаться, а посути догадываться. а после туториалов можно и книги почитать
Там где ты скинул воды ахуеть. Но! Если тебе норм, то конечно норм. Однако я бы охуел от такой подачи.
Тем более кресты лучше. На сишке тебе придется пердолиться в воид поинтеры, в крестах компилятор сможет сгенерировать оптимальный код под конкретный тип. В сишке ты притащишь виртуальные функции в виде указателей в структурках, в крестах компилятор тоже притащит, но там он их еще и девиртуализовывать умеет. И вот так вот все. Кресты всегда в состоянии обогнать сишку просто потому что у них выразительных возможностей больше, но поэтому же писать быстрый код на крестах гораздо сложнее, чем на сишке. Не умеешь - получишь тормоза, скатишься в необдуманные абстракции всего и вся - получишь тормоза.
Ты упускаешь что оптимизированный компилятором код игровых движков на крестах обычно производительней реализации на чистом C.
Посмотри даже какие-то бенчи языков программирования, кресты чаще всего впереди с реализацией того же алгоритма. Маргинально конечно, но все же. Учитывая это и более простую работу со структурами данных и ты прийдешь к выводу что без крестов никак.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/nbody.html
на прикриле массивы чаров не на стеке выделяются?
почему это работает?
мне надо освобождать память такую?
Литералы константные и лежат в секции данных (обычно). То есть, фактически твой код:
static const char anonymous_string[] = "hello world";
char *a = anonymous_string;
return a;
Потому и работает. Освобождать нужно только то, что ты выделял маллоком или то, что другие выделили и сказали, как освобождать (fopen/fclose и т. д.).
>На сишке тебе придется пердолиться в воид поинтеры
Не пердолься в воид поинтеры
>В сишке ты притащишь виртуальные функции в виде указателей в структурках
Не тащи виртуальные функции
>писать быстрый код на крестах гораздо сложнее
Именно.
>Ты упускаешь что оптимизированный компилятором код игровых движков на крестах обычно производительней
С чьих слов?
> не пердолься
qsort(), далеко ходить не надо. Сейчас ты скажешь реализовывать все стандартные алгоритмы, а для поддержки разных типов - копипастить, да?
> не тащи
А придется, потому что это единственный нормальный способ менять поведение в зависимости от типа объекта. Портянки из switch или ifelse ну никак не альтернатива.
>>108018
Кресты все равно будут протекать в твой мир, даже если тебя возьмут исключительно на сишку. Смирись и выучи хоть как-то.
>Сейчас ты скажешь реализовывать все стандартные алгоритмы
Нет, сейчас ты такой перечисляешь мне все стандартные алгоритмы с войд поинтерами. Про qsort все знают и он гуглится легко, а остальные приведёшь, раз уж
>реализовывать все стандартные алгоритмы
?
qsort скажу реализовать, но qsort это не все стандартные алгоритмы, это один стандартный алгоритм.
>а для поддержки разных типов - копипастить
Ну ты можешь копипастить конечно, если по-другому не умеешь, но обычно это делают с помощью макросов.
>>107809
Открыл ссылку. Исходники по ссылке для си и плюсов почти всюду разные, и чего они там по итогу сравнивают? Алсо, вот такого вот
> _mm256_setr_pd(...)
в геймдеве никто лепить не будет, лол (если ты, конечно, работаешь не на эпиков каких-нибудь, но тогда чего ты забыл на сосаче?).
>>107463
Не-а.
Сегодня геймдев - это хуяк-хуяк на юнити или чертежами на анриле и в продакшн, сражаться за каждый такт как в девяностых никто уже не будет.
По вопросу: уж игры и даже движки пишите на чём вам удобнее, хоть на руби. Машины у юзверей сегодня мощные, пережуют.
Если, конечно, ты не UE5 собираешься с нуля писать.
>По вопросу: уж игры и даже движки пишите на чём вам удобнее, хоть на руби. Машины у юзверей сегодня мощные, пережуют.
Ну знаешь ли. Я вот думаю дропну нахуй Outer Wilds, юнитипараша графона не содержит ноль целых хуй десятых, зато комп во время её работы протапливает хату будь здоров (когда на улице 41 особенно заебись).
Там вопрос был плана "что бы такого написать на си", а писать на си надо очевидно то, где сишка с лучшей стороны себя покажет. Игровой движок это как раз такая штука, но лишь одна из многих.
Игры целиком писать на си наверное всё же не стоит, как и на крестах кстати. Не сильно жрущую игровую логику лучше реализовывать на динамических языках имхо. Даже майнкрафт немного страдает от того что там моды на джаве, а это джава, это не кресты и даже не си.
Это-то как раз объективно понятные вещи.
Но тут просто проблема в том, что пока что ты будешь писать на си или плюсах, конкуренты уже давно выпустят свой говнокод на говноюнити и твой продукт никому нахуй будет не нужен. И плевать, что код на юнити превращает пекарню в обогреватель.
Сишка - это, увы, для многих сегодня забытые технологии предков.
Но не для меня.
Ну вот пока что выходит что мне как потребителю говнокод на юнити не нужен, по крайней мере пока я в Норвегию не перееду. Это вполне себе один из факторов, бьющих по продажам. Может я уникальная снежинка, но почему-то кажется что не я один сношу парашу, греющую квартиру. А игры крупных издателей почему-то часто нормально оптимизированы, значит на оптимизоний спрос есть, взгляни на рдр2, дум тот же. А там ведь ещё соснолечки, на которых без байтоебства вообще никак.
>Там вопрос был плана "что бы такого написать на си", а писать на си надо очевидно то, где сишка с лучшей стороны себя покажет. Игровой движок это как раз такая штука, но лишь одна из многих.
>Игры целиком писать на си наверное всё же не стоит, как и на крестах кстати. Не сильно жрущую игровую логику лучше реализовывать на динамических языках имхо.
Двачую, простой спрайтовый движок написать на C не так уж сложно, многие кстати пишут инди- разработчики своё, да просто потому что проще в итоге выходит и в поддержке, и фишки можно реализовать уникальные, и если ты делать будешь десяток игр то это просто выгодно. Инди кстати которые на своих движках, почему то почти все успешны и игры у них круче. Сам либу писал на С графическую 2д, просто летает на 1% загрузки процессора, вот думаю ещё простую аудио- либу приделать и скриптовый движок lua и будет игровой движок. Все студии нормальные имеют свой движок, а это что то да значит.
Про тот же СМаке, вот гуглю, но все для с++
вижу есть кто как в парашном камел кейсе пишут
кто-то в божественном снейк кейсе, вот я люблю в_снейке_писать.
мне руки не оторвут, если я на си буду тоже так делать?
я в свое время обблевался от ебаного голанга, потому что там на уровне синтаксиса публичные штуки надо с большой буквы писать
>а есть какой еще стайл гайд что-ли?
В каждом проекте свой, выбирай из них что считаешь нужным. Я например все переменные пишу слитно в нижнем регистре, а функции с _ ебой, имена структур с Большой буквы, ну и наименования без сокращений кроме счетчиков и индексов. А вот в крестах как раз КемелКейсом, там норм.
ох, наделали каждый свое, в этом и проблема си, нет единой инфраструктуры
autotools cmake meson scons
Но лучше использовать IDE
Не говори, ещё языков программирования наделали, текстовых редакторов, браузеров, операционных систем, вообще суки как их земля носит
Это тебе.
Недавно вон в /v/ был бугурт про пикрелейтед.
8 гигабайт ОЗУ для вот этого вот, тогда как у сеги было 64 килобайта на борту.
Но всё равно сожрут ведь, куда они денутся-то.
> а остальные приведёшь, раз уж
bsearch и qsort - это единственное, что есть в стандартной библиотеке, так уж получилось. Это еще одна проблема Си - нужно переизобретать мир, даже примитивный динамический массив заново писать, тогда как в крестах все из коробки. Но не суть. Обе функции с воид поинтерами. Но остальное реализуется так же, любые сортировки, любые структуры данных, у тебя либо частная реализация, либо где-то торчит войд поинтер.
>Это еще одна проблема Си - нужно переизобретать мир
Это не проблема. Это чистая вкусовщина и никакого консенсуса на тему что же должно быть в стандартной либе а чего там быть не должно попросту не существует (в контексте любого языка). Кому-то надо раздутую либу и раздутый язык с кучей говна к которому никогда не прикасаешься, и для него даже сишка со своими гото и волатайлами могла бы быть поменьше.
>у тебя либо частная реализация, либо где-то торчит войд поинтер
Либо ты генерируешь код макросами. Никто и ничто тебя не заставит копипастить код, если ты этого сам не пожелаешь.
Из-за ностальгии, скорее.
Но эта дискуссия совсем нерелейтед.
>>109127
Постараюсь попроще.
Внутри функции result действительно выделяется на стеке.
Но при этом, float2 является структурой данных, и при возврате из функции она копируется целиком. Поэтому v3 - это по факту полная копия структуры result, которая располагается уже на стеке функции main.
Проблемы у тебя возникли бы, если бы в функции у тебя было бы, например,
> char string[10];
И ты бы вернул из функции char * - в этом случае при возврате скопируется только указатель на массив, а сам массив будет потерян, ведь он располагался на стеке.
То же самое происходит, если ты пытаешься из внутренней функции вернуть
> const char string[] = "Hello";
Механизм работы точно такой же, но при этом поскольку константный литерал "Hello" лежит не на стеке, а в секции данных, то проблем в этом случае уже не возникнет.
В Си простые типы (int, float) копируются целиком, структуры копируются целиком, а вот массивы передаются только по указателю.
Как-то так.
ну ты боженька, спс большое, дай господь тебе долгой и счастливой жизни.
Тогда, я так понял, такие фокусы не получатся уже, если у меня в структуре будут указатели либо массивы, тогда уже под эти поля надо выделять динамическую память, иначе данные потруться когда выйду из функции? я правильно понял?
:3
Всё верно понимаешь, но там есть ещё одна тонкость, связанная с массивами и указателями.
Если у тебя есть структура
> struct yoba_s { int a[4]; int * b; }
И какая-то переменная этого типа, например, yoba_1.
То это означает то, что у тебя есть где-то область памяти, в которой подряд идут четыре целых числа int (в структурах массивы располагаются прямо "внутри" них), а затем указатель на массив из int.
Соответственно, если ты напишешь
> struct yoba_s yoba_2 = yoba_1;
То у тебя появится где-то на стеке вторая такая же структура, в которой будет точно такие же четыре int (опять же, структуры копируются целиком) и точно такой же указатель на массив int, указывающий на ту же самую область памяти, что и оригинальный.
Чтобы сделать полную "глубокую" копию этой структуры, тебе нужно будет после присваивания отдельно выделить память под поле b структуры yoba_2 и скопировать поле b в эту память из структуры yoba_1. В противном случае, если этого не сделать, массив a скопируется как ты ожидаешь, а вот массив b при изменении в структуре yoba_1 будет изменяться и в структуре yoba_2.
void push(int value)
{
__struct node_t *node = malloc(sizeof(struct node_t));
__node->value = value;
__node->next = NULL;
__tail->next = node;
__tail = tail->next;
}
При последовательном вызове push() вне цикла всё нормально - элементы добавляются в список как надо. В цикле for или while вызов на первой итерации добавляет элемент, а последующие переписывают его по тому же адресу. Объясните нубу, как это работает?
> Объясните нубу, как это работает?
__tail->next = node;
__tail = tail->next;
Это чо ха хуйня? __tail = node
Ну это какбэ основной вызов программирования, что у тебя общего стейта становится больше и больше и в какой-то момент ты уже перестаёшь в нём ориентироваться. Для этого и придумывают всевозможные паттерны и парадигмы. ФП, например, минимизирует протечку стейта, декларируя что функции должны быть чистыми. ООП максимально изолирует стейт, распиливая его на кусочки и распихивая по объектам, где им сравнительно легко управлять. Вот и думай.
ага, понятненько
В общем массивы они встроены в структуру, и т. к. структура копируется полностью то и массив в ней тоже,
а указатели - по сути число (адрес на память), при копировании структуры копируется и указатель, но копия указателя указывает на тот же блок памяти.
вроде даже как-то просто все
фух, вот это меня осенило, спс еще раз, анончик
tail на последний элемент списка указывает. Ты не добавляешь элемент в список, а просто переписываешь уже существующий.
Всё верно понимаешь!
Удачи тебе ещё раз в грызне гранита науки
>>109143
Проблем не вижу, если честно.
Выкладывай полный код, как вызываешь внутри цикла.
>>109151
> tail = tail->next;
> tail = node
Так это одно и то же ведь.
>>109243
Смотря чего ты пишешь, но обычно нет, не нормально.
Объявляй переменные по ходу, сишка уже давным-давно позволяет так делать.
Разбивай функцию main() на подфункции или хотя бы на { блоки }, объявляй локальные для блоков кода переменные внутри этих самых блоков - они не будут видны для кода вне блока.
Сливай переменные в структуры, если какие-то из них по смыслу кода лучше смотрятся вместе.
Ну давай, расскажи нам, чем
> tail->next = node;
> tail = tail->next;
отличается от
> tail->next = node;
> tail = node;
>> tail = tail->next;
Тем что это node->next текущего узла которое вероятно 0 или говно, ты глупенький?
Ориентируются на исходники юниксов и линуксов, но там много и устаревших приемов
я глупенький,
еще раз объясните пожалуйста, только языком, понятным для аутистов почему
>> tail->next = node;
>> tail = tail->next;
>отличается от
>> tail->next = node;
>> tail = node;
?
Ты слаб в иронии
Не в том смысле, что для крестов нужна, а в том, что "для крестов даже не нужна, а кресты в 500 раз сложнее, для си тем более не нужна".
та всмысле? вон братишка чет спизданул, правда я нихуя не понял, там написано на эльфийском, видимо
> Тем что это node->next текущего узла которое вероятно 0 или говно, ты глупенький?
второй братик рапортовал что он обосрался
всмысле ничем? братик зря обосрался что-ли?
>еще раз объясните пожалуйста, только языком, понятным для аутистов почему
Ничем, просто второй вариант более очевидный
>всмысле ничем? братик зря обосрался что-ли?
Пошел на хуй, обосрался и обосрался, признал свою ошибку, что доебался то?
>кресты в 500 раз сложнее,
Кресты кстати легче чем Си. На Сях иной раз нужно городить костыли под 1000 строк, в то время на Крестах тоже самое можно сделать через какой-нибудь темплейт с лямбдами где все это займет 200 строк.
Количество кода = сложность, понял тебя.
Я-то думал что количество нативного языкового барахла и объём стандартной либы определяет сложность, т.к. их надо ещё изучать и знать где и как применять, но раз так значит так.
Чел, ты просто двух анонов перепутал.
Другой анон подумал, что там в первом случае tail->next не проинициализирован. На самом деле всё инициализировано предыдущей строкой - ну ошибся, ну с кем не бывает?
Код действительно ничем не отличается, только лишь читаемостью.
Гуглишь: DialogBoxParam, сам диалог нарисуешь в Visual Studio (там можно .rc создать) или в Pelles C (100 метров вместо 6 гигов вижуалстудии) или в ResEdit (2 метра, http://rsdt.free.fr/ResEdit-win32.7z сайт https://resedit.net/ умер в этом году, есть в вебархиве).
> есть говнокод из >>093997
Это под линукс, в винде никаких дев-тетивай нету. Нужно будет CreateFile("COMxx"...), SetCommState, Read/WriteFile, возможно WaitCommEvent, вот это все.
в общем откопал тест фреймворк criterion
написал функцию, написал для нее юнит тест
он в общем упал, ну и хер бы с ним, решил подебажить
достаю гдб натравливаю на тест, ставлю бейкпоинт на свою функцию, а эта падла как-то хитро либо в тредах либо хуй пойми как запускает, что мой брейкпоинт не срабатывает
в общем нужна хелпа с гдб, почему не работает брейкпоинт
с меня как обычно огромное спасибо!
нашел у них ишью на гитхабе, можно с агрументом --debug
запустить бинарник с тестами и с гдб удаленно подключиться и дебажить, но гемор тот еще.
а я только в виме настроил гдб, а тут через какую-то шляпу надо запускать. Нормально что-ли сделать нельзя было. Эх, горе конечно (
хотелось бы найти способ чтобы просто скормить тесты гдб и стопнуться на брейкпоинте
хз, тип хочешь подебажить в определенных условиях функционал свой, написал тест, нужные аргументы проставил, вызвал метод, брейкпоинт поставил и погнал, удобно. Я так на рубях привык, тут даже дело не в тесте, а именно в возможности продебажить, нашел пофасту свой тесткейс, брейкпоинт поставил и погнал. да и на будущее юнит тесты остаются, полезно тоже
А что, на си нет культуры тесты писать? мне кажется как раз наоборот, на каком нибудь питоне или руби можно хуй забить, а в си надо.
Зови меня просто Леша, или Леха, как тебе удобнее
>>111507
GoogleTest можно си тестить?
>хз, тип хочешь подебажить в определенных условиях функционал свой, написал тест, нужные аргументы проставил
Все правильно, но на Си писать тесты это жопа, бери любой скриптовый язык который может с Си. Я в обще все на Перле прототипирую, потом на Си перекидываю. Си это ммм, вишенка на твоем разработанном и отлаженном торте.
> А что, на си нет культуры тесты писать?
Это не культура, это бескультурие. Лучше потратить время на написание качественного кода, вместо кучи некачественных тестов.
Вообще, достаточно сделать отдельный main с ассертами внутри #ifdef TEST, какие еще нахуй фреймворки.
С самим C++ при этом куча других проблем.
>Это не культура, это бескультурие. Лучше потратить время на написание качественного кода, вместо кучи некачественных тестов.
я же говорю, что для дебага, как ты можешь написать качественный код не отладив его? и почему идет сравнение качественного кода и некачественных тестов, все равно что сравнивать свежий кексик с черствой печенюхой.
>Вообще, достаточно сделать отдельный main с ассертами внутри #ifdef TEST, какие еще нахуй фреймворки.
ну можно и так, я ж поэтому и спрашиваю, как принято.
В рубях тоже можно сделать test.rb файл и в нем ебошить что-то типо
raise "Test failed" unless actual == expected
но никто же так не делает.
Да и вон видишь как допустим этот тест фреймворк тесткейсы запускает, в потоках или форках хуй знает, видимо изолирует как-то их друг от друга.
Хотя я подозревал что в си сидят суровые дядьки с компилятором в голове, и они не отлаживают, они видят все проблемы сразу как только посмотрят на код
Но я же не такой (( пока)
>>111517
не понял немного подхода, ты тип пишешь на перле и потом все на си переписываешь?
либо какой-то функционал переписываешь на си, но в общем это все равно перл? и как это спасает от написания тестов?
Все мы ошибаемся, так что всё нормально! Главное усвоить новый опыт
> почему идет сравнение качественного кода и некачественных тестов
Потому что тестировать strlen("x") == 1 глупо. Чтобы в тестах был смысл, нужно увидеть и проверить граничные условия и специальные случаи. Если ты их не видишь или видишь не все, то твои тесты некачественные. Это во-первых.
Во-вторых, вот у тебя есть код: int values[3] = {0}; for (i = 0; i <= 3; i+=) values += 2; Вот ты написал тест, assert, memcmp, все дела и пошел спать довольный. А завтра у тебя код падает, тест работает. Или наоборот. А потому что в Си есть UB. Это скорее всего та причина, по которой твой фреймворк запускает тесты в потоках. Но потоки все равно ничего не гарантируют, на то оно и UB.
да я согласен что юнит тесты вообще не дают никаких гарантий. Я на практике это знаю.
но ты просто так говоришь что вот не будешь ты писать тесты, и код качественней станет за счет того что ты больше времени на него потратил. я с этим категорически не согласен.
Во первых тебе все равно надо как-то прогнать/запустить то что ты написал, как ты можешь быть увереным в том что код твой рабочий, если ты его не запустил. Юнит тесты отличное этому применение, я для этого их и юзаю, а не для уверенности что я обработал вообще все состояния и исходы.
Во вторых пока ты тестишь вручную, по сути тоже самое что и тестами, только в случае тестов, они у тебя остаются на будущее. В случае какого-то рефакторинга, добавление каких-либо данных или фичей старые тесты помогут понять не сломался ли старый функционал, как минимум то что было покрыто.
Да и как по мне когда у тебя описаны основные кейсы тестами то отладка ускоряется, тебе всего лишь в нужное состояние надо брейкпоинт вставить, и сиди колупай что происходит. Сам тест написать не сложно, хуле вызвал ассерт свою функцию что ожидается. Разработка как по мне ускоряется когда рука набита тесты писать.
> как ты можешь быть увереным в том что код твой рабочий, если ты его не запустил
Я сейчас скажу страшную вещь, адепты TDD от нее рвутся обычно. Ты не поверишь, но я свой код читаю. В особо сложных случаях (реализации алгоритмов, а не перекладывание байтиков из одной переменной в другую) еще и комментирую возможные входные данные и реакцию на них, потому что спустя полгода нихуя не очевидно, почему оно написано именно так.
> старые тесты помогут понять не сломался ли старый функционал
Вот это реальный юзкейс, но рефакторинг еще не факт что будет. Это как с избыточными абстракциями в ООП: чаще всего интерфейс не имеет больше одной реализации, код не переиспользуются, но все равно пишется куча ненужного кода на тот невероятный случай, если вдруг когда-нибудь понадобится сделать что-то странное. Будет рефакторинг - тогда придет время писать тесты (для публичного апи), без этого никак. Не будет - останется больше времени на написание кода.
>Ты не поверишь, но я свой код читаю.
ну я так пока не могу, я только вкатываюсь в си. я не могу быть уверен на 100% что я написал код, который работает как надо, просто потому что у меня опыта на си толком нет.
и я не адепт TDD, скорее R(epl)DD, но так как репла в си нет, я пытаюсь сделать реализацию, запустить ее с какими-то входными данными и пройти в гдб по шагам. Но запускать мне проще через тесты, чем все время менять тело main функции, да и других причин хватает. Возможно я пытаюсь применить подход не применимый к си.
>я не могу быть уверен на 100% что я написал код, который работает как надо
Тесты тебе не помогут
Тесты не нужны, я живу активной и полноценной жизнью. Каждая отладка занимает 20 минут. А потом я иду писать void ptr, я не писал void ptr неделю!!! Пойду попишу.
Тесты не нужны, я живу активной и полноценной жизнью. Каждая отладка занимает 20 минут. А потом я иду писать void ⚹ptr, я не писал void ⚹ptr неделю!!! Пойду попишу.
Тесты часто проверяют банальщину, что тратит время, а сложное протестировать ты всё равно не сможешь, ибо обычно прогер всё проверяет на работоспособность и если ошибка возникает, то она такой сложности, что ты заебёшься придумывать тест для неё.
Так, как будто никакого UTF-8 не существует. Он вполне прозрачен, особенно пока твоя обработка ограничивается ASCII-символами (ну там путь к файлу по слешам порезать или текст на строчки разбить). Если нужно будет всякое там регистронезависимое сравнение, возьмешь ICU уже по-взрослому, но обычно это означает гораздо больше ебли с юникодом, чем ты можешь себе представить.
Но ведь тесты алголоподобным языкам реально не нужны, ведь есть борщехлёбские тройки Хоара.
> часто проверяют банальщину
Не банальщину, а edge cases, чтобы при очередном рефакторинге тебя банальной off-by-one error по невнимательности не убило нахуй.
> сложное протестировать ты всё равно не сможешь
Сложное руками тестировать не нужно, для этого есть fuzzing. Руками нужно тестить то, на чем уже погорел, т.е. удостовериться, что все найденные баги действительно пофикшены.
> если ошибка возникает, то она такой сложности, что ты заебёшься придумывать тест
Это указывает на проблемы в дизайне кода. Функции надо делать размером поменьше, абстракции попроще, а state локализовывать.
какие же сишники дегенераты, пиздец, подумать только, я лет 10 назад сам таким же был
> edge cases
Я уже говорил об этом выше. Если знаешь, что тебя тут может ебануть - проще перепроверить условие, а не писать тест. Если не знаешь или предполагаешь неверно - и код, и тест будут неверными.
> fuzzing
Это называется рандом. Или найдет проблему, или не найдет. Второе вероятнее, зато можно говорить работодателю модные слова и уверять, что ты не занимаешься хуйней вместо написания кода.
> Функции надо делать размером поменьше
Начинаются своих макконнеллов, а потом у них хром с одной вкладкой тормозит. Надо, да. Еще бы это было всегда возможно, вообще было бы здорово.
Ты ему про Ерёму, а он тебе про Фому.
> Если знаешь, что тебя тут может ебануть - проще перепроверить условие
А если не заметишь и проебёшься? А если это не твой код, и ты не знаешь? Такими темпами и код-ревью давай в пизду, а то что время на какую-то хуйню новомодную тратить, кабану код выкатывать ещё вчера. Прелесть тестов именно в том, что то, что ты предлагаешь можно автоматизировать: вместо того, чтобы всем постоянно делать это вручную, достаточно запрограммировать один раз.
> Если не знаешь или предполагаешь неверно - и код, и тест будут неверными.
Это всё детский максимализм. Вот у тебя и еще сотни разработчиков проект на 10 миллионов строк, какая-нибудь залупа из твоего кода дергает функцию, написанную 10 лет назад чуваком, который уже помер, а она тормозит. Можно пойти, выбросить к хуям так любимые сишниками связанные списки и воткнуть туда хеш-таблицу. Тебе не надо тратить время и разбираться как эта функция работает, тебе лишь интересно убрать десяток миллисекунд латенси в своей API или что там у тебя. Если функция покрыта тестами, то у тебя на подобный фокус уйдет минут 15, дальше ты можешь дальше идти заниматься своими делами, а иначе нужно сидеть и изучать бизнес логику, играть сам с собой в виртуальную машину и т.п. Нахуя? Ну ок, вот решил ты полностью переписать этот старый кусок говна. Молодец, а что дальше? А дальше, если у остальных есть тесты, то быстро всплывет, что то, что ты посчитал в коде придурью и выбросил за ненужностью оказывается было необходимо для какой-то хитрой ебанины, про которую ты вообще раньше и не слышал даже. Проблема, безусловно, в ебанине, которая, возможно, неверно понимает контракт, но фишка в том, что баг удалось поймать до релиза. А не было бы тестов - уронил бы прод, потому что полез своими ручонками куда не следует.
>Функции надо делать размером поменьше
Это вот эти вот легендарные погромисты "мам функция слишком длинная, разделю-ка я её на три и вызову их последовательно, ну и что что они у меня больше нигде в программе не вызываются", превращающие нормальный структурированный код в лапшу.
Все с точностью до наоборот: превращают лапшу в структурированный код. Банально потому, что у функций есть осмысленные человекочитаемые имена. Но меру тоже надо знать, это да. Писечка, конечно, вся именно в правильно выбранных абстракциях и композиции.
Это копия, сохраненная 1 августа 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.