Это копия, сохраненная 7 сентября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ или http://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Классика от Отцов: 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 (драфт)
- man/Dash/zealdocs
Чем конпелировать:
- Очевидный GCC.
- clang: оче годно, батя рекомендует.
- Intel C++ Compiler: оптимизации, тысячи их.
- Visual Studio 2017 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://www.iso-9899.info/wiki/Books#Learning_C
Онлайн-утилиты:
- https://godbolt.org/ - Compiler Explorer позволяет посмотреть выхлоп компиляторов для введенного куска кода (больше полусотни разных версий компиляторов).
- http://cdecl.org/ - С Gibberish ↔ English помогает читать сложные сишные декларации.
Прошлые треды:
- №28: https://arhivach.cf/thread/339326/
- №29: https://arhivach.cf/thread/347271/
- №30: https://arhivach.cf/thread/366174/
"Дефолтный" в смысле как лапак для обычных. То есть любой человек, занимающийся матричными вычислениями, почти наверняка будет использовать его и блас.
Го в смузийную.
Я скачал DbgView и KmdManager.
Поставил на виртуалке Windows 7, загрузился через F8 отключил проверку цифровой подписи.
Использую WDK 7.1, получаю .sys файл, открываю DbgView->Capture Cernel messages, открываю KmdManager делаю Register (succes), делаю Run
Дальше KmdManager пишет succes, но DbgView при этом молчит (а должен напечатать "Hello World"), а через секунда появляется окно, в котором Windows ругается на отсутствие цифровой подписи.
Что я делаю не так?
Бля,
сейчас на Windows 7 - 32 запустил драйвер (до этого была 64), DbgView все равно молчит, но зато хоть сообщение об ошибке не появлется.
Сука, ничего не понимаю.
>>08281
И на 32 и на 64 DbgView перестал молчать после установки галочки "Enable Verbose Kernel Output" (понятия не имею что это значит)
Но мне все равно не понятно, почему в 64 версии он ругается, что "Системе Windows требуется драйвер с цифровой подписью", а в 32 - нет.
Кто-нибудь может объяснить?
mov eax, -2
ret 0
Господи, что происходит? Компилятор нашёл все неизменяемые переменные, прогнал их через код и заоптимизировал всё нафиг. Полностью! Ну как так жить?
А ведь всё, что я хотел, это посмотреть как компилятор разбирается с постфиксными инкерементами/декрементами внутри условий. Ну, типа вот такого
if( myvar-- < 0)
break;
К слову сказать - с выключенной оптимизацией компилятор такую чушь городит - заводит лишнюю переменную на стеке и реализует эту операцию очень неоптимально.
> с выключенной оптимизацией компилятор такую чушь городит
> заводит лишнюю переменную
В смысле, кладет в стек, а потом снова достает, выполняет операцию и кладет обратно? Это чтобы source-level отладчику было удобнее.
Блять звездочки не указываются, суко
да, джве звездочки
Блин, звездочки скушаны. :(
Спасибо.
Считается true сделать один вариант программы и по надобности компилировать под нужную платформу или делать изменения в программе и компилировать?
Платформенно-зависимые вещи выносишь в отдельные файлы (или даже модули), остальное единое для всей программы. Грубо говоря:
cc foo.c bar.c windows_feature.c
cc foo.c bar.c linux_feature.c
(а feature.h один для всех поддерживаемых платформ). Так не всегда получается, но желательно к этому стремиться.
Да, посмотри в https://github.com/GNOME/gtk/tree/master/gdk/ - там как раз отдельные папочки под конкретные платформы.
Для сетевых задач например да. Если данные, передаваемые по сети, можно сериализовать, то их сериализовывать следует в отличие от данных которые никуда с машины не уходят и их нужно обрабатывать без геморроя.
Если ты работаешь на локальной машине, никаких упаковок делать не надо. Если упаковываешь, то все выравнивания идут по пизде, и в упакованных данных можно оперировать типами меньшими чем машинное слово, не боясь растерять скорость которой и так нет.
Я ещё ногтем к крестам не прикасался.
Дефайны хреначу через строку.
В каждой функции, прямо между аргументами.
Иногда забываю, что пишу, начинаю рекурсивно один в один заворачивать, пока все *.c файлы до пары макросов не сожму.
Экспанд у меня длится больше компиляции на порядки.
На налима пойти наконец, весь год решаюсь.
Я если начну в скором времени кресты, буду их главаря читать.
Бьерн Страуструп типа
Программирование. Принципы и практика использования C++. Это же типа как у нас K&R?
2016, вроде свежий, главное, чтобы >2011, да?
Ну, как сказать. Читай только выборку, у него там воды на два косаря страниц унылого текста с размазанной сутью.
Я вообще с плюсов для самоваров начинал.
Мне главное, чтобы наиболее полное изложение языка сразу в одной книге было.
Я думаю, уж создатель языка асилил.
Вот у тебя нервы. Если дочитаешь, то через месяцов 4 отпишись, хочу посмотреть, что с тобой станет.
Сделать что ли несколько процессов средствами ОС API?
Не выдавай!
fopen может вернуть твой ENOENT в наследие от open().
open возвращает ENOENT по след. причинам:
> O_CREAT is not set and the named file does not exist. Or, a directory component in pathname does not exist or is a
dangling symbolic link.
> pathname refers to a nonexistent directory, O_TMPFILE and one
of O_WRONLY or O_RDWR were specified in flags, but this kernel
version does not provide the O_TMPFILE functionality.
Отметаем из этого либопроблемы (на уровне stdio) и остаётся:
A directory component in pathname does not exist or is a dangling symbolic link. Pathname refers to a nonexistent directory
Да
Указатель на указатель на указатель, указатель на массив указателей, массив указателей на указатели массовов указателей... В общем, можешь задрочить MMU и мозг как пожелаешь.
Ты немного объебался.
Что с тобой?
НУ ЯДРО ВИНДЫ ЖЕ НА СИ ЗНАЧИТ ЕСТЬ))))))))))))))))))))))
И есть какая-то замена system("cls") в си? Не хочется передавать управление. clrscr() - ф-я плюсов
И зачем ты мне написал, как надо чистить консоль в линуксе? Я имел в виду, есть ли какая-то функция, аналогичная clrscr() в си. system не нравится тем, что юзает командный процессор, соответственно, стандартная очистки консоли нет.
Также
>Почему работает функция system без подключения библиотеки stdlib.h? В исходнике из хедеров только stdio.h. Пишу в VS 2017.
?
Смотря чем собираешь. MinGW линкуется к MSVCRT.DLL, которая есть по умолчанию, плюс втыкает статически то, чего в MSVCRT нет (семейство printf, умеющее в C99-спецификаторы, например). Студия линкуется к поддерживаемой ей CRT, и если только это не Visual Studio 6.0, нужные рантаймы придется таскать с собой или устанавливать.
>>10579
> Почему работает функция system без подключения
Каждый тред одни и те же вопросы. >>1200083
> И есть какая-то замена system("cls") в си?
Нет. В Си нет понятия терминала, не то что консоли. В винде можешь проверить, что ввод-вывод не редиректнули, получить хэндл консоли и сделать FillConsoleOutputAttribute.
>>10603
Ты тредом ошибся. Но раз уж ты спросил, с lsusb работать очень просто:
lsusb -vvv
Тот, который используется в качестве системного компилятора.
Linux - gcc
FreeBSD/OSX - clang
Для совместимости с системными C++ библиотеками (включая runtime компилятора)
Ведь GCC генерирует лучший код, нет? В том же godbolt программы с аналогичными уровнями оптимизации в GCC выдают меньше ассемблерных строчек.
Синтетику отличаешь от реальных проектов?
Ну не скажи. Меньше строк = меньше итераций ЦП. Меньше времени на выполнение инструкций = меньге энергопотребление и тепловыделение.
Я утрирую конечно же, но в целом оно в общем-то так. Но когда речь идет о наборе из миллиарда из струкций и спор о <5 строках, то конечно это разговор в пользу бедных. Впрочем, минимизация даже на 0,00000001% тоже оптимизация.
Некоторые инструкции x86 жырные-жырные, они могут требовать очень разное время выполнения, особенно с учётом времени доступа к памяти.
Ну ет ты в дебри полез, я конечно согласен, но давай не будем про отдельно взятые инструкции. Их уместнее сравнивать в контексте обработки шлангом и гцц. Я и еб ввиду какой они выхлоп дадут
Ты далеко очень полез, для того, чтобы малость понимать, что он там оптимизирует, тебе надо знать алгоритмы и реализацию одной из сотни-другой оптимизаций https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html, чтобы осознавать возможность её применения.
Вот как раз доскональное знание асма тебе здесь не очень-то и нужно.
Подключил windows.h, объявил HWND mycaret = NULL, вл main вызываю
if (HideCaret(mycaret)) {
printf("HIDED");
}
Однако каретка не прячется, ф-ия вовзаращает нулевое значение, и, соотвественно, сообщение тоже не печатается.
mycaret ининицализирую NULL'ом, т.к. в документации майков сказано: "
Type: HWND
A handle to the window that owns the caret. If this parameter is NULL, HideCaret searches the current task for the window that owns the caret".
И про работу HideCare:
"HideCaret hides the caret only if the specified window owns the caret. If the specified window does not own the caret, HideCaret does nothing and returns FALSE".
Извиняюсь за опечатки, было неудобно писать
Лол. Каретка - это такая мигающая вертикальная палочка в GUI приложении. В консольном окне - курсор. GetConsoleCursorInfo, CONSOLE_CURSOR_INFO.bVisible = FALSE, SetConsoleCursorInfo.
Хм, путаница какая-то.
Когда вы в программе набираете текст, обычно маленький символ подчеркивания или маленький четырехугольник показывает вам место, где следующий набираемый вами символ появится на экране. Вы можете считать, что это курсор (cursor), но, если вы программируете для Windows, необходимо отказаться от такого представления. В Windows это называется "каретка" (caret). Слово же "курсор" относится к битовому образу, отражающему положение мыши на экране.
>Каретка - это такая мигающая вертикальная палочка в GUI приложении.
А где про это все можно прочитать? У меня обычно гуглится хуйня типа того, что написал выше
Алсо
Каретка — это обычно горизонтальная черточка или прямоугольник, имеющие размер символа, или вертикальная черточка
> А где про это все можно прочитать?
В MSDN. В разделе Carets про гуевые, в разделе Character-mode applications про консольный курсор.
Насчет терминологии, да, там путаница. Я в Windows API вещи принято называть именно так: консольный курсор, курсор мыши и каретка. Алсо, консольный курсор курсором называли еще во времена CGA, когда мышь если и была, то только у избранных.
Проиграл, сколько страниц осилил?
Лафоре пишет вроде неплохо, можешь его, но весь из себя такой объектно-ориентированный.
Там вроде только вступление на страниц 80. Из-за этой книги я долгое время думал, что плюсы - большая жопа. Ну на деле они все равно жопа, но не большая, а такая средняя.
Даже Си - большая жопа, если пытаться писать на нем правильно, а не как получится. А кресты - жопа не просто большая, а просто необъятная. Просто осознание наличия этой самой жопы в обоих языках приходит через несколько лет, по мере накопления опыта. И вообще, шли бы вы с крестами в крестотред.
Говорить, что С - жопа, потому, что тебе попалось какое-нибудь API с попоболью в придачу это как-то глупо.
C гибкий, не навязывающий парадигму, не перегружен синтаксисом, ну какая же эта жопа.
Максимум попка
Через десять лет, если не перестанешь писать на Си, ты обо мне вспомнишь. Дело не в каком-то там API, дело в недостаткках абстрактной машины, заданной стандартом - в избыточных абстракциях в одних местах, в излишней свободе в других, в огромном количестве UB.
https://bash.im/quote/119233
Я не могу аргументированно говорить за другие, потому что в основном пишу на Си и крестах.
Так а как ты будешь питуну учиться? Книг нормальных тонет. То ли язык быстро развивается, то ли это принципиально "нам лень писать программы, книги писать нам тоже лень, поэтому мы выбираем питун".
Можно написать на С, на асме может выйти эффективней.
> не могу взглянуть
Можеш, тебе не понравится.
https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/vfprintf.c
> почему он уже изначально скомпилирован
Потому что код библиотек относительно редко меняется, зачем тогда ее исходники копировать из проекта в проект, зачем возиться с особенностями сборки, зачем пересобирать весь мир каждый раз, если можно один раз скомпилировать в машинный код, положить в либу и потом уже подлинковывать по необходимости?
> что такое библиотеки в языках с/с++
Когда ты делаешь cc -c file.c, компилятор делает объектный файл, содержащий скомпилированные в машинный код функции и данные. Библиотека - архив с такими файлами (как .zip, только без сжатия), и еще там есть индекс, чтобы можно было быстро узнать, что есть в библиотеке и в каком конкретно объектном файле оно лежит.
> Может потому что все эти функции нельзя написать на языке си и они написаны на ассемблере?
Отдельные части, где нужна скорость (memcpy, strcmp и т.п.) или те части, которые невозможно написать на Си (setjmp, например) могут быть написаны на ассемблере.
Исходники чаще всего где-нибудь есть. В линуксах в принципе опенсорс, в винде при установке той же Visual Studio можно установить заодно и исходники (U)CRT.
>В том же godbolt программы с аналогичными уровнями оптимизации в GCC выдают меньше ассемблерных строчек
Это уже 20 лет как не актуально. В современных CPU встроен out-of-order приборчик и транзисторный-компилятор-в-risc-микрокод приборчик, поэтому в наше время компилятор ублажает именно эти приборчики и все эти ужимки из доприборчиковых 80х-90х неактуальны.
>Довен, это не язык.
Кстати, для довнов:
Ассемблер - это компилятор языка ассемблера. Не та хуйня, на котороый вы пишете, а конкретно файлы masm.exe, tasm.exe - вот это вот все ассемблеры
Язык ассемблера - это хуйня на которой буковками пишут.
> Что за ошибка выдается компилятором на SetPixel?
Вангую, Gdi32.lib подключить в настройке проекта/Cmakelists забыл.
Засунул в компилятор маек и заработало.
Ocaml.
C# -> Win
Modula-2
Я, к своему стыду, только один такой проект вспомнил.
Там какой уровень и чё объясняется?
Нормально, упражнения поделой
Там только старьё вылазит.
>почитай про ОС и язык ассемблера
Ты, видимо, не представляешь как это всё взаимосвязано с Си.
> CPython получается умеет динамически вызывать сишные функции
ctypes/ffi.
> читал там про указатели на функции, но это же чё-то не то по идее
Почему не то? Аргументы преобразуются во что-то удобоваримое для сишной функции. Где-то берется адрес функции, и она вызывается. Только не напрямую, как ты бы сделал для обычного указателя на функцию, а через ассемблерную обвязку, потому что в Си нет синтаксиса, позволяющего вызывать одну и ту же функцию с разным количеством аргументов. Ну, точнее, можно switch (nargs) { case 0: return foo(); case 1: return foo(args[0]); case 2: return foo(args[0], args[1]); ... }, но это дикий костыль, который, к тому же, далеко не всегда применим (например, __stdcall/__fastcall так не вызовешь).
> Довен
Коверкает слова, путает название синдрома с именем его исследователя, а сам подгорает из-за "ассемблера". С этим ребенком все ясно.
>есть ли смысл читать K & G несишнику?
Откровенно говоря, эту книгу стоит читать людям далёким от профессионального программирования для изучения истории развития языка. К&R давно уже бесполезная ерунда для парочки ностальгирующих олтфаков.
Петя, ты чё несёшь? Какой синдром, какой исследователь? И где ты пожар увидел, на своём пердаке?
Не, я все прекрасно знаю, просто не так понял человека
подумал что он хочет си для саморазвития учить,
а оказалось, что хочет для саморазвития почитать классику от дедов
бля, чувак, ты слишком эрудированный
вангую что получаешь <60 если ты в мухосрани и <90 если в дс
потому что люди обладающие сакральными знаниями, должны уничножатся ибо нехуй шатать систему и стабильность
В том смысле, если такой поток захватил на очередном тике кванта проц, то он его уже не отдаст другим юзермодным потокам, пока не завершится (ядро, прерывания могут забрать, естественно). Похуй если все остальное при этом повиснет, если проц в системе один. Я подозреваю в что nt такой трюк не провернуть, а в nix? Модификацией и перекомпиляцией ядра, например? Хуй его знает зачем я тут это спрашиваю, но сишники должны быть прошарены в этой теме.
>Модификацией и перекомпиляцией ядра, например?
Да, можно. Есть же ртос RTLinux. Можешь сам погуглить или жди ответа отцов.
>ты слишком эрудированный
Скорее старый. RISC всех нагнул ещё в 90-х, это сейчас уже не слышно той волны хайпа. Т.е почти все современные процессоры, в т.ч. CISC, на самом деле RISC с "приборчиками" и прочими микропрограммами.
Javascript
Что делать????????
Спасибо большое!
>Где-то берется адрес функции, и она вызывается
Вот как раз этот механизм интересен. Получается, что определяется адрес функции в памяти по её имени. Ничего не нагуглил по этой теме.
Зачем? Это не ты там все еще в msr пишешь? Юзай интринсики. Если не ты, то ты всегда можешь написать интересующую тебя функцию в отдельном .asm-файле - в общем-то, так стоит делать даже в том случае, когда инлайн-асм поддерживается.
>>13324
> определяется адрес функции в памяти по её имени
Для этого где-нибудь в каком-нибудь виде хранятся символы (имена с адресами). Например, для .so и .dll ты можешь пропарсить эти данные и получить адреса экспортируемых функций с помощью dlopen/dlsym и LoadLibrary/GetProcAddress соответственно. Неэкспортируемые функции по имени вызвать нельзя, но можно делать колбеки - ты кому-то аргументом передаешь адрес (или адреса) функций, а этот кто-то в нужный момент их вызывает.
> Ничего не нагуглил по этой теме.
Можешь полистать Linkers and loaders как минимум. Ну или википедию на худой конец.
Покажите, пожалуйста, пример аккуратного и простого мейкфайла, чтобы я мог посмотреть на него, сразу разобраться что к чему, и потом по его образу и подобию лепить свои поделки.
Главу про мейкфайлы из книжки хороших примеров прочитал, но там целикового файла сложнее, чем из одного .с в один .out нет да и кое-где там всё довольно странно для хорошего стиля
> аккуратного и простого мейкфайла
SOURCES=foo.c bar.c baz.c
LIBS=-lsomething -lanother
appname: $(SOURCES)
$(CC) $(CFLAGS) -o $@ $(SOURCES) $(LIBS)
Вот код:
int main (void){
int arr [] = {0,1,2,3,4,5,6,7,8,9};
printf ("%p = %p\n",&arr[0], arr);
printf ("sizeof arr = %ld\n", sizeof arr);
printf ("sizeof arr[0] = %ld\n", sizeof arr[0]);
printf ("Elements = %d ", sizeof arr/ sizeof arr[0]);
return 0;
}
Вот вывод:
0061FF08 = 0061FF08
sizeof arr = 40
sizeof arr[0] = 4
Elements = 10
Вопрос: В книге пишут, что arr и arr[0] по сути то же самое и по этомуони имеют одинаковй адрес. Но почему тогда размер arr 40 бит а arr[0] - 4 бита?
Эти две штуки указывают на один адрес памяти, но подразумевают разные типы данных - массив и первый элемент массива. Посему этот код делит размер всего массива на размер элемента массива, таким образом вычисляется количество элементов в массиве.
Приём интересный, но если не понимаешь что делаешь, лучше объявил размерность массива дефайном и используй его. Иначе можешь наступить на грабли с указателем вместо массива - код скомпилится, но работать будет не так как ожидаешь.
Это не одно и тоже, arr имя массива, поэтому сайзоф его равен количеству байт, которые он занимает, а arr[0] это первый элемент массива и у него соотв сайзоф будет равен размера именно елемента.
Насчёт одно и тоже, просто arr и arr[0] имеют одинаковый адрес, поэтому в плане доступа к первому элементу нет разницы, что ты напишешь звездочкаarr = 1, что arr[0] = 1, второе раскроется в звездочка(arr+0) = 1.
И да sizeof не в битах возвращает, а байтах..
Хотя не в байтах, а фактически в char. Обычно это байт, но на некоторых микроконтроллерах char является 16-бит.
Т.ч. если хочешь писать действительно портабельный код, имей это в виду char не всегда байт.
> Т.ч. если хочешь писать действительно портабельный код
#include <limits.h>
#ifdef CHAR_BIT != 8
#error "Уходи."
#endif
Чаще всего это наиболее верное решение.
#if CHAR_BIT != 8, ну вы понели
поясните за биндинги, зачем нужны всякие растики и прочие плюсы, если можно писать скриптули на питонии, и трогать железки через сишечку только при необходимости?
ну и вообще объективно какие плюсы у С ? лол, чому весь линепс на сишке и хаскеле, наследие саянтистов, лень или какая то объективная йоба причина?
Скорость. И не забывай, что из Питония в сишечку данные переложить — это тоже не бесплатно.
Создатели Юнити тоже думали "можно писать на решетках и жабаскрипте, а плюсики трогать только при необходимости", в итоге эта "необходимость" - бутылочное горлышко 95% программ (в т.ч. игр) на сабже.
>Скорость
Надежность.
уже начинатался, один лягушатник линупсовое ядро на расте переписал, но всем похуй, тому шо новые баги за бесплатно никому не упали, не только в ядре но и в других утилитах
а что до скорости, так она нужна не везде же, а если на глаз не видно разницы, то зачем платить больше?
>>16465
>Создатели упити думали
над тем как по дешману склепать бесплатное говно и распиарить среди безмозглых школьников что бы подсадить на стор, в котором лежит основная часть функционала
так что пример неудачный
> один лягушатник линупсовое ядро на расте переписал
Работы тут на качественную ВКР. Отличие абстрактного ядра от ядра Линукса в количестве драйверов. У лягушатника их нет, говно лягушатника потому никому и не нужно.
Если ты вдруг решил не проверять, он написал 120 КБ кода. Это действительно уровень ВКР, за которую не стыдно.
C реально крут и удобен, когда теме надо на низком уровне с данными работать, упаковывать их куда-то в какие-то пакеты, работать с указателями и т.п. Есть вещи, которые ты на Си сделаешь парой строк, а на питоне в разы больше будет и кривее, не говоря уже про скорость.
А стыковать Си и Питон то ещё удовольствие.
и ещё объективный момент, что просто удобнее запускать. Ты ведь запускаешь всегда что-то скомпилированное. А если пишешь на питоне, то надо запускать интерпретатор тяжеловесный, а под ним уже саму программу. Накладно. У тебя на компе ведь реально десятки-сотни сервисов одновременно работают
Могут ли опытные господа тут объяснить, зачем потребовался такой в высшей степени уёбищный костыль, как CMake?
Сейчас работаю с ним, и эта хуйня зачем-то генерит абсолютные пути к проекту, в результате его не скопируешь в соседнюю папку без геморроя.
Задаюсь этим вопросом все время, пока он существует. Почему-то из всего существующего говна именно это стало модным. Хуй с ними, с путями. Каждый раз при сборке тысячей мелких тестов проверяются очевидные вещи, которые нормальные люди делают целую одну строку #if __STDC_VERSION__ >= 201112 и уже не задаются вопросом, есть ли у компилятора size_t. CMake не может задетектить доступный в path компилятор, я могу сделать cc file.c, а эта охуительная система сборки - нет. Не может увидеть даже слегка нестандартно установленный компилятор, особенно под виндой - установлена студия, в path cl.exe, нет, надо полезть в реестр, полезть в Program Files, нихуя не найти и ничего не скомпилировать. Добавление поддержки какой-то кастомной утилиты или неподдерживаемого компилера - это пиздец вообще - макроязык и документация к нему за пределами добра и зла.
>когда теме надо на низком уровне с данными работать, упаковывать их куда-то в какие-то пакеты, работать с указателями
ну да вот я так себе и представляю, что есть нормальная программа с абстракциями всей хуйней, а есть самая низость, которую вася из барнаула за 35к пишет, походу откушивая горькую, вся его жизнь боль
>А стыковать Си и Питон то ещё удовольствие.
чому?
>>16928
>надо запускать интерпретатор тяжеловесный, а под ним уже саму программу. Накладно. У тебя на компе ведь реально десятки
питонических софтин работают, ну может не десятки, но с пяток точно
придет день и питоний будет в ядре в браузере даже в аллахе, вот тогда заживем ммм
>Могут ли опытные господа тут объяснить, зачем потребовался такой в высшей степени уёбищный костыль, как CMake?
Просто для C/C++ нет нормальных систем сборки вообще (не считать же кнопку F5 в проприетарных IDE?). Или ты пишешь нечитаемые баш-скрипты руками на прыщах штульмана, или ты пишешь нечитаемые баш-скрипты руками с применением разных велосипедов (autotools и прочие). Или пишешь код на питоне.
Собственно, CMake и выстрелила тем что не нужно заниматься программированием на других языках чтобы просто собрать проект
обосрался, с самого начала выглядело подозрительно..
>если можно писать скриптули на питонии, и трогать железки через сишечку только при необходимости?
Потому что это маняфантазии и на практике код более менее сложнее хелоуворлда безбожно тормозит. Тот же джанго уже давно в среде системных интеграторов стал мемасиком - под него топовые сервера только в путь уходят. А заводчики облаков с джангоебов лопатами бабло за топовые конфигурации гребут.
Более того, даже история с микроядрами загнулас по причине их неработоспособности в реальном мире, а там всего лишь байтики по каждому чиху копировать надо.
А ты скрипты интерпретируемые пердолить предлагаешь. Тут вот годот в соседней доске про геймдев собирается переходить на CLR, потмоу что собственный велосипедный фреймворк безбожно тормозит, а ты скрипты пердолить интерпретатором. Одумайся.
>ты про хурд? ну так там просто всем лень же
После хурда еще стопицот попыток было, вспомнить то же семейство l4 из которого самое успешное применение - модуль анальной DRM защиты гипервайзером к операционке (точнее параллельно в trustzone, насколько я помню).
>около-крестовая производительность после нативизации
Поржал. В уече и крестовая то не але, без перепиливания ванильного рендера и ядра.
ой всё, байтоёб раздухарился))
Пишу ядро ос. Как создавать дескрипторы файлов на таком низком уровне? Например, дескриптор, при помощи которого можно писать в видеобуфер в сегмент B8000.
С помощью драйвера файловой системы, который ты уже написал.
Но при чем тут видео буфер? Мапишь его куда тебе надо и работаешь с ним.
> не нужно заниматься программированием на других языках
Как не нужно? Если что-то сложное собирать, приходится писать на макроязыке CMake. А если что-то простое, то СMake не нужен, и мейкфайлы отлично заходят.
>>17274
> Но при чем тут видео буфер?
У него "все есть файл" протекает.
>>17241
Юзермодный дескриптор - индекс структуры в списке дескрипторов в ядре, в структуре описание девайса и всякие дополнительные данные, у девайса драйвер, у драйвера структурка, содержащая его собственные обработчики для read/write/seek/ioctl. Вот и реализуй в драйвере чтение-запись в видеобуфер.
Вставляет целиком и полностью запрашиваемый файл в оный файл.
0|0 -> 0
0|1 -> 0
1|0 ->1
1|1 -> 0
Вот как мне подобное провернуть для всех битов числа? Прошу подсобите.
Благодарю.
Но что-то моих знаний явно не достаточно. Кто-нибудь такое делал?
Можете поделится опытом, книги, сайты где это разжевано нормально.
Вот самый примитивный функционал. Даже с пояснениями.
http://blog.vinu.co.in/2012/03/multitasking-in-avr-atmega32.html#more
> Не говоря уже о пояснениях принципов работы
Городишь систему таймеров, хотя можно обойтись и без нее. Основа - очередь с приоритетом, в которую ты заносишь следующее запланированное срабатывание каждого таймера (гуглишь фибоначчиеву кучу, чтобы сделать очередь с приоритетом), добавляешь туда же таймаут переключения задач (если нужно), програмируешь таймер на ближайшее срабатывание из очереди и ждешь.
По прерыванию (таймера или чего-то еще) выбираешь задачу, на которую хочешь переключиться - смотришь, какой задаче "принадлежит" это прерывание (допустим, какая-то нога выделена какой-то задаче, и за нее дернули) или какая-то задача давно не получала процессорного времени. Сохраняешь текущие значения регистров, заменяешь на значения регистров выбранной задачи, все. Это была вытесняющая многозадачность. Для кооперативной делаешь все то же самое, только переключаешь задачи не по таймеру, а исключительно по вызову какого-нибудь yield().
>>18167
> Бля, ассамблер.
Кусок кода для манипуляций с регистрами все равно придется писать на ассемблере, хотя можно извратиться с setjmp/longjmp. Остальное вполне можно написать на Си.
Так у avr он очень простой. Главное алгоритм понять.
На гитхабе поищи еще, может там уже говнокодил кто
Он хочет изобрести велосипед, тащемто ничего плохого в этом нет.
Я находил простой, вот:
https://pastebin.com/YDCjSzKb
https://pastebin.com/2a7eePqc
Все вроде расписано. Но я не очень умный, и у меня почему-то не работате
Допустим, есть функция
uint8_t testf(float var1, float var2) {
...
static float var3 = 0;
...
...
var3 = var4;
return out;
}
Я правильно понимаю, что при каждом вызове функции var3 будет равно нулю, хоть что в неё присваивай далее по ходу функции?
Вообще, даже если объявить static var3; , то там будет чёртов нуль и после var3 = var4; будет тот же нуль?
static-переменная внутри функции полностью аналогична static-переменной вне функции, за исключением того, что область видимости ограничена функцией, а не текущим модулем. Такая переменная будет инициализирована однократно, на этапе компиляции, обязательно константой, а если ты забыл ее инициализировать, то там гарантированно будет ноль. Когда ты впервые вызовешь функцию, в переменной будет то значение, которым ты ее инициализировал, а если ты потом запишешь туда что-то другое, это новое значение там и останется.
Не, ну там подробно и последовательно вроде расписано, я хз почему он справочник, это единственное что я выцепил в библиотеке, а то в электронном виде мне что-то не читается. Прост если например я Пратта почитаю, я сразу поумнею или шило на мыло?
Вузик дропай
что не так, поясни
А если нет, то на какие функции следует обратить внимание и похацкать перед сборкой, чтобы запрашиваемое количество памяти при старте было минимально?
Но ведь часть страниц просто будет храниться на жёстком диске периодически заменяя другие, подгружаясь в рам.
Почему-то так тоже не работает, прога все равно киллает саму себя при любом размере подключенного файла подкачки
Это не сакральные знания, это даже на стэковерфлоу можно прочитать. Впечатляет не эрудиция, а как он пишет красиво.
Читаю вики
> FENV_ACCESS ON
> pragma
> isnan
Ничерта не понимаю. Мне нужно нормально реализовать матешу, контроли переполнений и делений на ноль.
Я даже не могу найти инфу, что переполнение вызывает NaN.
Там ещё как-то макросами можно точность вычислений менять по возможности, тоже хотеть.
>вызывает NaN.
Строго говоря - в том числе при переполнении вместо результата нани.
>макросами можно точность вычислений менять
Полная хуйня, точнее дабла стандартных нет - а делать точность меньше это явно не твой случай.
И графики на ходу.
У меня, правда, лагают писец эти графики
%%А ещё, грёбаный в рот, я уже придумал, как это дело параллелить, но сложнее тут распарсить и обработать исключения*/
> Есть где полновесный гайд по фичам C99 c FP-операциями?
Черновик стандарта в шапке, IEEE 754. Начинать с https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ (чуть ниже начала статьи есть оглавление).
>>20368
> Полная хуйня
Про -ffast-math слышал?
> точнее дабла стандартных нет
long double.
> >макросами можно точность вычислений менять
>-ffast-math
Ебать дебил.
>long double
== double, дурачок.
На x86 еще с тех времен, когда FPU был отдельным чипом, поддерживаются 80-битные флоаты.
> The x87 provides single precision, double precision and 80-bit double-extended precision binary floating-point arithmetic as per the IEEE 754-1985 standard.
Только не говори, что x87!=x86
Про выравнивание слышал? Процессору неудобно читать 80-битные числа, поэтому они хранятся в 96 битах (3 дворда), но фактически вычисления идут в 80 битах. Признай уже, что ты уже обосрался, как только мог.
Смотря что писать. Если это не крупный проект, достаточно любого блокнота, который по интерфейсу нравится (саблайм, vscode). Студия - для тех, кому на самом деле нужны адвансед-фичи. Ты тоже можешь поставить ее поиграться, в ней можно (и удобно) писать код, и отладчик более чем норм, но стоит ли это все тех гигабайтов и тормозов - решать тебе. То же самое касается и CLion.
ну ок, допустим блокнот, а че там с компиляторами, они там идут в подарок? или брать первый попавшийся из шапки?
Ну как бы берешь MinGW или через MSYS2 ставишь гцц. Есть еще visual studio build tools от MS, оно немного bloatware, но в принципе норм. Можешь еще tcc взять в подарок, он что-то около 20 метров весит.
Если просто позапускать че-нить короткое tio.run
Все, что она умеет, это выдавать столбики кординат/скоростей каждого тела в каждый момент времени.
Было бы интересно сделать видео с перемещающимися точечками. Идеально -- в реальном времени, то есть чтобы не пришлось сначала 20 минут ждать высчитывания некоторого числа координат, а потом отрисовывать видео.
Это можно сделать на Си? Что проще всего использовать? Не хотелось бы, чтобы отрисовка занимала больше строчек, чем симуляция.
Графика может быть совсем простая. Каждое тело просто точечка. Но хотелось бы, чтобы это былы не совокупность статичных изображений, а полноценное видео, то есть чтобы точечки перемещались.
Про всякие полиморфизмы и перегрузки я ещё из теории компиляторов наслышан, но я всё равно не понимаю, когда разговор заходит про всякие монады-хренады.
Есть какая подборка всего это говна с разъяснением? Вики мне явно недостаточно, там зависимостей между статьями много.
Нихуя не понял, но подозреваю, что ты хочешь что-то типа https://nullprogram.com/blog/2017/11/03/
Что не так-то, блять? У тебя есть все координаты и скорости в каждый момент времени, ты осилил эту задачу, а теперь спрашиваешь как запилить рисование точек по заданным координатам?
А что не так в его вопросе?
Он может просто не знать, как делается, что в этом удивительного? Шахматист не должен обыгрывать тебя в покер просто потому, что видит на много ходов вперёд.
Спрашиваю, как создать видео. Типа такого: https://www.youtube.com/watch?v=DoLe1c-eokI
Внезапно, первый видосик в гугле имеет ссылку на гитхаб, посмотрю там, что за библиотека используется
Но вообще ты прав, поставленную задачу -- численно решить задачу n тел, -- я решил.
Визуализация полученного решения это новая задача.
Т.к. я такому решению смог придумать только такое использование, но это же полное извращение с кастами.
ideone.com/ea2Zag
>Это можно сделать на Си? Что проще всего использовать? Не хотелось бы, чтобы отрисовка занимала больше строчек, чем симуляция.
SDL+OpenGL первой версии.
> но это же полное извращение с кастами
Это Си. Не нравятся длинные касты - сделай тайпдефы, оберни касты в макросы, оберни обратные касты (из list в содержащую его структуру через offsetof) в макросы, напиши функции для манипуляции списками, и будет норм. А можешь пойти по пути Windows, там используют точно такой же list, но кладут его не в конец структуры, а в начало, что очень сильно упрощает жизнь и адресную арифметику.
> может ли кто-то объяснить как это работает?
Что именно объяснить?
Как работает список, ведь в структуре у нас лежит структура с указателями на себя же, а не на первичную структуру, как обычно делают списки.надеюсь понятно написал
Ну смотри. Есть макрос, который с помощью вот такого заклинания получает указатель на структуру из указателя на заголовок списка:
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
Используется так:
my_list ∗item = list_entry(somelist->list->next, my_list, list);
В свою очередь, макрос container_of, если опустить проверку типов, реализован примерно так:
#define container_of(ptr, type, member) \
((type ∗)((char ∗) (ptr) - offsetof(type, member)))
Т.е., от указателя на заголовок списка (struct list) отнимается смещение struct list внутри твоей структуры, и тем самым получается указатель на твою структуру. В винде то же самое называется CONTAINING_RECORD, параметры те же, реализация аналогичная. Вообще, при попытках реализовать нетривиальные структуры данных, подобной хуйней пользуются очень часто, она практически идиома, поэтому советую запомнить и применять только когда без нее по-другому никак не обойтись.
offsetof - уже стандартный сишный макрос из stddef.h, практически везде реализован как-то так:
#define offsetof(type, member) \
((size_t) &((type ∗) 0)->member)
Т.е., структура "виртуально" располагается по нулевому адресу, в этом случае адрес нужного поля численно равен его смещению. Автор известного в этой стране статического анализатора утверждает, что так делать нельзя, и хотя дереференса фактически нет, это все равно undefined behavior, и мы все умрем. И хотя никто не умер, никогда не стоит реализовывать этот макрос самостоятельно. Во-первых, потому, что он уже есть в стандартной библиотеке, а во-вторых, на какой-то экзотической платформе все может быть сложнее.
И, в общем, тебе не нужно обязательно помнить все эти детали реализации, просто пользуйся list_entry и прочими функциями и макросами из линуксового list.h, и будет тебе счастье.
Делаю костыли через fseek, но они не работают
Опиши подробнее задачу, расскажи, что именно не работает, потому что именно через fseek() (ну еще через fgetpos/fsetpos иногда) это и решается. Если поток - именно поток, а не файл, тогда ты не можешь по нему перемещаться, и тогда только кэширование уже прочитанного.
Нужно чтобы правая сторона картинки в разрешении bmp была зеркальным отражением левой
Считываю попиксельно через
fread(&rgb, sizeof(rgb), 1, in);
fwrite(&rgb, sizeof(rgb), 1, out);
и когда дохожу до середины ширины изображения нужно читать в обратную сторону для зеркальности
Звучит как максимальное извращение. Тебе известна ширина же. Выделяй массив шириной со строку, читай туда строку целиком (а не по байту), пиши строку целиком, потом в памяти изменяй порядок элементов в массиве на обратный, пиши строку целиком. Это будет на порядок быстрее и проще.
Если все же хочешь через жопу, то pos = ftell(in) в конце строки, потом for (i = 0; i < width; i++) { fseek(in, pos - i - 1, SEEK_SET); fread(...); fwrite(...) } но это пиздец как медленно и костыльно.
Раньше (лет 10+ назад) изучал C по Кернигану-Ритчи, но довольно скоро перешел на C++. Тонкостей работы с памятью, если и учил, то уже не помню. Сейчас хочу освежить знания. Да и язык, вижу, обновился.
Я нашел книжку 21st Century C: C Tips from the New School, но не уверен, подойдет ли она мне. Всякие азы азов уже объяснять не нужно, но вдруг там требуется уверенное владение старыми диалектами C? Так что, может и Кернигана-Ритчи достать перечитать лучше.Что вы мне посоветуете?
> 21st Century C: C Tips from the New School
Бесполезное говно. В одной книге смешаны питоновский апи, гсл, доксиген и еще куча материала, имеющего к сям посредственное отношение.
При том материал не описывается, а рекламируется: "Смарите, какая хуйня -- гсл. Щас диффур решим. О ебать, решили. Если понравилось, качайте документацию и разбирайтесь сами".
Блять, как работает эта ёбаная хуйня? Уже неделю не могу разобраться. Может кто-нибудь объяснить?
#include <stdio.h>
main()
{
int i;
//Проход по числам от 1 до 10
for (i = 1; i <=10; i++)
{
if ((i%2) == 1) //Остаток от деления нечетных чисел = 1
{
printf("От нечетных чисел одни неудобства…\n");
// Перескочить к началу новой итерации цикла
continue;
}
printf("То ли дело четные числа! \n");
}
return 0;
}
Далее приведен результат выполнения данной программы:
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
Блять, как работает эта ёбаная хуйня? Уже неделю не могу разобраться. Может кто-нибудь объяснить?
#include <stdio.h>
main()
{
int i;
//Проход по числам от 1 до 10
for (i = 1; i <=10; i++)
{
if ((i%2) == 1) //Остаток от деления нечетных чисел = 1
{
printf("От нечетных чисел одни неудобства…\n");
// Перескочить к началу новой итерации цикла
continue;
}
printf("То ли дело четные числа! \n");
}
return 0;
}
Далее приведен результат выполнения данной программы:
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
От нечетных чисел одни неудобства…
То ли дело четные числа!
тебя continue смущает что ли?
Внезапно никак. % это mod в паскале, | в апээле. Означет остаток от деления. Если совсем через жопу это значение последнего разряда при переводе в заданную систему счисления, тут двойка, значит последний бит.
i-(i/2)*2
А если задача не стать экспертом в C, а просто нормально понимать C, оставаясь в C++? 1000 страниц это явно не для меня уровень подробности.
Есть ли что-то лучше K&R?
> просто нормально понимать C, оставаясь в C++
Так глобальных-то отличий в общем синтаксисе не так много: навскидку, это отличия в linkage, менее строгая типизация указателей, пространства имен для struct/enum, void для функций с без аргументов. В основном тебе нужно лишь знать, каких крестовых фич в Си нет, а если что-то в Си есть, оно практически всегда есть и в крестах (кроме полутора исключений вроде designated initializers, которые завезут только в C++20 и нахуй не нужного в обоих языках _Generic). Если ты знаешь кресты, ты по умолчанию можешь нормально читать сишный код. Так что хуй знает, что тебе советовать.
> Есть ли что-то лучше K&R?
K&R слегка устарел, там нет C99/C11. С таким же успехом можно читать страуструпа бородатых годов, пролистывая страницы со словом class.
Я имею в виду подход к решению тех же задач, но средствами языка C. В C++, паче с STL порой бывает достаточно знать, какой заголовок включить и что вызвать, а там уже всё придумано до нас. В C придется как-то проявлять смекалку. Вот в какой литературе есть более-менее подробное описание практики современного С? Работы с памятью, например.
> можно ли её безопасно подсунуть как метод с другим числом аргументов
Тебе в соседний тред в общем-то, но да, можно подсунуть, на x86/x86-64 проблем быть не должно, если возвращаться не планируешь.
>на x86/x86-64 проблем быть не должно, если возвращаться не планируешь
Спасибо. А на других платформах? Мне не принципиально, но просто интересно.
>Тебе в соседний тред в общем-то
В какой? Если ты про спп, то - нет, я всё предпроцессором руками пока запиливаю.
> Спасибо. А на других платформах?
Все зависит от того, как ABI требует передавать аргументы, и кто прибирается в стеке, если стек используется и т. д. В целом, сам вызов должен сработать (call - это jmp на стероидах, а jmp сломать сложно). Вот возврат - тут уже все не так просто, даже между компиляторами под одну архитектуру соглашения о thiscall сильно различаются, и если тебе не повезет, все с высокой вероятностью свалится при возврате или вскоре после него.
> В какой?
Нет, не в крестовый, а скорее в ассемблерный >>1221420
>В целом, сам вызов должен сработать (call - это jmp на стероидах, а jmp сломать сложно).
Вот и ладушки, ты теня успокоил, тут возвращаться точно не требуется. Добра.
>Вот в какой литературе есть более-менее подробное описание практики современного С? Работы с памятью, например.
https://github.com/torvalds/linux
Короче, Кернигана и Ритчи буду читать. Я такой сделал вывод из ваших советов. Спасибо.
Наслушался советов зелёных и рад.
Читай Прата и Танненбаума в последних редакциях. КР советуют либо дегенраты-хелловодщики, либо васяны, которые детстве увлекались программированием на бейсике, а сейчас въёбывают на заводе ЧПУшниками.
Прата пугает уже объемом. Я же говорю, мне не нужно знать всё в C, мне нужно понимать те базовые вещи, которые попадаются в примерах, ведь C — язык номер 1 и примеры чаще всего на нем. Я уже знаю C++ и остается понять, как там работают все эти маллоки-каллоки и прочие чисто сишные штуковины. Зачем мне Прата на 1000 страниц.
Таннебаума не нашел — там же об операционных системах. Можно название книги?
Еще в шапке увидел такое Zed A. Shaw "Learn C the Hard Way" и соблазнился надписью «для гуманитариев», что в целом обо мне. Что скажешь об этой книге?
man malloc
>я уже знаю с++
>хочу узнать о выделении памяти
Ты ещё наверное думаешь, что то, что написано в популярных книгах это и есть "низкоуровневое программирование на си".
Хехмда, куда мы катимся, господа.
Но ведь я просто пишу драйвера, да и на заводе не работал никогда.
Почему сегфолтится, когда строка с calloc находится в функции new_line, а не в main?
Никаких предупреждений не выдаётся (gcc версия 7.3.0).
Собираю через gcc -Wall -std=c99 -pedantic -g test.c -o test
Я же не сказал, что знаю в совершенстве. Я в курсе, какой заголовок включать и какой шаблон STL юзать, чтобы решить нужные мне задачи. Но вот работу с памятью собираюсь изучить подробнее и думал, что православнее начать с обычного C, раз в куче объяснений от него отталкиваются. Не надо надо мной иронизировать. „Не надо надо“ прикольно звучит.
Просто скажите, в какой из книг это лучше всего объясняют, как новичку, без лишних дебрей.
K&R C
Только внимательно смотри на такие вещи как массив указателей, указатель на массив. А также адресную арифметику ((ptr + foo) это тоже что и ptr[foo]).
И блять научись именовать переменные уже. line что блять? Это массив указателей? Тогда lines. Или же это линейный буфер? Тогда у него тип корявый.
https://pastebin.com/rnjAzQFT
До меня дошло, что calloc меняет адрес указателя line, поэтому в функцию нужно передавать указатель на указатель.
Спасибо, эти кунштюки с array[2] = 2[array] знаю еще из C++.
А вот по части line и какого-то кода на pastebin, ты меня с кем-то путаешь. Я тут только о литературе спрашивал.
>Прата пугает уже объемом.
А я осилил. Там нет ничего лишнего. Более того, дополнить бы не мешало примерами работы с юникодом, сетью, потоками.
Хочу вкатиться, но понятия не имею, с чего начать.
Их существует дохрена, наверн.
Хочешь переносимости и прагм компилятору- учи OpenMP.
Хочешь традиций C и UNIX - учи pthreads.
Они взаимозаменяемы
> Они взаимозаменяемы
Каким местом? OMP - это параллелизация компилятором на основе аннотаций программиста, pthreads - это полностью ручной пердолинг со всем контролем.
>>22801
В C11 завезли стандартные потоки, с них и начни. Знать нужно и pthreads, и OMP, если хочешь писать что-то сложнее хелловорлдов.
Ну ладно, Прата так Прата.
Как его читать? Подряд, ничего не пропуская, или как справочник по нужным темам?
Анон, я понимаю, что разные механизмы.
Я в плане возможности решать на них одни и те же задачи на практике говорил.
Я ничего не пропускал и выполнял все упражнения. Потом с K&R проделал то же самое.
Никак. Не стоит инициализировать что-либо в хедере. В хедере ты делаешь extern struct mystruct foo;, в одном из файлов делаешь struct mystruct foo = { 0 }; и так как это не автоматическая переменная, компилятор сам инициализирует ее нулями.
ect ec;
int_big x,y,z;
Coord coord;
int_big mX,mY,mZ,mT;
alignas(32) uint64_t data[256];
uint64_t dp;
} test;
То есть мне эту структуру убрать в .c файл? Извини, я немногу тупой.
Хотел заполнять только нужные поля при создании экземпляра (то есть без "конструктора"), а массив чтоб был нулевым по умолчанию без всяких мемсетов. Но, видимо, так не получится. Хотя он и так нулевой, но это в дебаге, а валгринд ругается.
>А иницилизировать будут так: test x = { 0 }
Воу, а я не знал, что так можно было — без указания полей.
А нет, можно было, это я тупой. А что получается, все поля нулём инициализируются?
Меньше доверяй всякому говну. Так можно. Указываешь инициализатор первому элементу составного объекта, а все остальные инициализируются своими дефолтовыми значениями (0 для интов, 0.0 для флоатов и т. д.).
Понял, благодарю.
Почему вместо единичек и нулей выводит какую-то хуиту? Это он значение из ячейки памяти по адресу берёт что ли? Как заставить его воспринимать единицы и нули как обычное число?
Если начинается с 0, то трактует как восьмеричное число.
Если с 1, то как base10.
Двоичный ввод не предусмотрен.
Значит, мне нужно к каждому значению добавить единицу в начале? Или может тип на какой-нибудь другой заменить?
Да, это я хочу, спасибо. А в С++ можно ввести двоичное число без всяких бубнов или тоже придётся добавлять единичку в начале?
В C нельзя ввести двоичное число явно.
>А в С++ можно ввести двоичное число без всяких бубнов
Сейчас, да - 0b10100101, можно с разделителями разрядов 0b1010'01010'0011'1100
А про единицу ты там выше не допер.
Это ты ему какое-то GNU-расширение втираешь, или это новый стандарт какой?
Мог бы ещё в макрос обернуть функцию для перевода bin в dec.
Асло раньше не макросы с функциями использовали, а шаблоны для преобразования в компайл тайм
Не нервничай так, брат меньший.
sizeof (int) = 4
sizeof (*ptr) = 8.
Если адрес у меня 8 байт, следовательно машина у меня 64 битная, машинное слово вроде должно быть 8 байт, а int у меня 4.
Или int это не машинное слово?
Компилятор с чистой и даже не особо функцией от константного аргумента такое прокрутит ещё в компайл-тайм оптимизации ради, зашатаешься.
Как видишь, не машинное.
Не понимаю. Вот есть заданный массив int a[4][2][8], как заполнить все ячейки нулями без помощи циклов? Memset не подходит, он просто по указателю заполняет блок памяти без разделения на [4][2][8]
И что это за уебанская капча с постоянно появляющимися картинками, как вернуться на старую?
>он просто по указателю заполняет блок памяти
Дурачек, массив это и есть блок в памяти, `a` - это указатель считай. мимобогсишки
Спасибо
Придется проходиться двойным циклом по a[0...3][0...2] и делать memset a[j][0...8]. С чего ты взял что твой массив располагается в памяти одним куском и его можно зараз мемсетнуть?
Общепринятый способ − вводить в base16, потому что каждые 4 двоичные цифры это одна буква, и можно в голове переводить.
С того, что массивы в Си лежат одним куском и их можно за раз мемсетить.
>>23388
Нельзя. Требуется хотя бы один инициализатор.
>>23402
В первых тредах был срач, хардвей решено было оставить. В статье все правильно говорят, но есть нюанс в виде некоторых гуманитариев, которым только подобного рода книжки и заходят.
Так ты внимания на кресты не обращай.
Пошёл нахуй, «веб-программист».
Интернет написан на Си и крестах, а то что ты выдаешь за программирование — скриптописание и не более того.
Потому что если бы не титанические усилия байтоёбов, ваш медленный говнокод даже не завелся бы.
Ну и за программиста почти никакую вебмакаку нельзя считать.
Потому что эти "байтоебы" в основном студентота, только что осилившая компилируемый язык. У взрослых дяденеке бомбит в основном с подходов, а не с технологий (ну там - какими-то костыльными неповоротливыми инструментами качать непонятно откуда библиотеку, которая делает пятьюдесятью строками то, что без нее можно сделать двумя).
Платят мало
make_file_from_tree(search_tree head, char filename)
{
FILE out = fopen(filename, "w");
if(out == NULL){
perror("make_file_from_tree: Can`t open output file.");
}else{
void print_tree_node(FILE output, search_tree cur)
{
fprintf(f, "%s: %d\n", cur->key, cur->value)
}
visit_recursive(head, print_tree_node);
}
}
[/code]
Вот есть примерно такая залупа. Могу я в print_tree_node передать явно открытый FILE out, не передавая его в visit_recursive?
А ты не можешь переделать класс в структуру + совокупность функций для работы с ней?
char str1 = "String one"
char str2 = "String two"
почему со второй строкой я могу сделать так: str2[0] = str2[3] или (str) = *(str+3) а с перовй нет??
Ты написал бред. Хрен знает, что ты хотел спросить.
Ну хуй знает, как у тебя там visit_recursive реализовано, но нет, не можешь, замыкания только в следующем стандарте завезут. Стандартный подход для обхода чего-либо: три параметра, а не два. Второй - колбек, а третий - void *userdata, куда ты можешь передавать хоть черта в ступе.
Алсо, вложенные функции - это расширение гцц, хорошие ребята так не делают.
>>23896
Запости пример на ideone, но сразу напоминаю, что "строковые литералы" доступны только для чтения, и то, что у тебя почему-либо получается туда писать, не означает, что так делать можно.
Код:
#include <stdio.h>
#include <locale.h>
int main (void)
{
setlocale (LC_ALL, "Rus");
int i;
char string[20];
puts("Вводите строку");
fgets(string, 20, stdin);
fputs(string, stdout);
return 0;
}
Вывод:
Вводите строку
двачик помоги
¤ў зЁЄ ЇRR?Ё
Попробуй скажи ему -fexec-charset=866 (очень плохое решение, зато очень простое). Или -fexec-charset=utf-8 и chcp 65001 в консоли. А локаль можешь выкинуть. Вообще, с LC_ALL стоит поаккуратнее, чтобы не появлялось вопросов, почему это 1.23 из файла не читается.
Спасибо, -fexec-charset=866 помогло
А как мне тогда реализовать обход узлов дерева с выполнением для каждого узла функции? Чтобы можно было разные функции засовывать?
ptr_to_jmptable имеет тип char, то, например, байт 8b выглядит как надо при печати, а если тип моей структуры Byte, то печатается b8. Почему? Почему перестановка полей структуры делает все оки-доки?
Дело в порядке бит?
https://pastebin.com/an9SkACR
> си более переносим
Ну сам посуди:
#include "stdio.h"
int main(void)
{
printf("hello 2ch\n");
return 0;
}
Этот код валиден на юних системах, спермо системах и даже прыщах. Даже на ардуине.
И не дойдёт пока сам в этот чан с кодом не окунешься.
Расположение полей в структуре (от старшего бита к младшим или от младшего к старшим) зависит от компилятора.
>>24476
> язык си более переносим нежели бейсик или фортран
Это распространенное заблуждение. Бейсик более переносим. Любой сколько-нибудь сложный код прибит к платформе пачкой ифдефов. Тогда как код, выполняющийся на виртуальной машине (как бейсик) просто работает везде, где есть эта машина.
>>24481
> Стандарт языка
Совершенно необязателен. Для Си это нужно по всяким юридическим и техническим причинам.
> Стандарт языка программирования это то как должен работать язык?
Стандарт рассказывает, как должен работать сферический Си в вакууме. Ты можешь реализовывать свой компилятор как угодно. Единственная твоя задача - сделать так, чтобы наблюдаемое пользователем поведение не отличалось от того описанного Си в вакууме. Но если никто не сможет этого увидеть, ты можешь сколько угодно перечить стандарту.
> ритчи и томпсон изначально разработали стандарт
Нет, они сначала написали компилятор уродливого неюзабельного говна, а потом несколько лет его допиливали. Потом комитет по стандартизации тоже допиливал из говно, но уже на бумаге. То есть, использовались оба подхода. Но обычно сначала есть какие-то наброски, пишется компилятор, все проверяется на практике, а потом наброски оформляются в описание языка.
>>24485
Упс, freestanding environment не гарантирует наличие stdio.h на голом железе, как и вообще возможность что-либо куда-либо вывести.
>Линух как пример самой успешной Unix-ветки.
Че бля? Это архитектурное уебище, хуевая копипаста Миникса зделонная пьяным финсаим оленем, лол
I'd just like to interject for a moment. What you’re referring to as Linux, is in fact, GNU/Linux, or as I’ve recently taken to calling it, GNU plus Linux. Linux is not an operating system unto itself, but rather another free component of a fully functioning GNU system made useful by the GNU corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX.
Many computer users run a modified version of the GNU system every day, without realizing it. Through a peculiar turn of events, the version of GNU which is widely used today is often called “Linux”, and many of its users are not aware that it is basically the GNU system, developed by the GNU Project. There really is a Linux, and these people are using it, but it is just a part of the system they use.
Linux is the kernel: the program in the system that allocates the machine’s resources to the other programs that you run. The kernel is an essential part of an operating system, but useless by itself; it can only function in the context of a complete operating system. Linux is normally used in combination with the GNU operating system: the whole system is basically GNU with Linux added, or GNU/Linux. All the so-called “Linux” distributions are really distributions of GNU/Linux.
Расскажи подробнее про стандарты
Рэймонд может считать как угодно, но Linux — это рекурсивный акроним, который расшифровывается как линух это не юних.
Да-да, в APUE случайно мимоходом упомянули про Linux, а не разрабатывали все примеры, фокусируясь на работу в нём.
В вузиках препода UNIX-дисциплин используют Linux из лени и халатности, вот колясочники!
Ты дичь какую то поришь, на каникулах что ли?
Ты сейчас ещё больше охуеешь, возможно, но GNU - GNU's Not UNIX или LAME — LAME Ain't an MP3 Encoder. Такие дела.
Пруфа нет, ибо это народное творчество. Linux искаженная форма имени Линуса. Вроде как самим Линусом и придуманно. А откуда пошло линух не юникс... возможно из-за GNU. GNU/Linux.
здрасте, друзья, рекурсивно обхожу каталог и заполняю массив char именами файлов, возникла проблема с заполнением, наскок я понял она связана с тем, что несколько функций обращается к одному и тому же элементу массива, решил проблему заменив массив структурой из массива и полем int значащее размер элементов в массиве. Все ок но само решение какое-то некрасивое, есть другие варианты?
>Пруфа нет, ибо это народное творчество.
Вот и я об этом.
Раньше такой расшифровки не было, придумали (относительно) недавно, скорее всего.
Не берусь судить. Вполне возможно.
И нужны ли вообще дейтелы?
После Праты брать уже конкретные книги по разработке под интересующую платформу и там уже по ходу дела читать про хороший/плохой код, про алгоритмы/структуры данных и т. д.
Можно написать вручную, не очень сложно, но проще взять какой-нибудь flex, пусть компьютер сделает за тебя хотя бы половину работы.
Смешались в кучу кони, люди...
Что такое машинное слово? Что такое int?
>>23681
По-моему, всё-таки бомбит у веб-макак т.к. постоянно лезут сюда с подобными вопросами.
>>24451
Гугли littleendian и big-endian
>>24661
>придумали (относительно) недавно
Это старая рекурсия. Слышал в начале 2000-х где-то в русскоязычной литературе.
>>24610
А он и не эмулятор. Это реализация WinAPI под никсы, а не эмуляция выни.
>>24737
Сначала осиль Прата. Если пойдёт на пользу, то ты уже не будешь задавать таких вопросов антону.
Библиотеки содержат библиотечные ф-ции - это обертка над системными вызовами. Ну т.е. допустим есть у тебя printf() - это тупо обертка на сисколом write. Но только плюс еще есть буферизация, чтобы потсоянно не вызывать сискол, ибо это дорого для процессорного временя(смена контекста). Ну и плюс еще кроссплатформенность, ибо сисколы могут иметь разные номера на различных системах. Как-то так.
>Это старая рекурсия. Слышал в начале 2000-х где-то в русскоязычной литературе.
Перепутали с GNU, которое действительно GNU is Not Unix.
Линукс - это линус с X на конце, ну типа он юникс (конкретнее, порт minix с блекджеком и шлюхами) изначально хотел запиливать, тогда было модно в название UNIX-совместимых систем букву Х пихать чтобы всем понятно было..
> winapi
Здесь
> руссиновича
-> /fag/
> внутреннюю структуру винды
-> /re/ Обсуждают то, чего нет
Ну это как говорить, что OpenGL - обертка над putpixel. Между тем, printf() на самом деле обертка над fprintf(), который обычно использует общую для всего семейства функцию, форматирующую текст и по мере форматирования выводящую результат (в поток или буфер, в зависимости, и там все нихуя не просто. Зато можно делать так: https://github.com/HexHive/printbf твой write() так может?
Ага, а OpenGL ОДИН ХУЙ когда-нибудь рисует пиксел. Все, обертка!
И нет, printf может и не делать сискол. Например, у тебя embedded, и твоя реализация либц напрямую пишет в регистр UART. Или рисует текст на экране, вызывая не write(), а какой-нибудь blit_screen(). И это не говоря уже о http://man7.org/linux/man-pages/man3/fmemopen.3.html который в ядро (даже если оно есть) не ходит в принципе.
>Ну это как говорить, что OpenGL - обертка над putpixel
Ну не над putpixel, а, вместе с юзермодным драйвером и libdrm - обертка над ioctl.
Как же вы заебали.
> A wrapper function is a subroutine in a software library or a computer program whose main purpose is to call a second subroutine or a system call with little or no additional computation.
> (Википедия)
>Да что значит это слово то, пе-ре-но-си-мость?
>Не понимаю.
Программа без доработок работает на разных компьютерах с разной архитектурой CPU и разными операционными системами. Например - любая скриптопараша, начиная с бейсиков для восьмибитных компов 80х - более-менее переносима.
А как ты будешь делать какой-нибудь линкед-лист из структур, если не знаешь размер структуры?
Да. И на подавляющем большинстве машин char = byte = octet, поэтому никто не заморачивается и говорит про байты.
> char из 2 байт
Возможно сделать такой компилятор, но смысла в этом нет. Так что на практике и байт, и char - минимальный адресуемый юнит. И это скорее не
> байт из 5, 7, 10 бит.
а 16 или 32.
Телепаты в отпуске, лето же. Тащи код. Да, по идее, должно быть много строк. Может быть, у тебя где-то #ifdef в false развернулся? Может, ты другой файл смотришь?
Весь вопрос, где почитать, чтоб не как бы и о практичной интуиции — это, спасибо, знаю, а где это строжайше задается и где полномочия C, а где зависит от от чего зависит, кстати??
> typedef struct { ... } yoba;
вместо простого
> struct yoba { ... };
есть какая-то разница вообще?
https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/#toc-GCC-Command-Options
Подкинул, иди читай.
> Имеет ли смысл использовать -std=c89(99,11)
Очевидно, что если ты используешь недефолтную версию стандарта, ты ее указыаешь.
> правда ли они компилят по старому стандарту
Кто они?
>>26049
> есть какая-то разница вообще?
В Си (но не в C++) у тегов struct и enum отдельные пространства имен, не пересекающиеся с пространством имен типов. Если ты напишешь struct yoba, то и использовать в качестве имени типа сможешь только struct yoba myvar, но не yoba myvar. Чтобы поиметь последний вариант и не писать лишних кейвордов, делают typedef.
>В Си (но не в C++) у тегов struct и enum отдельные пространства имен, не пересекающиеся с пространством имен типов. Если ты напишешь struct yoba, то и использовать в качестве имени типа сможешь только struct yoba myvar, но не yoba myvar. Чтобы поиметь последний вариант и не писать лишних кейвордов, делают typedef.
Охуеть, спасибо.
Двачую. Вкатился только два месяца назад, до этого писал на крестах и джаве, в адовом восторге до сих пор.
И ничем не похожи
Поясните ньюфагу, как объявить define в одном хедере так чтобы он был виден в других хедерах?
Например:
defines.h
#define DEBUG
main.h
#ifdef DEBUG
#define A
#else
#define B
#endif
Сам спросил, сам и отвечу.
Не знаю насчёт правильности такого решения, но можно просто вписать в
main.h
#include "defines.h"
#ifdef DEBUG
#define A
#else
#define B
#endif
Спасибо, не увидел твоего ответа.
Ну я писал на плюсах для себя, как устроился на работу - писал на джаве. А следующий проект был на Си+АСМ, так что я недолго думая сказал, что готов, хотя был не готов.
В принципе, вкатился очень легко, не могу сказать, что мне действительно что-то мешало в плане программировании.
А вот недостаток математики чувствовался (и сейчас чувствуется, но уже полегче) очень сильно, так как отрасль связана с криптографией. Но меня в общем-то хвалят, значит справляюсь.
То количество бит, которое удобнее всего обрабатывать ALU. Поэтому регистры в процессоре обычно размером с машинное слово.
В данном случае u32 только для переносимости? Получается это просто флаг работает?в большинстве случаев
> В данном случае u32 только для переносимости?
Это от глупости. Во-первых, u32 намекает на 32 бита, хотя их там, конечно же, нет. Во-вторых, это наоборот ломает переносимость. Для битовых полей стандартом разрешены только bool и int (в том числе unsigned), возможность использовать что-то еще - implementation defined.
> Получается это просто флаг работает?
Да, обычно такое притаскивают ради флагов, для более читаемого кода, чтобы с масочками не ебаться.
Понятно, спасибо.
Нигде, сейчас нет кодировок, в котором отсутствую представленные триграфами символы. Ты можешь столкнуться с триграфами разве что в обфусцированных исходниках или при написании своего компилятора (и то, если ты вдруг про них забудешь - никто и не заметит).
В примерах \r\n не нужен. Если у тебя stdout/stderr или текстовый файл (открытый без флага "b"), то стандартная библиотека Си автоматически будет транслировать \n в \r\n, если платформа это требует (читай: Windows).
Вот если у тебя бинарные файлы, тогда для виндовых концов строк нужно будет явно писать \r\n. Или если у это велосипедный HTTP поверх голых сокетов, или просто CGI-скрипт, там тоже нужен явный \r\n.
> ILP32
32-битная машина. integer, long и pointer по 32 бита.
> LP64
64-битная машина. Просто взяли и договорились, что будет так. На 64-битных машинах бывает еще LLP64 (винда), с 64-битным long long и указателями, и 32-битными int/long.
Спасибо. Я знал, что эта аббревиатура просто должна быть хоть мало мальски осмысленной. ILP это удобно.
А что за странные штуки типа __m64, __m128, __m256? Где они вообще обитают и как используются?
> Где они вообще обитают и как используются?
Это типы данных для SIMD-интринсиклв (SSE,AVX). Сам гугли.
Нет, в линуксе лучше вариантов нет. Более того, узнать, что за браузер установлен, тоже будет непросто. Существуют еще всякие xdg-open и аналоги, но и их может не быть. Поэтому обычно путь к браузеру пишут в конфиг.
На си писал, но обычные программы. микроконтроллерами вообще не интересовался до настоящего момента.
Касательно stm32 есть reference и programming мануалы, а также книга с имеющимся русским переводом - "Ядро Cortex-M3 компании ARM. Полное руководство". Ну и плюс ютуб, хотя качество материала там говняное и с ошибками, хотя для хеллоуворлдов пойдёт.
У праты очень непонятно об этом написано(
>>1229147
Кажется, приблизился к разгадке, но нужен хелп.
Есть структура, к одному из полей которой применяется атрибут alignas(32).
Вычисляется размер этой структуры с учётом паддингов (если есть), после чего динамически аллоцируется память (malloc).
И тут получается какое-то совсем странное поведение. Размер посчитан с учётом паддингов, вызванных в том числе и атрибутом алайн, а значит выделенной памяти должно быть достаточно для алайна. Но выравнивания не происходит.
Если делаю allocated_alloc(32, х) вместо malloc(х), то получаю выравнивание всей структуры целиком. При этом, я так понимаю, никакой гарантии выравнивания конкретного поля не будет, верно? Какие тогда есть варианты решения?
Из простого я вижу allocated_alloc для структуры, а поле, для которого мне нужно выравнивание, поставить первым (хотя по стандарту гарантий нет, чтоб аллокация будет в порядке определения, но обычно так и происходит).
Из правилнього я вижу использование allocated_alloc непосредственно для нужного мне поля и присвоение ему полученного указателя, а не для всей структуры.
malloc() не помогает потому, что может возвращать память, выровненную на sizeof(double), чего явно не хватает для выравнивания твоего поля.
Пример:
struct foo {
int a; // Офсет 0 выравнивается по 4 (неявный alignas для int) = 0, размер 4.
alignas(32) char b; // Офсет 4 выравнивается по 32 = офсет 32, размер 1.
}; // Офсет 33 выравнивается по 32 = размер структуры 64.
Допустим, malloc() вернула нам адрес 0x00000008. 8 + offsetof(struct foo, b) = 8 + 32 = 40 = пиздец выравниванию. Вот если бы адрес начала структуры был кратен 32, то и адрес b из-за alignas(32) тоже был бы кратен 32.
Почему в примере размер структуры выраванивается до 32? Если бы этого не происходило, то следующая структура в массиве таких структур оказалась бы невыровненной, т.е., адрес следующей структуры не был бы кратен 32, поэтому не получилось бы удовлетворить требование о выравнивании b на 32. Для выравнивания размера берется максимальное необходимое выравнивание внутри структуры. В язык вместе с alignas добавили еще и alignof, и если его применять к структуре, он как раз и выдает выравнивание поля, которому требуется наибольшее выравнивание.
И если ты скормишь результат alingof(struct foo) = 32 в aligned_alloc, то тебе дадут адрес, кратный 32, что автоматически гарантирует тебе правильное выравнивание как b, так и других полей, которым требуется меньшее выравнивание (ведь то, что кратно 32, кратно и 4). Поэтому используй aligned_alloc с alignof, выставляй правильные alignas нужным полям структуры и не выделывайся, ничего никуда двигать не нужно, и отдельно выделять тоже не нужно.
> хотя по стандарту гарантий нет, чтоб аллокация будет в порядке определения
Есть гарантии. Нет гарантий, что между полями не будет паддинга. Например, между a и b в примере - 28 байт мусора.
>И если ты скормишь результат alingof(struct foo) = 32 в aligned_alloc, то тебе дадут адрес, кратный 32, что автоматически гарантирует тебе правильное выравнивание как b, так и других полей, которым требуется меньшее выравнивание (ведь то, что кратно 32, кратно и 4). Поэтому используй aligned_alloc с alignof, выставляй правильные alignas нужным полям структуры и не выделывайся, ничего никуда двигать не нужно, и отдельно выделять тоже не нужно.
Можешь перефразировать?
Ты о том, где 8 + 32? Ну так 8 - это адрес, который выдала malloc(), 32 - смещение поля от начала структуры (там в комментариях к структуре посчитано). Результат сложения - адрес поля. Пример не очень получился из-за того, что офсет с выравниванием совпадает.
>>29235
> Можешь перефразировать?
somestruct ∗ptr = aligned_alloc(alignof(∗ptr), sizeof(∗ptr)); и все будет ок.
>>29242
> Почему при выделении на стеке такой проблемы нет?
Потому что malloc() возвращает void ∗, и это внешняя функция из библиотеки, компилятор не может ей через астрал рассказать, что именно ты собрался туда класть - из параметров там только размер (собственно, поэтому aligned_alloc со вторым параметром и появился). Для malloc() есть лишь требование вернуть адрес достаточно выровненный для любого из встроенных типов т.е., фактически для double или long double, так как они самые требовательные). Если для тебя такого выравнивания недостаточно - тебе нужен aligned_alloc (или раньше, до aligned_alloc выделяли больше необходимого и "вручную" выравнивали указатель).
При размещении структуры на стеке компилятор знает, что кладешь ты именно структуру и знает ее выравнивание, поэтому он может напрямую сгенеририровать код, который делает после уменьшения указателя стека выравнивает его по alignof(структура). Вот если ты будешь делать alloca(), которая опять же знает только размер, у тебя возникнет точно такая же проблема, как и с malloc().
Превосходно, спасибо огромное.
А как быть в случае, если структура должна быть упакованной (без паддингов)? С той идеей, чтоб её размер был постоянный и можно было при инициализции делать assert(X == sizeof(struct)), где X был бы суммой всех sizeof полей (эта штуки считалась бы снаружи, где сама структура не видна, известно только о наличии некоего хэндла void*).
> А как быть в случае, если структура должна быть упакованной (без паддингов)?
Не совсем понятно, зачем. Без выравнивания крэши могут быть даже на интах, если у тебя арм какой-нибудь. alignas тебе не поможет, но обычно компиляторы умеют в #pragma pack, которая эффективно шлет нахуй все требования по выравниванию: и явные alignas, и неявные для всяких int и double. А стандартного ничего нет - alignas может только увеличивать требуемое выравнивание, но не уменьшать.
#pragma pack(push, 1)
struct foo {
char a;
alignas(32) int b;
};
#pragma pack(pop)
static_assert(sizeof(struct foo) == 5, "wrong structure size");
>Не совсем понятно, зачем.
Мне тоже.
Идея чувака была в том, что "снаружи" считается сумма полей в compile-time, это значения хранится в enum рядом с другими такими же для других структур.
А при инициализации структуры полученный void приводился к struct и его sizeof сравнивался со значением, хранящимся в enum. Это, насколько я понял, дополнительная дебажная гарантия того, что мы используем правильный контекст.
Но мне понадобилось использовать выравнивание, стукрутура получилась с паддингами и её размер перестал совпадать с суммой размеров полей.
А, вспомнил. Это ещё для того, чтоб можно было на стеке размещать структуру, не перевыделяя память наугад.
В итоге две идеи:
1. Компиляция в два этапа. Определяем структуру, считаем её sizeof на данной системе. Полученный результат подставляем в исходники для выделения блока памяти на стеке. С учётом этого компилим уже основной проект.
2. Предположение о каком-либо расширении gcc/стандарта, позволяющем выделять на стеке variable-length данные, честно обещая, что оно посчитается в compile-time.
Буферизованный ввод-вывод.
stdio тебе предоставляет.
http://man7.org/linux/man-pages/man3/setbuf.3.html
> дополнительная дебажная гарантия того, что мы используем правильный контекст.
Какая-то странная гарантия. Раз изменил структуру - правь enum тогда, зачем тебе упаковка?
Если очень хочется знать, что структура не поменялась, лучше понатыкать static_assert (будет проверять на стадии компиляции), сравнивающий sizeof структуры с константой, можно даже проверять offsetof каждого поля, чтобы еще более быть уверенным. Но правильнее всего будет комментарий в определении структуры, поясняющий, как именно принято ломать совместимость со старыми версиями структуры в данном случае.
> Предположение о каком-либо расширении gcc/стандарта, позволяющем выделять на стеке variable-length данные,
alloca() же. Только к чему тут это?
> Полученный результат подставляем в исходники для выделения блока памяти на стеке.
sizeof() и так compile-time (за исключением VLA), зачем что-то подствавлять? В общем, снова нихуя не понятно.
>как именно принято ломать совместимость со старыми версиями структуры в данном случае
Звучит забавно конечно.
>сравнивающий sizeof структуры с константой, можно даже проверять offsetof каждого поля
Да, об этом думал. В общем, хрен знает. Но спасибо тебе большое.
>alloca()
The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca() returns to its caller.
>when the function that called alloca() returns to its caller.
То есть именно так, а не при выходе из scope? Грустно как-то.
> То есть именно так, а не при выходе из scope? Грустно как-то
Компиляторы чаще всего не заморачиваются scope-ами, и выделяют стандартным прологом все автоматические переменные за раз (но бывает, что выделяют меньше и потом переиспользуют локальные переменные и даже аргументы под что-то другое). В любом случае, это стек, его не жалко.
Я прошу рекомендации: что почитать, чтобы вникнуть в основы сетевого программирования?
Сам не профи и с OSI и всякмими сокетами-портами на вы и шепотом, не знаю даже, как это тестить (ну типа, хеллоуворлд написать чтобы проверить поток вывода на экран — понятно, а с сетевыми штуками куда?) такие вот начальные данные. Нужно на первое время хотя бы поверхностное, но общее понимание что к чему. Какую литературу/видеолекции порекомендуете?
Stevens. UNIX Network programming
Вы пользуетесь аллокаторами?
Я тут пробовал поставить всякие dmalloc, tmalloc, jemalloc, но нихрена не получается, потому что у меня Windows. Пробовал через MinGW и MSYS2 — ничего не помогло.
У dmalloc выдает при запуске ./configure кучу ошибок типа Core Dumped, остальные вообще даже запускать скрипт конфигурации не хотят.
Есть какой-то способ поставить их под винду или, раз у меня шындовс, то всё, несудьба?
> Вы пользуетесь аллокаторами?
Да. Маллок из сишной стандартной либы, говорят, неплох. Расскажи, зачем тебе понадобился нестандартный? Поиграться? Поставь на виртуалку линукс, поиграйся и успокойся. Вот если ты странного хочешь, то boehm gc на винде работает. Только зачем?
Въехать в суть хочу. Там один дядька в шляпе показывал, как эти штуки помогают находить утечки памяти. Вот себе тоже думал, ща запилю, ан нет.
А boehm gc так умеет? Там еще какое-то замерение скорости он делал, короче, интересно. Значит, виртуалка? Какую посоветуешь?
> как эти штуки помогают находить утечки памяти
У белых людей существует gcc/clang -fsanitize=address,leak давно уже. Но на винде оно в leak не умеет, только в address. Зато на винде ты можешь перед завершением программы посмотреть неосвобожденные блоки банальным HeapWalk(GetProcessHeap(), ...), потому что malloc() в гцц и шланге пользуется стандартной виндовой кучей.
> А boehm gc так умеет?
Нет, это противоположное решение проблемы - автоматическая сборка мусора (с оговорками).
> Значит, виртуалка? Какую посоветуешь?
Дефолтный виртуалбокс. Ну или впску дешевую купи за бакс в месяц - GUI тебе не нужно, а поиграть с компилятором за глаза хватит.
Это копия, сохраненная 7 сентября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.