Это копия, сохраненная 12 декабря 2017 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ или http://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Классика от Отцов: http://www.cypress.com/file/56651/download
- Годное пособие для гуманитариев: http://web.archive.org/web/20160727235220/http://c.learncodethehardway.org/book/ (автор внезапно захотел денег)
- Немного примеров хорошего стиля: 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 умеет компилировать код в память и запускать его, что позволяет писать скрипты прямо на сишечке.
Что еще почитать:
Stephen Prata "C Primer Plus, 6th Edition" (2014)
Свежая знает про C89, C99, C11, описывает различия, объемная около тысячи страниц, годная хотя есть некоторые шероховатости, с вопросами, упражнениями и ответами. Читать после K&R или до.
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 помогает читать сложные сишные декларации.
Прошлые треды:
- №22: https://arhivach.org/thread/262491/
- №23: https://arhivach.org/thread/277223/
- №24: https://arhivach.org/thread/291766/
>>1075061
Не совсем так. Никто не мешает использовать ELF под винду или PE под линукс (я вот писал лоадер Mach-O под винду, никаких сложностей не возникло). Проблема в либах, но либы можно собрать под нужную ОС. А основная проблема в несовместимых системных вызовах, которые используют эти либы или исполняемые файлы напрямую. Если решить все проблемы, получится WINE (алсо, раньше был LINE еще) или тот же WSL.
>Проблема в либах, но либы можно собрать под нужную ОС
на 64 разные размеры типов в вин/лин. так что не совместимо будет бинарно.
или я хуйню несу - я не знаю.
Это все решается, хотя и не отменяет того факта, что все это - дикое извращение, требующее овердохуя работы. Ради ничего.
Во-первых, разных ABI.
Во-вторых, разное API syscall'ов ядра.
В-третьих, разный формат бинарников.
В-четвертых, разные либы.
В-пятых, разное окружение.
В общем, то все эти проблемы решаются платформо-независимым кодом, и кросс компилятором, например как тот же gcc под винду в виде MinGW.
Но тут если приложение использует GUI, то все становится намного сложнее и без использования кроссплатформенных фреймворков, типа Qt, GTK+ и т.п. не обойтись. Конечно разработчики, в основном конченые ебланы, и много программ делается без поддержки кросс-платформености, хотя могли бы делать кроссплатформенные, ведь это не так сложно.
Ну что сказать, ебанутая сфера, ебанутые люди.
>В-третьих, разный формат бинарников.
>В-четвертых, разные либы.
>В-пятых, разное окружение.
Уже вошло в (1) и (2), не?
Алсо, какие задачи решает С? Кругом только и слышно про кресты, Яву, питон, шарп. Где используют С?
я твою мамку использую в с позе.
Драйвера, модули ядра, обоссанные нии.
>Алсо, какие задачи решает С
Программирование микрококо и прочих встраиваемых систем.
>Какой учебник лучше всего?
Мне понравилась книга "Язык программирования C" Стивена Праты. По плюсам у него тоже для начала неплохая книга, на мой взгляд.
>Кругом только и слышно про кресты, Яву, питон, шарп.
Потому что под них задач гораздо больше, чем под это говно мамонта. Драйвера и ядра пишут намного реже, чем всё остальное, а программирование контроллеров сейчас многие расценивают как студентоподобные поделки на ардуино. Скоро и в контроллерах много где будут наверняка использоваться высокоуровневые языки типа того же питона, если ЖОСКИЙ РИАЛТАЙМ не нужен.
Мой тебе совет: как вкатишься в C, бери другой язык, подучи и пиздуй работать, иначе с этим говном ты так и будешь решать одни и те же задачи всё время в нии или в частной фирме, работающей на фсб/армию. Сколько знал людей, все ушли на высокий уровень как только смогли, получают в 2-2.5 раза больше меня и радуются, а я всё ещё сосу хуи и блюю от одной только мысли, что надо снова идти на работу и писать какое-то говно.
void function (int n) { n = 5; }, то значение n в main не поменяется.
Но если из main передается массив в функцию
void function2 (int mass[], int size) { mass[0] = 5; }, то соответствующее значение в массиве из main тоже меняется.
То есть для массивов обязательно нужно каждый раз в функции дублирующий массив создавать, чтобы можно было присваивать ему значения и он не менял бы при этом значения в main?
просто если ты хочешь массив передать в функцию, просто оберни в структуру и передай.
передача в функцию int mass[] равнозначна int mass, а mass[0] = 5 равнозначно (mass + 0) = 5
Бля забыл про макаку, сожрала звездочки.
>int mass[] равнозначна int(звездочка) mass, а mass[0] = 5 равнозначно (звездочка)(mass + 0) = 5
Как я понимаю, тут объявляется структура tagBITMAPFILEHEADER, потом описывается. Потом в создавая экземпляры этой структуры мне нужно будет указывать имя структуры как BITMAPFILEHEADER. Так зачем то, что подчеркнуто красной чертой?
И нахуя это вообще делать, если можно просто структуры с нужным именем объявить?
> Так зачем то, что подчеркнуто красной чертой
Это вопрос предпочтений, конвенции (и легаси еще слегка). В Microsoft считают, что PBITMAPIMAGEHEADER header выглядит лучше, чем BITMAPIMAGEHEADER *header.
Понятно.
То есть если я напишу
struct _mystruct {//} *mystruct;
А потом где нибудь сделают
mystruct _ptr;
То _ptr будет указателем на структуру?
но ты умалчиваешь. понятно желание, ведь объявление void a, b; это не void a, *b;
но какой же это конченный стиль, ворд, дворд - всё чаше думаю, что мы слишком запареваемся. просто пишем как есть. а вместо int пишем intptr или что-то типа того.
ах да, забыл заменить - блин, в этом что-то есть, в этом преодолении естественной фильтрации.
Это блять майрософт там писать не умеют нихера на С, как впрочем и на все остальном.
Писать typedef на структуры не желательно, если это не opaque объекты к полям которого не должен быть доступ из вне.
Ну блять в майрософт вообще все уебищно, даже эти капитал летерс в названиях - просто пиздец. еще и венгерская нотация, еще и ебанутые тайпдефы на инты. Короче неудивительно что винда такое говно.
> понятно желание
Нет. Ошибка с указателем, как у тебя, возникает, если ставить звездочку у типа, не понимая сути (духа, лол) объявлений в Си:
int∗ foo, bar; // Непонятно.
а если писать правильно, то никаких проблем не возникает:
int ∗foo, bar; // Сразу видно, что имеется в виду.
Ну а нормальные люди вообще не смешивают разнородные типы в одном объявлении:
int foo = 1, bar = 2; // Допустимо.
int ∗foo = NULL, bar = 2; // Говнокод.
WORD, DWORD нужен для того, чтобы можно было писать более менее платформонезависимый код в том смысле, что стандартные типы данных на разных платформах могут в принципе отличаться по размеру. И тогда вместо того, чтобы перелопачивать весь код, тебе в header файле достаточно typedef переписать и всё. Переписать 1 строку легче чем тысячи.
Да но как можно выбрать такие ебанутые имена, да еще и капитализированные? Почему нормальные люди в линуксе сделал все понятно u32 u64 i32 i64, а у этих блять WORD, DWORD это вообще какие типы signed unsigned как их складывать умножать делить? Этож просто пиздец. Рак мозга налицо.
> Писать typedef на структуры не желательно
Да ты охуел. Отдельный неймспейс для struct и enum - это костыль и косяк разработчиков, вызванный по большей части техническими ограничениями, а не желанием сделать именно так.
>хуйню сказал. платформа назначают размер типов, укладывающийся в стандарт - нет смысла уродовать язык.
Вот щас ты хуйню сказал. Т.к. long на 32 битной архитектуре равен 4 байта, а long на 64 битной 8 байт.
на 32 битной надо писать long long что получить 64 битный. Но с С99 есть замечательный хедер <stdint.h> в котором все тайпдефы на инты типа uint64_t и т.д
> Но с С99 есть замечательный хедер <stdint.h>
Этим хедером подавляющее количество людей пользоваться не умеет. Типы фиксированного размера нужно избегать, если они не нужны вот прям пиздец как (например, для type punning и упакованных структур), в stdint есть правильные типы least и fast, вот ими и стоит пользоваться.
> ещё раз пропуках.
что ты несёшь, у каждого типа есть минимальный размер - это хватает практически для всего. и твои угарные -наивные представления о типах, тоже, улыбают - как захотят на платформе так и сделают.
В линуксовом стайлгайде очень много всякой дури. Мне в любом случае, что со struct, что без название типа ничего не скажет, надо идти и смотреть на него. Какая мне нахуй разница, структура ли foo_t. Если это что-то целочисленное, мне стоит узнать лимиты, узнать о наличии знака, узнать о каких-то специальных значениях (типа -1). Если это структура, мне как бы неплохо знать ее поля. Если я все это знаю - кейворд не нужен. Если не знаю - кейворд не нужен.
>>1075480
> у каждого типа есть минимальный размер
Удачи в следующий раз при компиляции 16-битного кода, использующего int. И удачи разгребать говно после дебилов, которые считают, что Си обеспечивает переносимость, а не люди.
Ну использовать least и fast стоит только если ты пишешь пиздец кроссплатформенных код под максимальное число архитектур, да и то я думаю лучше под каждую архитектуру иметь свои типы, если ты действительно делаешь что-то такое.
>>1075480
Я хз что ты вообще несешь. Ты походу вообще не понимаешь что такое размер типа и какие это может вызвать проблемы и баги.
или я слишком много дунул, или мы просто не понимаем друг друга. на всякий случай - блин, секс, да, вот чего хочется. заебали вы все уже.
>Ты походу вообще не понимаешь что такое размер типа и какие это может вызвать проблемы и баги.
а махрасофтовская типизация что-то меняет? это ты - несёшь хуйню. нет такого кода, который может работать везде, люди берут типы и определяют для себя платформы - всё.
>Если это что-то целочисленное, мне стоит узнать лимиты, узнать о наличии знака, узнать о каких-то специальных значениях (типа -1).
Там все целочисленые типы определены для каждой архитектуры u8 u16 u32 u64 и т.п которые сами за себя говорят обо всем. А кейворд struct помогает четко разделить тайпдефы которые могут быть opaque типами аля typedef struct _my_type my_type и открытые структуры с полями.
Меняет то, что достаточно изменить 1 typedef, а не листать весь код и заменять каждый int
Нет, ты начал загонять что все разруливает стандарт, я говорю что нихуя он не разруливает, ты стал загонять что вообще похуй на размер типа мол платформе виднее какой размер использовать, я говорю что такой подход 100% приведет к тяжело излечимым багам а то и вовсе неработающей программе. Теперь ты решил мне доказать, что типа ты изначально имел в виду обратное, а я был не прав?
> махрасофтовская типизация что-то меняет?
В ней иногда есть смысл. Например, они однажды написали (когда еще не было uint32_t), что палитра в BMP - это массив DWORD, и ни одна сука, ни на какой разрядности процессора это уже не сломает - нужно будет изменить только тайпдеф дворда, а не все 50 метров Platform SDK.
>>1075492
> сами за себя говорят обо всем
Так сколько там бит в pid_t?
> четко разделить тайпдефы которые могут быть opaque типами
Покажи мне юзкейс, когда мне просто пиздец как нужно знать, opaque тип это или нормальная структура.
я просто курнул - я вот и потерял нить. не знаю зачем я эту вкалдку оставил открытой. но.
не, подожди. я всё равно считаю, что тебе почти никогда не нужны фиксированные типы, а если нет - то и не тыёбуйся, пусть платформа их определит.
а ошибки переносимости зачастую из за того, что в своё время не было модного типа intptr и все кастовали к тому, что у них на платформе эквивалентно.
>Так сколько там бит в pid_t?
Ты походу не понимаешь что такое opaque типы. pid_t как раз им и является, ты не должен знать сколько там бит и т.п это закрытый типа, с которым работает некоторый сет функций и только через них ты должен с ним обращаться, но никак не напрямую.
u64 это специальные тайпдефы на инты в названии которых заложен знак и разрядность независимо от платформы, ты знаешь что размер будет 64 байта хоть на x86_64 хоть на ARM хоть на sparc хоть на аллахе. И ты можешь с ними работать как с обычными интами.
> ты не должен знать сколько там бит
Ну охуеть теперь. А как мне pid процесса-то напечатать? Какой спецификатор в printf пихать? Это не структура, так что, я думаю, %lf подойдет.
> u64 это специальные тайпдефы на инты
Да-да, я уже понял, что они не осилили stdint. Такие-то стайлгайды.
> Ты походу не понимаешь что такое opaque типы
Это ты не помимаешь. Opaque-типы декларируются через incomplete структуры, чтобы в клиентском коде нельзя было объявить переменную этого типа и нельзя было прочитать что-то осмысленное. Со структурой такого типа можно работать только посредством фунций (методов), которые получают только указатель на тип. В реализации, естественно, есть определение структуры. Очевидно, что pid_t ни разу под такое не подходит: я могу объявить pid_t, могу читать pid_t, могу передавать в функции целочисленные литералы, скастованные (или нет) к pid_t.
Во-первых, я все это пересказал уже пару постов выше.
pid_t я немного не точно сказал, т.к. это относится к user space типу из ядра, чтобы была переносимость юзер кода. Linux kernel code style такое не запрещает, этот случай там описывается, и это единственный возможный вариант сделать платформонезависимый тип во вне.
Алсо, забыл добавить, что к таким типам арифметика в идеале не применима и ты не можешь им пользоваться как обычным интом, так что считай тип opaque.
Это знаешь как в OpenGL практически все возращаемые хендлеры имеют тип GLuint хотя полезной информации в себе не несут никакой для пользователя, и не понятно при чем тут uint, могли бы указатель возвращать на настоящий opaque тип, либо хотя бы не приписывать uint к типу, который только сбивает с толку. Но не все идеально в этом мире.
Таненбаум тебе коротко пояснит, всего на 2100 страниц. Да это коротенько совсем. Если углубляться, то лучше не считать страницы... нужно уже годами считать.
Что делаете, делитесь кодом, мыслями, проблемами?
Я вот уже неделю делаю CPU scheduler для одной реалтайм приложеху в юзер спейсе. Заебался че-то, сегодня вот потратил день на рефакторинг, разделения всего на модули и т.п. т.к. чето тупанул и хуярил сначала все в одном вайле и сам не заметил как он перевалил в 3к строк.
>Заебался че-то, сегодня вот потратил день на рефакторинг, разделения всего на модули и т
это то, чем я занимался последнюю неделю. а ещё тесты писал.
а я пишу какое-то говно. вон, тут спрашивал на тему курутин.
но сложно, не всегда код можно отделить друг от друга - я нарисовал схему, где одни подсистемы пользуются только такой-то частью структур и прочее...
(pk) (ph)
keya-+--> subcxt <------------2[cxt]
.---:----:-^ key(pck)
| | | ^ ^
| | '----> cxtins(pci)<-2[key]
| | |
| +--> substt <--:-------1[stt]
~ | .:---------1'2
[main] | .-----||-----------'
~ | | |'------1.
| +--> subper <-:-----1[per]
| | | |.------1'
| | | vvv------1[vrt]
| | .--:-> appins(pai)
| | +--:-> appcnt(pac)
| '--> subapp <------------2[app]
'---------^ '-^
>разделения всего на модули и т.п. т.к.
Как остановится? Я разделяю код на совсем уж мелкие объекты, чтобы было проще покрывать тестами пользуюсь cmocka. В итоге даже небольшой проект состоит из нескольких папочек. Иногда кажется, что нарушаю принцип KISS.
Плохо, когда слабо связанные функции находятся во всем этом, например после рефакторинга шедулера, у меня появились отдельные файлы для очереди, для профайлинга, для воркеров, файл с общими макросами и структурами, и главный файл с хедером в котором все это собрано в шедулер и в хедере торчат уже апи.
>>1076504
Разделяй по смыслу и по архитектурным особенностям приложения, выделяй общий код в отдельные файлы.
Я вообще не особый сторонник разработки через тестирование, ибо работал в одном проекте где на каждый пук надо было тесты писать и это пиздец как утомляло и замедляло разработку, очень сильно замедляло, ибо порой на простую функцию сделанную за пару часов, тебе нужно было писать несколько сложных тестов на которые у тебя мог уйти день, а потом могло оказаться что нет, нам эта функция не нужна, отменяйте там все. И спрашивается нахуя мы пишем тесты эти?
Вообще я считаю, хорошо спроектированное приложение, с хорошим дизайном, разделенное на модули, с обработкой ошибок и т.д. вообще не нуждается в тестах ( ну максимум в каких-то совсем общих ), ибо любую ошибку можно легко отследить, при таком раскладе, она останется локальна в каком-то модуле и по логам сразу всплывет. Ну и конечно уровень разработчиков если они пишут на С должен быть соответствующим, чтобы не допускать глупых ошибок.
> не нуждается в тестах
Двачую этого. Тесты нужны, если разработчик не до конца понимает, что делает (например, не кристально ясно видит алгоритм, не полностью знаком с API, пишет по-быстрому, чтобы успеть к дедлайнам и т. д.). К сожалению, сейчас почти весь код так и пишется.
>Тесты нужны, если разработчик не до конца понимает
Тесты нужны, если разработчик не работает в одиночку. Если я ковыряю чужой говнокод, мне проще добавить фичу/изменить что-то, а потом прогнать тесты, чтобы удостовериться, что я ничего не сломал.
Разработчик никогда не работает в одиночку. Ты сегодня и ты через месяц - два разных разработчика.
мимопроходил и охуел с обсуждения таких пубертатных тем в си-треде. сосака, хуле
>говнокод
Ключевое слово.
>>1076663
>Ты сегодня и ты через месяц - два разных разработчика.
Вот этот прав. Поэтому в хороших проектах, особенно опенсорсных, придерживаются жесткого код стайла. Чтоб новички только начавшие заниматься проектом, как можно быстрее в этом разобрались и чтоб старые разрабы не запутывались в своих поделиях.
Время потраченное на поддержку хорошего код стайла и дизайна в проекте, намного меньше чем написание говнотестам к ковнокоду, в котором никому не охото разбираться.
> Если я ковыряю чужой говнокод, мне проще добавить фичу/изменить что-то, а потом прогнать тесты
Ну так и я о том же. Ты не понимаешь, как кусок твоего кода взаимодействует с чужим, поэтому надеешься на тесты вместо того, чтобы писать качественно.
мне он нужен чисто как дополнение к питону для повышения быстродействия. видимо все же придётся, жаль пока нет библиотек для интеграции Go в питон
Изучи строение компьютера.
Примитивные процессорные комманды, типа движение байт влево-вправо, двоично посклатывай\вычитай в уме.
Адресное пространство. Регистры. Как выполняется программа на ассемблере, в каком порядке.
Ну всё вроде.
void func(int arr[], int n);
и
void func(int n, int arr[n]);
>пространств имён, перегрузок
вырпботать стиль именования фанкций, обычно префикс служит как пространство имени. но если ты будешь хуярить ооп на си, заворачивая например указатели на функции в структуры, то ты нахуй съезжать с плюсов?
>она останется локальна в каком-то модуле и по логам сразу всплывет
Что теперь весь стек в лог переписывать или в каждую процедуру отдельную пихать систему логирования и обработки ошибок? И как потом использовать такие процедуры в других проектах, выковыривать всю эту систему логирования и обработки ошибок?
> чем кардинально отличаются прототипы функций
Ничем. Когда Си видит массив в выражении или в формальных параметрах функции, он неявно преобразовывает массив к указателю на его первый элемент. Следующие объявления эквивалентны:
void func(int n, int ∗arr);
void func(int n, int arr[]);
void func(int n, int arr[100]);
void func(int n, int arr[n]);
void func(int n, int arr[∗]);
Последние два объявления используют (и соответственно требуют поддержки компилятором) VLA. Но из-за преобразования массива к указателю никаких VLA там не остается, и прототипы становятся совместимы с предыдущими. Вот если бы у тебя было два и более измерения, тогда вариант с VLA отличался бы типом.
читаешь в буфер по 4ре байта и ксоришь?
double (звездочка)x = malloc(50*sizeof(double));
int size = sizeof(x) / sizeof(double);
Так нафига при передачи указателя в функцию мы пишем
int f(double (звездочка)x, int size_x)
?
> верно ли, что что указатель "знает" свой размер
Нет. Указатель знает свой размер, но не размер объекта, на который он указывает. Указатель тупо содержит адрес области памяти (смещение до первого байта объекта в адресном пространстве), не больше. Даже информация о типе существует только во время компиляции.
Значение size во второй строке не имеет смысла и зависит от платформы. sizeof(x) равен размеру самого указателя x - ну, например, 4 на x86, а sizeof(double) будет, например, 8.
Тогда немного не понял, чего хочет препод (строкой выше в коде был объявлен массив LIST_OF_PLANETS):
> const unsigned LEN_LIST_OF_PLANETS = 11;
> можно так: sizeof(LIST_OF_PLANETS) / sizeof(LIST_OF_PLANETS[0])
> и не придётся следить за соответствием массива и его размера.
Алсо, почему так получается, что мы никак не можем узнать количество выделенной памяти, а free, получая указатель на нулевой элемент, очищает память? Ведь получается, free точно знает количество выделенной памяти.
Ключевое слово - массив. Если у тебя именно массив, то компилятор знает его размер (или знает, где его взять в рантайме в случае с VLA):
int foo[10]; printf("%zu\n", sizeof(foo) / sizeof(foo[0]));
напечатает 10, потому что первый sizeof вернет размер массива в байтах, а второй - размер элемента. Делим, получаем количество элементов. Это работает. А вот:
int ∗foo = whatever; printf("%zu\n", sizeof(foo) / sizeof(foo[0]));
уже не будет работать, как ожидается. Этот вариант - очень частая ошибка (особенно если делают #define countof(array) (sizeof(array) / sizeof(array)[0]) и случайно скармливают ему указатель). Поэтому у компилятора обычно можно включить предупреждение о попытке сделать sizeof(указатель).
> Ведь получается, free точно знает количество выделенной памяти
Да, malloc(), выделяя память, в том или ином виде запоминает размер блока (или указатель на следующее за ним свободное место, или используются иные способы). free() знает, как в данном конкретном аллокаторе хранятся размеры, поэтому может освободить память. Стандартного и доступного программисту способа узнать, сколько было выделено, не существует, но в зависимости от используемой стандартной библиотеки есть всякие расширения типа malloc_usable_size и прочих _msize() (может вернуть значение слегка больше того, что ты передавал в malloc). Но лучше не закладывайся на нестандартные фичи и храни размер сам, если он динамический.
Благодарю.
#define int long long int
Кодеблокс.
clion
какого хуя если не указывать celsius в printf, он всё равно выводится после табуляции? как блять? компилирую gcc из терминала
#include <stdio.h>
int main()
{
int fahr;
int celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
while (fahr <= upper) {
celsius = 5 * (fahr - 32) / 9;
printf("%d\t%d\n", fahr);
fahr = fahr + step;
}
}
Так блять.
Во-первых, указывай -Wall -Wextra, особенно пока учишь язык.
Во-вторых, это неопределенное поведение (баг), не делай так. В другими ключами компиляции или в другую фазу луны будет выводиться другое значение.
В-третьих, суть спецэффекта в том, что printf просто читает аргументы последовательно, начиная с какой-то локации в стеке. Рядом с аргументами лежат и локальные переменные функции. И если ты указываешь меньше аргументов, чем нужно, то у некоторых функций типа printf появляется шанс прочитать локальную или какую-то временную переменную вместо аргумента.
интересно, спасибо!
Потому что Си можно объяснить нормальному человеку на нормальном уровне за полгода и выучить качественно года за два. А кресты во много раз сложнее, и хорошо его знают очень немногие.
Ты можешь читать хоть на китайском, но имей в виду, что большого количества документации и статей на русском не существует вообще. Привыкать читать на английском понемногу с самого начала или скрипеть зубами, когда припрет - дело твое. На самом деле, технический английский очень простой же.
Ок, буду стараться, с художественным так-то проблем нету, но вот технический открываю, прочитаю страницу и хочется закрыть уже
Пиздёж какой-то, технический буквально на порядок легче.
Огромное спасибо, теперь я хоть понял как работать с многомерными массивами разных размеров, а то до этого ебался с массивами.
>Во-первых, указывай -Wall -Wextra, особенно пока учишь язык.
Вместе с -Wall -Wextra надо ещё -Werror добавлять.
> -Werror
Чушь. Если у тебя стремление анально ублажить компилятор, ты, наверное, и в жизни так поступаешь? Не все ворнинги одинаково полезны. Они на то и ворнинги, а не ошибки. Они призывают обратить внимание. Особо ебнутые ворнинги вообще нужно затыкать. В качестве отличного примера можно привести высер столмана -Wdate-time.
>>1078750
> -ansi
Фу таким быть. 2017 год подходит к концу.
Ты не прав. Ворнинги на то и ворнинги, что чтоб предупреждать об отклонении от правил языка и потенциальных ошибках. Если ты затыкаешь ворнинги, думаю твоя программа упадет в один прекрасный момент. Я всегда пишут со всеми включенными ворнингами, кроме иногда -Wpedantic. Если в моей программе появляется ворнинг, то я его сразу пытаюсь устранить пересмотром кода.
Меня это очень много раз спасало от ошибок и багов.
А -Werror не плохая идея, ибо в большом проекте можно и не заметить за кучей вывода ворнинг. Да и при рекомпиляции они затухают и можно забыть о их существовании и ускать баги в другом месте, когда ворнинг чекто указывает туда.
-ansi конечно я сам не использую, ибо сложно отказаться от вкусностей С99, но для обучения С отлично подойдет.
Удваиваю этого. Когда пишу по AVR всегда правлю все ворнинги. Потому что обычно то, что считается ворнингами довольно критично при работе самой программы, особенно если там сорт оф байтоёбство.
Ты забыл ответить, чем __DATE__ отклоняется от правил языка, и какие потенциальные ошибки привносит.
Ты забыл рассказать новичку, что из-за твоего -Werror у него не будет компилироваться добрая половина примеров. А как исправить причину, он может пока и не знать.
Ворнинги - это способ, которым автор (или авторы) компиляторы говорят, что конкретно им что-то не нравится (есть ворнинги, которые требуются по стандарту, и они обычно адекватные). Это не всегда имеет отношение к языку, это всего лишь личные предпочтения. И чаще всего это ломает чьи-то привычки и хуже того, ломает чей-то работающий и не имеющий проблем код.
Например, по мне if (fp = fopen(...)) вполне нормальный код (стандарт языка со мной согласен), я не помню ни одного раза, когда я бы перепутал = и ==, но разработчики из GCC считают иначе, и из-за них я не могу так писать. Еще они не любят неиспользуемые аргументы, и мне приходится либо ублажать компилятор и замусоривать код всякими UNREFERENCED_PARAMETER(), либо не использовать Windows API, наполненный колбеками, в которых половина аргументов чаще всего нахуй не нужна. Еще в GCC много лет не было никаких предупреждений на тему "забытого" break в switch, но затем они изменили свое мнение, и вот, наконец, в GCC 7 у нас есть -Wimplicit-fallthrough, причем переносимого способа ублажить компилятор на этот раз вообще не существует (атрибуты появятся только в C2x). Охуенный подарок мейнтейнерам тех дистрибутивов, в которых кто-то, подобный тебе решил, что сборка пакетов с -Werror - это замечательная идея. Ну и, например, разработчики шланга не любят definition внешней функции без предварительного declaration, поэтому даже в проекте из двух .c-файлов нужны хедеры или бесполезные объявления.
> особенно если там сорт оф байтоёбство
foo = bar + 127 | 1;
> SUGGEST PARENTHESES AROUND ARITHMETIC
> МЫ НИПОМНИМ ПРЕОРИТЕТАВ, НАМ НИПРИЯТНА!!1111
А что с __DATE__ то не так?
>If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
>Ворнинги - это способ, которым автор (или авторы) компиляторы говорят, что конкретно им что-то не нравится
Опять ты не прав.
Даже тот же педантик
>-Wpedantic
>-pedantic
>Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
> if (fp = fopen(...)) вполне нормальный код
А по мне это потенциально опасный код и плохой code style ибо заставляет задумываться, что там имелось ввиду, сравнение или присвоение.
> Еще они не любят неиспользуемые аргументы, и мне приходится либо ублажать компилятор и замусоривать код всякими UNREFERENCED_PARAMETER()
Вот это очень полезный ворнинг, предупреждающий многие баги. Меня лично сотни раз спасал от неинициализированных переменных и т.п. Особенно когда делаешь рефакторинг, можешь запросто удалить часть кода и забыть исправить логику.
>не использовать Windows API
Это очень хорошая идея. А лучше вообще не использовать Windows.
>наполненный колбеками, в которых половина аргументов чаще всего нахуй не нужна
Так, чего ты хотел от говнокода сделанного в майкрософте, где 95% разработчиков индусы.
>есть -Wimplicit-fallthrough, причем переносимого способа ублажить компилятор на этот раз вообще не существуе
Тоже полезная вещь, ибо очень легко забыть поставить break после case и долго не понимать почему твоя программа работает по другой логике, если вообще работает.
Алсо, любой ворнинг можно отключить через Wno-{warning_name}.
>сборка пакетов с -Werror
Так никто не собирает с -Werror пакеты, -Werror должно стоять у разработчиков, а у пользователей кто собирает нет, ибо вероятность появления ворнинга на друглой платформе или компиляторе большая из-за разности стандартов и т.п. но если разработчики делают, что-то что вызывает ворнинги, значит сами виноваты и это на их совести.
Вот например скажи мне почему ядро линукс, собирается без ворнингов на любом поддерживаемом gcc? При том они там успользуют С99 c GNU расширениями, а не -ansi.
А что с __DATE__ то не так?
>If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
>Ворнинги - это способ, которым автор (или авторы) компиляторы говорят, что конкретно им что-то не нравится
Опять ты не прав.
Даже тот же педантик
>-Wpedantic
>-pedantic
>Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
> if (fp = fopen(...)) вполне нормальный код
А по мне это потенциально опасный код и плохой code style ибо заставляет задумываться, что там имелось ввиду, сравнение или присвоение.
> Еще они не любят неиспользуемые аргументы, и мне приходится либо ублажать компилятор и замусоривать код всякими UNREFERENCED_PARAMETER()
Вот это очень полезный ворнинг, предупреждающий многие баги. Меня лично сотни раз спасал от неинициализированных переменных и т.п. Особенно когда делаешь рефакторинг, можешь запросто удалить часть кода и забыть исправить логику.
>не использовать Windows API
Это очень хорошая идея. А лучше вообще не использовать Windows.
>наполненный колбеками, в которых половина аргументов чаще всего нахуй не нужна
Так, чего ты хотел от говнокода сделанного в майкрософте, где 95% разработчиков индусы.
>есть -Wimplicit-fallthrough, причем переносимого способа ублажить компилятор на этот раз вообще не существуе
Тоже полезная вещь, ибо очень легко забыть поставить break после case и долго не понимать почему твоя программа работает по другой логике, если вообще работает.
Алсо, любой ворнинг можно отключить через Wno-{warning_name}.
>сборка пакетов с -Werror
Так никто не собирает с -Werror пакеты, -Werror должно стоять у разработчиков, а у пользователей кто собирает нет, ибо вероятность появления ворнинга на друглой платформе или компиляторе большая из-за разности стандартов и т.п. но если разработчики делают, что-то что вызывает ворнинги, значит сами виноваты и это на их совести.
Вот например скажи мне почему ядро линукс, собирается без ворнингов на любом поддерживаемом gcc? При том они там успользуют С99 c GNU расширениями, а не -ansi.
> __DATE__ will expand to "??? ?? ????".
Да, есть такое. И часто ты видел компы без RTC, которые дату не знают, но при этом на них собирается код на Си? Но ты, видимо, не в теме. Ворнинг, про который я говорил - безусловный, просто из-за факта использования __DATE__ или __TIME__, просто потому что сталману захотелось воспроизводимые сборки, а биндиффы он не осилил.
> заставляет задумываться
А меня заставляет задумываться математика в DSP. Иногда очень надолго. Давай сделаем ворнинг -Wой-сложна? Или лучше -Werror-ой-сложна?
> от неинициализированных переменных
Про неинициализированные переменные - отличный ворнинг, и стандартный к тому же. Но он не имеет отношения к неиспользуемым параметрам.
> лучше вообще не использовать Windows
Лол, чего еще я мог ожидать.
> Так, чего ты хотел от говнокода сделанного в майкрософт
Я сомневаюсь, что там был хотя бы один индус, когда дизайнился Windows API. Ну да похуй. Поговорим про sigfunc_t и ее параметр? Про кучу 3rd-party кода, который тоже не сделан в майкрософте, а колбеки использует?
> -Wimplicit-fallthrough
> Тоже полезная вещь
Согласен. Очень полезная. Только в стандарте такого нет, а код сломался.
> можно отключить через Wno-{warning_name}
Можно. Только это не спасет от тех, кто будет собирать с -Werror и вопить, что у него не компилируется. Поэтому приходится городить полстраницы всяких #pragma GCC diagnostic ignored и аналогов в ифдефах для каждого компилятора. Но и это не спасает от внезапно появивишегося -Wой-сложна.
> Так никто не собирает с -Werror пакеты
А ты думаешь, я на пустом месте бугурчу? Нет, собирают. Ближайший пример - арч, в котором пару лет назад внезапно перестали не собираться дрова, использовавшие __DATE__. Хотя чего это я... арч же.
> Вот например скажи мне почему ядро линукс
Тебе принести вопли Торвальдса про strict aliasing, или сам найдешь? Ядро собирается без ворнингов, потому что они сосут GCC, при выходе нового GCC досасывают недостающее, а в тех редких случаях, когда не сосут, указывают ключиками, что они умнее. Лучше ты мне скажи, почему ядро линукс более никаким компилятором не собирается, и как после всего этого без смеха слушать про переносимость линукса и Си?
> __DATE__ will expand to "??? ?? ????".
Да, есть такое. И часто ты видел компы без RTC, которые дату не знают, но при этом на них собирается код на Си? Но ты, видимо, не в теме. Ворнинг, про который я говорил - безусловный, просто из-за факта использования __DATE__ или __TIME__, просто потому что сталману захотелось воспроизводимые сборки, а биндиффы он не осилил.
> заставляет задумываться
А меня заставляет задумываться математика в DSP. Иногда очень надолго. Давай сделаем ворнинг -Wой-сложна? Или лучше -Werror-ой-сложна?
> от неинициализированных переменных
Про неинициализированные переменные - отличный ворнинг, и стандартный к тому же. Но он не имеет отношения к неиспользуемым параметрам.
> лучше вообще не использовать Windows
Лол, чего еще я мог ожидать.
> Так, чего ты хотел от говнокода сделанного в майкрософт
Я сомневаюсь, что там был хотя бы один индус, когда дизайнился Windows API. Ну да похуй. Поговорим про sigfunc_t и ее параметр? Про кучу 3rd-party кода, который тоже не сделан в майкрософте, а колбеки использует?
> -Wimplicit-fallthrough
> Тоже полезная вещь
Согласен. Очень полезная. Только в стандарте такого нет, а код сломался.
> можно отключить через Wno-{warning_name}
Можно. Только это не спасет от тех, кто будет собирать с -Werror и вопить, что у него не компилируется. Поэтому приходится городить полстраницы всяких #pragma GCC diagnostic ignored и аналогов в ифдефах для каждого компилятора. Но и это не спасает от внезапно появивишегося -Wой-сложна.
> Так никто не собирает с -Werror пакеты
А ты думаешь, я на пустом месте бугурчу? Нет, собирают. Ближайший пример - арч, в котором пару лет назад внезапно перестали не собираться дрова, использовавшие __DATE__. Хотя чего это я... арч же.
> Вот например скажи мне почему ядро линукс
Тебе принести вопли Торвальдса про strict aliasing, или сам найдешь? Ядро собирается без ворнингов, потому что они сосут GCC, при выходе нового GCC досасывают недостающее, а в тех редких случаях, когда не сосут, указывают ключиками, что они умнее. Лучше ты мне скажи, почему ядро линукс более никаким компилятором не собирается, и как после всего этого без смеха слушать про переносимость линукса и Си?
>в которых половина аргументов чаще всего нахуй
К примеру? Там вроде всегда один и тот же набор аргументов более менее. Хендл объекта ядра, какие нибудь смещение битовое, парочку текстовых строк, какой нибудь флаг и может быть зарезервированное слово какое нибудь.
Convert.ToInt32(t2.Text) = Convert.ToInt32(t1.Text) % Convert.ToInt32(t2.Text);
Почему выдаёт ошибку:
the left-hand side of an assignment must be a variable a property or an indexer
> безусловный, просто из-за факта использования __DATE__ или __TIME__
Что-то я не пойму о чем ты. Никаких ворнингов нет.
>printf("%s", __DATE__);
gcc 7.2.0 -Wall -Wextra
Может ты себя накручиваешь просто?
>А меня заставляет задумываться математика в DSP.
Так конструктивно есть что сказать? Без иронизирования моих аргументов с целью увильнуть от объективного рассуждения.
>Про неинициализированные переменные - отличный ворнинг
Есть но он не может угадывать, как в твоем коде что может инициализироваться. Например, например ты забыл заполнить поле структуры из входящего аргумента, но тот ворнинг тебе ничего не скажет ибо та структура была инициализорованна, а вот на счет неиспользованного параметра ругнется.
>код сломался
Так опять же, никто не заставляет тебя в релиз билды в параметрах конфигурации пихать -Werror.
>Ближайший пример - арч
Слушай я сам на арче сижу уже несколько лет, до этого сидел на генту.
Но ты в курсе же что арч это бинарный дистрибутив и пакеты уже собраные устанавливаются., а то что лежит в AUR за это не несут никакую ответственность сами разработчики арча. Да и потом, переодически что-нибудь ставлю из AUR и очень редко в популярных пакетах не от Васяна, возникают какие-либо проблемы. Чаще всего проблемы возникают из-за того что меинтейнеры этих пакетов просто перестают их поддерживать и обновлять.
>strict aliasing
Так при чем здесь алиасинг и ворнинги? Алисинг серьезная вещь, которая может заставить проект вообще не работать. Тем более в гцц есть же атрибут для указания алиасинга.
> Ядро собирается без ворнингов, потому что они сосут GCC, при выходе нового GCC досасывают недостающее, а в тех редких случаях, когда не сосут, указывают ключиками, что они умнее
Тут я не особо понял, что ты имеешь ввиду. Да они кооперируются с разработчиками гцц, потмоу что ядро требует особого подхода во многих вещах, которых нету в стандарте, но это проблемы стандарта, а не кого либо из них.
>ядро линукс более никаким компилятором не собирается, и как после всего этого без смеха слушать про переносимость линукса и Си
Слушай братишка, это откровенная ложь , я лично сам собирал полностью ядро со всеми драйвера и т.п. интеловским компилятором. Да и цланг там вроде допиливают, по крайней мере видел в сорцах хедеры специально для цланга типа compiler-clang.h. Вопрос в том, какие еще компиляторы тебе нужны и какие реально существуют, а не заброшенны пару десятков лет назад? На сегодняшний день 3 основный компилера это GCC, Clang и Intel, другими в основном никто уже и не пользуется, даже майкрософт поняла что их компилятор говно и перешла на цланг.
> безусловный, просто из-за факта использования __DATE__ или __TIME__
Что-то я не пойму о чем ты. Никаких ворнингов нет.
>printf("%s", __DATE__);
gcc 7.2.0 -Wall -Wextra
Может ты себя накручиваешь просто?
>А меня заставляет задумываться математика в DSP.
Так конструктивно есть что сказать? Без иронизирования моих аргументов с целью увильнуть от объективного рассуждения.
>Про неинициализированные переменные - отличный ворнинг
Есть но он не может угадывать, как в твоем коде что может инициализироваться. Например, например ты забыл заполнить поле структуры из входящего аргумента, но тот ворнинг тебе ничего не скажет ибо та структура была инициализорованна, а вот на счет неиспользованного параметра ругнется.
>код сломался
Так опять же, никто не заставляет тебя в релиз билды в параметрах конфигурации пихать -Werror.
>Ближайший пример - арч
Слушай я сам на арче сижу уже несколько лет, до этого сидел на генту.
Но ты в курсе же что арч это бинарный дистрибутив и пакеты уже собраные устанавливаются., а то что лежит в AUR за это не несут никакую ответственность сами разработчики арча. Да и потом, переодически что-нибудь ставлю из AUR и очень редко в популярных пакетах не от Васяна, возникают какие-либо проблемы. Чаще всего проблемы возникают из-за того что меинтейнеры этих пакетов просто перестают их поддерживать и обновлять.
>strict aliasing
Так при чем здесь алиасинг и ворнинги? Алисинг серьезная вещь, которая может заставить проект вообще не работать. Тем более в гцц есть же атрибут для указания алиасинга.
> Ядро собирается без ворнингов, потому что они сосут GCC, при выходе нового GCC досасывают недостающее, а в тех редких случаях, когда не сосут, указывают ключиками, что они умнее
Тут я не особо понял, что ты имеешь ввиду. Да они кооперируются с разработчиками гцц, потмоу что ядро требует особого подхода во многих вещах, которых нету в стандарте, но это проблемы стандарта, а не кого либо из них.
>ядро линукс более никаким компилятором не собирается, и как после всего этого без смеха слушать про переносимость линукса и Си
Слушай братишка, это откровенная ложь , я лично сам собирал полностью ядро со всеми драйвера и т.п. интеловским компилятором. Да и цланг там вроде допиливают, по крайней мере видел в сорцах хедеры специально для цланга типа compiler-clang.h. Вопрос в том, какие еще компиляторы тебе нужны и какие реально существуют, а не заброшенны пару десятков лет назад? На сегодняшний день 3 основный компилера это GCC, Clang и Intel, другими в основном никто уже и не пользуется, даже майкрософт поняла что их компилятор говно и перешла на цланг.
Твоё Convert.ToInt32(t1.Text) % Convert.ToInt32(t2.Text);
Должно куда-то записываться. А ты его пытаешься запихнуть в Convert.ToInt32(t2.Text)
У тебя там должно быть что-то вроде
t2.Text(Сonvert.ToInt32(t1.Text) % Convert.ToInt32(t2.Text)) = Convert.ToInt32(t1.Text) % Convert.ToInt32(t2.Text);
ой лол
t2.Text(Сonvert.ToInt32(t1.Text) % Convert.ToInt32(t2.Text));
Вот так конечно же. Забыл удалить твой код
ебать ты наложница компилятора.
калят ворнинги по & я что даун который не может запомнить таблицу приоритетов?
>Лучше ты мне скажи, почему ядро линукс более никаким компилятором не собирается, и как после всего этого без смеха слушать про переносимость линукса и Си?
так это на самом деле нормально, хотя-бы исходя из того, что платформа (ос) определяет размеры типов.
> Там вроде всегда один и тот же набор аргументов
Например, я сделал SetTimer с колбеком. Аргументы колбека: hwnd, uMsg, idEvent, dwTime. Главное окно одно, сообщение всегда WM_TIMER, таймер один, время нужно редко. Итого, колбек может не прочитать ни одного аргумента. Или, например, во многих функциях Enum и им подобных может интересовать только какой-то один аргумент. Вообще, навскидку сложно вспомнить, но ублажать компилятор на эту тему требуется достаточно часто.
>>1078877
> Что-то я не пойму о чем ты. Никаких ворнингов нет.
Окей, видимо, мне не везло с CFLAGS. Сейчас посмотрел, и не нашел Wdate-time ни в Wall, ни в Wextra. Но оно, разумеется, есть в шланговском Weverything.
> Так конструктивно есть что сказать?
Так я ж уже сказал. Вариант с присваиванием в if для тебя кажется непривычным и диким, потому что наличие ворнинга тебя к этому приучило (а может, и не тебя, а тех, у кого ты учился языку). Но на самом деле он не сложнее тех конструкций, к которым ты привык. Если уж говорить о вещах, которые заставляют задуматься, то if (NULL != (fp = fopen(...))) гораздо сложнее воспринимается, но кто-то все равно считает это хорошим стилем. Когда разработчики компилятора относят один вариант синтаксиса к хорошему стилю, а на второй выдают ворнинг - это их личное мнение, а не какая-то объективная оценка. И вот ворнинги как раз и придуманы для того, чтобы дать тебе шанс согласиться и исправить или наоборот решить, что разработчики пидоры и послать компилятор нахуй. Werror у тебя этот выбор отнимает. Все может измениться, если ты придумаешь способ заткнуть ворнинг в конкретном месте на всех компиляторах сразу без уродования кода и комментариев с бессмысленными цифрами. У PVS Studio не получилось, например.
> а вот на счет неиспользованного параметра ругнется
struct foo { int flag; int ∗someptr; };
void init_foo(struct foo ∗arg) {
arg->flag = 1;
}
Частый случай? Защитило? Ну да, я не забыл заполнить структуру. Но лучше бы забыл. Может, все же стоит головой думать?
> Но ты в курсе же что арч это бинарный дистрибутив и пакеты уже собраные устанавливаются
А ты слышал такое слово "DKMS"? grep Werror /usr/lib/modules/4./build/Makefile
> я лично сам собирал полностью ядро со всеми драйвера и т.п. интеловским компилятором
Это говорит о том, что Intel специально научили собирать ядро. Как tcc в свое время, например. Ок, я был не прав. Есть еще полтора компилятора, умеющие собирать линукс.
> Так при чем здесь алиасинг и ворнинги?
При том, что если ты просто попробуешь собрать ядро, оно не соберется. Ему нужны ключики, ему нужен отключенный strict aliasing, ему нужны расширения гцц. Если взять какой-нибудь другой компилятор, который просто поддерживает стандарт Си, хуй ты что соберешь, и хуй оно будет работать. А уж если ты Werror в нем включишь (или какой-то аналог), то ты узнаешь о коде ядра много нового, но при этом останешься с несобранным ядром.
> ядро требует особого подхода во многих вещах, которых нету в стандарте, но это проблемы стандарта
Что ни пост, то охуительное заявление. Windows нинужен, стандарт языка нинужен... огласишь остаток списка?
> даже майкрософт поняла что их компилятор говно и перешла на цланг
Я что-то пропустил? Я вот всегда думал, что кодогенератор у них свой, а шланг они притащили, просто потому что не успевают за охуительными фантазиями комитета по крестам.
> Вопрос в том, какие еще компиляторы тебе нужны и какие реально существуют
В моем мире существует много всяких железок и различных компиляторов. Коммерческие, опенсорсные, заброшенные и не обновлявшиеся с середины девяностых, но все они в той или иной мере нужны.
Впрочем, ладно. Нам всё равно друг друга не переубедить. Зато хоть тредик побампали.
> Там вроде всегда один и тот же набор аргументов
Например, я сделал SetTimer с колбеком. Аргументы колбека: hwnd, uMsg, idEvent, dwTime. Главное окно одно, сообщение всегда WM_TIMER, таймер один, время нужно редко. Итого, колбек может не прочитать ни одного аргумента. Или, например, во многих функциях Enum и им подобных может интересовать только какой-то один аргумент. Вообще, навскидку сложно вспомнить, но ублажать компилятор на эту тему требуется достаточно часто.
>>1078877
> Что-то я не пойму о чем ты. Никаких ворнингов нет.
Окей, видимо, мне не везло с CFLAGS. Сейчас посмотрел, и не нашел Wdate-time ни в Wall, ни в Wextra. Но оно, разумеется, есть в шланговском Weverything.
> Так конструктивно есть что сказать?
Так я ж уже сказал. Вариант с присваиванием в if для тебя кажется непривычным и диким, потому что наличие ворнинга тебя к этому приучило (а может, и не тебя, а тех, у кого ты учился языку). Но на самом деле он не сложнее тех конструкций, к которым ты привык. Если уж говорить о вещах, которые заставляют задуматься, то if (NULL != (fp = fopen(...))) гораздо сложнее воспринимается, но кто-то все равно считает это хорошим стилем. Когда разработчики компилятора относят один вариант синтаксиса к хорошему стилю, а на второй выдают ворнинг - это их личное мнение, а не какая-то объективная оценка. И вот ворнинги как раз и придуманы для того, чтобы дать тебе шанс согласиться и исправить или наоборот решить, что разработчики пидоры и послать компилятор нахуй. Werror у тебя этот выбор отнимает. Все может измениться, если ты придумаешь способ заткнуть ворнинг в конкретном месте на всех компиляторах сразу без уродования кода и комментариев с бессмысленными цифрами. У PVS Studio не получилось, например.
> а вот на счет неиспользованного параметра ругнется
struct foo { int flag; int ∗someptr; };
void init_foo(struct foo ∗arg) {
arg->flag = 1;
}
Частый случай? Защитило? Ну да, я не забыл заполнить структуру. Но лучше бы забыл. Может, все же стоит головой думать?
> Но ты в курсе же что арч это бинарный дистрибутив и пакеты уже собраные устанавливаются
А ты слышал такое слово "DKMS"? grep Werror /usr/lib/modules/4./build/Makefile
> я лично сам собирал полностью ядро со всеми драйвера и т.п. интеловским компилятором
Это говорит о том, что Intel специально научили собирать ядро. Как tcc в свое время, например. Ок, я был не прав. Есть еще полтора компилятора, умеющие собирать линукс.
> Так при чем здесь алиасинг и ворнинги?
При том, что если ты просто попробуешь собрать ядро, оно не соберется. Ему нужны ключики, ему нужен отключенный strict aliasing, ему нужны расширения гцц. Если взять какой-нибудь другой компилятор, который просто поддерживает стандарт Си, хуй ты что соберешь, и хуй оно будет работать. А уж если ты Werror в нем включишь (или какой-то аналог), то ты узнаешь о коде ядра много нового, но при этом останешься с несобранным ядром.
> ядро требует особого подхода во многих вещах, которых нету в стандарте, но это проблемы стандарта
Что ни пост, то охуительное заявление. Windows нинужен, стандарт языка нинужен... огласишь остаток списка?
> даже майкрософт поняла что их компилятор говно и перешла на цланг
Я что-то пропустил? Я вот всегда думал, что кодогенератор у них свой, а шланг они притащили, просто потому что не успевают за охуительными фантазиями комитета по крестам.
> Вопрос в том, какие еще компиляторы тебе нужны и какие реально существуют
В моем мире существует много всяких железок и различных компиляторов. Коммерческие, опенсорсные, заброшенные и не обновлявшиеся с середины девяностых, но все они в той или иной мере нужны.
Впрочем, ладно. Нам всё равно друг друга не переубедить. Зато хоть тредик побампали.
> Вообще я считаю, хорошо спроектированное приложение, с хорошим дизайном, разделенное на модули, с обработкой ошибок и т.д. вообще не нуждается в тестах
такой-то манямирок
> тесты
всю неделю хотел написать: не знаю что бы я делал без тестов в том плане, когда я придумываю систему-апи, и делая тесты, я в процессе нахожу кучу логических ошибок, архитектурных промашек - то есть, в таком ещё плане можно про них думать.
>if (NULL != (fp = fopen(...)))
Бля ну почему нельзя ну писать
fp = fopen(..);
if(fp == NULL)
ну или хотя бы просто if(!fp)
но нахуя это в одну строку то городить?
> Ну да, я не забыл заполнить структуру.
Так этот пример и не показывает случай с unused param у тебя там аргументом то и нету в функции.
flag = 1
Мммм меджик намберс збс.
>DKMS
Да у меня постоянно дрова от нвидии собираются через DKMS и еще пару других модулей. Никогда ошибок и ворнингов с этим не возникало.
А вот теперь остановимся на компиляторах и стандарте.
Ты прав, интел научили путем включения всех необходимых gnu extensions в языке, при чем эта возможно существует уже лет 7 если не больше.
>стандарт языка нинужен... огласишь остаток списка
Ты же понимаешь, что стандартных средств языка С недостаточно для написания полноценной, портабельной ОС, для всех архитектур? Поэтому существуют всякие gnu extensions и gcc builtins, которые нужны ребятам которые занимаются ядром ОС и эти ребята походу единственные кто двигает и улучшает язык С, и часть этих расширений в конце концов включается в новые стандарты. Но дело даже не в стандарте одобренным ISO/ANSI, дело в реальных потребностях на деле от языка С и если с этим соглашаются все остальные крупные разработчики компиляторов, типа gcc, clang intel то почему это не может считаться стандартом в неком роде, только из-за формальности ввиде отсутствия запатентованного драфта от ISO? А всем известно что такое стандартизация чего либо, и какая там бюрократия и еще что может быть.
Да и потом, кому как не разработчикам ядра придумывать новые возможности для языка? Ведь язык С был создан как раз для переписывания Unix с ассемблера на более высокоуровневый и портабельный язык.
Про майкрософт вообще говорить не стоит, их блядская студия, вообще никогда стандарту не следовала, и всегда была со своими расширениями, которые теперь нахуй никому не всрались и их говнокомпилятор даже С99 не поддерживает. Вон они сделали себе С# пусть на нем теперь и пишут свою ОС ( кстати сказать неплохой язык для макакинга в качестве альтернативы яве ), но по части ядра ОС и языка С майкорософт просто может идти нахуй. Все люди как люди, gnu, apple, intel, at&t, hp, amazon, google, а майкрософт у нас со своим говном, как говорится в семье не без урода.
>if (NULL != (fp = fopen(...)))
Бля ну почему нельзя ну писать
fp = fopen(..);
if(fp == NULL)
ну или хотя бы просто if(!fp)
но нахуя это в одну строку то городить?
> Ну да, я не забыл заполнить структуру.
Так этот пример и не показывает случай с unused param у тебя там аргументом то и нету в функции.
flag = 1
Мммм меджик намберс збс.
>DKMS
Да у меня постоянно дрова от нвидии собираются через DKMS и еще пару других модулей. Никогда ошибок и ворнингов с этим не возникало.
А вот теперь остановимся на компиляторах и стандарте.
Ты прав, интел научили путем включения всех необходимых gnu extensions в языке, при чем эта возможно существует уже лет 7 если не больше.
>стандарт языка нинужен... огласишь остаток списка
Ты же понимаешь, что стандартных средств языка С недостаточно для написания полноценной, портабельной ОС, для всех архитектур? Поэтому существуют всякие gnu extensions и gcc builtins, которые нужны ребятам которые занимаются ядром ОС и эти ребята походу единственные кто двигает и улучшает язык С, и часть этих расширений в конце концов включается в новые стандарты. Но дело даже не в стандарте одобренным ISO/ANSI, дело в реальных потребностях на деле от языка С и если с этим соглашаются все остальные крупные разработчики компиляторов, типа gcc, clang intel то почему это не может считаться стандартом в неком роде, только из-за формальности ввиде отсутствия запатентованного драфта от ISO? А всем известно что такое стандартизация чего либо, и какая там бюрократия и еще что может быть.
Да и потом, кому как не разработчикам ядра придумывать новые возможности для языка? Ведь язык С был создан как раз для переписывания Unix с ассемблера на более высокоуровневый и портабельный язык.
Про майкрософт вообще говорить не стоит, их блядская студия, вообще никогда стандарту не следовала, и всегда была со своими расширениями, которые теперь нахуй никому не всрались и их говнокомпилятор даже С99 не поддерживает. Вон они сделали себе С# пусть на нем теперь и пишут свою ОС ( кстати сказать неплохой язык для макакинга в качестве альтернативы яве ), но по части ядра ОС и языка С майкорософт просто может идти нахуй. Все люди как люди, gnu, apple, intel, at&t, hp, amazon, google, а майкрософт у нас со своим говном, как говорится в семье не без урода.
>но нахуя это в одну строку то городить?
вот с таких оленей я всегда угораю: как хочу так и пишу, может вы язык перепутали?
Так может ты перепутал чего, браток? Это тебе не щитпостинг на дваче.
В языках программирования нужно придерживаться правил и считаться с другими людьми, кто твой код читать будет.
Ты за 5 лет так ничему и не научился? Мда..
> но нахуя это в одну строку то городить?
Это другой вопрос. Но в целом - это позволяет не забыть проверку при получении ресурса. Вон в крестах под такой случай недавно разрешили даже декларации (!) в if, чтобы можно было делать if (FILE ∗fp; fp = fopen(...)) { handle fp here; }.
> Так этот пример и не показывает случай с unused param у тебя там аргументом то и нету в функции.
Ну так тот факт, что я не забыл о параметре, не избавляет меня от необходимости вдумчиво следовать описанному в документации контракту (инициализировать все поля структуры, а не одно).
> Никогда ошибок и ворнингов с этим не возникало.
Ну а у меня возникало. Однажды даже с виртуалбоксовым модулем, который очень широко используется.
> Ты же понимаешь, что стандартных средств языка С недостаточно для написания полноценной, портабельной ОС, для всех архитектур
Не понимаю. Для создания полноценной ОС нужен стандартный Си и пара ассемблерных файликов для нужной архитектуры. Расширения нинужны. Единственное, что мешает, убивая язык - это все тот же strict aliasing в текущем виде. Было бы оно opt-in или хотя бы opt-out - цены бы ему не было.
> почему это не может считаться стандартом в неком роде
Потому что вынуждает разработчиков других компиляторов смотреть на какой-то там другой компилятор, а не на стандарт. А смотреть на него сложно, он жирный. И это очень плохой подход, подобный тому, что было в вебе с Internet Explorer (раньше) или Webkit/Blink (сейчас).
> их говнокомпилятор даже С99 не поддерживает
Да вы заебали. Пруф неподдерживаемой возможности C99?
> в крестах под такой случай недавно разрешили даже декларации (!) в if
Ну еще не хватало разрешить декларации в if и заодно лямбды зауячить в С, ну а там и шаблоны можно хуле. Мало того, что они разрешили декларации посреди кода?
Кресты-то понятно, это Java #2, я уже давно крест на них поставил. Но в крестах такая конструкция выглядет более логичной, чем в С, ибо в крестах деклараии изначально разрешены где угодно и отличить сравнение в ифе от присвоения с такой конструкции наоборот легче. Но проблема в том, что такая конструкция не приемлема к С, я как и многие другие, считаю mixed-declarations самой ебанутой хуйней которую можно было ввести в стандарт, ибо это рушит просто весь подход к формированию программм на С.
>Не понимаю. Для создания полноценной ОС нужен стандартный Си и пара ассемблерных файликов для нужной архитектуры
Для создания, чего-то типа minix может и достаточно, а вот высокопроизводительную систему для серверов и чего угодно другово - нет. Ибо, код ядра состоит из огромного числа оптимизаций и подсказок компилятору как нужно генирировать код, чего нету в стандарте. Даже тот же __builtin_expect который используется в ядре чуть ли не в каждой функции в виде макросов likely/unlikely. А выравнивание памяти? Инлайн ассемблер? Тот же inline которого до С99 небыло в стандарте. Всякие трюки с кешем типа __builtin_prefetch? Тот же may_alias? Да еще сотня различных аттрибутов и билтинов, которые нужны в реальной разработке, но которых нету в стандарте и опять же которые со временем появляются в нем как раз из этих расширений.
>>1079070
>смотреть на какой-то там другой компилятор, а не на стандарт
А как ты представляешь себе формирование стандарта? Ты думаешь собираются такие люди, которые никак ни с кем не связанны, с разработкой тоже и их работа заключается только в формировании стандарта. Значит собираются они за круглым столом и начинают типа "А давайте добавим Х в язык?" и все начинают галдеть типа "Нет, это не нужно давайте лучше Y добавим!!1"?
Тут как в рыночной экономике - спрос рождает предложение, спрос формируют разработчики ядра и других систем, но т.к изменить стандарт и что-то туда добавить это очень очень сложный и геморный процесс, тут много чего от кого-то и чего-то зависит, поэтому разработчики сами договариваются о каких-то новых вещах и реализуют их в виде расширений, а потом уже это доходит спустя лет 20 до стандарта и то частично. Не могут же разработчики 20 лет ждать пока им там в стандарте дяди одобрят нужный функционал и потом только это разработчики компиляторов реализуют и потом только это дойдет до них. Так всегда все устроено в этом мире, кто у руля тот и диктует правила и остальные только вынуждены с этим соглашаться, чтоб не остаться у обочины прогресса.
Конечно такой подход не идеален и может вносить хаос и идиотию, как например с ситуацией в вебе, где теперь чуть ли не каждый день появляется новый модный фрейворк от фейсбука или кого-то подобного и все начинают это бездумно использовать, ибо у обычных резрабов выхода нету либо учить новое говно, либо сидеть голодным без работы.
Но к счатью, в сообществе разрабочиков ОС и компиляторов языка С, ситуация намного лучше и более менее стабильна, т.к. тут никто не гонится за модными технологиями и прочему позерству, тут людям нужена надежность и стабильность, поэтому новые изменения более менее органично вписываются и принимаются в сообществе. Да и предметная область куда более серьезная и зачастую связанна с производителями железа.
В общем, хочу сказать, что не стоит возводить то что написанно в стандарте ISO за святую и единственно возможную истину. Я вполне считаю GNU C, таким же стандартом как и ISO C с разницей лишь в том, что GNU мне может предложить куда больше возможностей чем ISO.
> в крестах под такой случай недавно разрешили даже декларации (!) в if
Ну еще не хватало разрешить декларации в if и заодно лямбды зауячить в С, ну а там и шаблоны можно хуле. Мало того, что они разрешили декларации посреди кода?
Кресты-то понятно, это Java #2, я уже давно крест на них поставил. Но в крестах такая конструкция выглядет более логичной, чем в С, ибо в крестах деклараии изначально разрешены где угодно и отличить сравнение в ифе от присвоения с такой конструкции наоборот легче. Но проблема в том, что такая конструкция не приемлема к С, я как и многие другие, считаю mixed-declarations самой ебанутой хуйней которую можно было ввести в стандарт, ибо это рушит просто весь подход к формированию программм на С.
>Не понимаю. Для создания полноценной ОС нужен стандартный Си и пара ассемблерных файликов для нужной архитектуры
Для создания, чего-то типа minix может и достаточно, а вот высокопроизводительную систему для серверов и чего угодно другово - нет. Ибо, код ядра состоит из огромного числа оптимизаций и подсказок компилятору как нужно генирировать код, чего нету в стандарте. Даже тот же __builtin_expect который используется в ядре чуть ли не в каждой функции в виде макросов likely/unlikely. А выравнивание памяти? Инлайн ассемблер? Тот же inline которого до С99 небыло в стандарте. Всякие трюки с кешем типа __builtin_prefetch? Тот же may_alias? Да еще сотня различных аттрибутов и билтинов, которые нужны в реальной разработке, но которых нету в стандарте и опять же которые со временем появляются в нем как раз из этих расширений.
>>1079070
>смотреть на какой-то там другой компилятор, а не на стандарт
А как ты представляешь себе формирование стандарта? Ты думаешь собираются такие люди, которые никак ни с кем не связанны, с разработкой тоже и их работа заключается только в формировании стандарта. Значит собираются они за круглым столом и начинают типа "А давайте добавим Х в язык?" и все начинают галдеть типа "Нет, это не нужно давайте лучше Y добавим!!1"?
Тут как в рыночной экономике - спрос рождает предложение, спрос формируют разработчики ядра и других систем, но т.к изменить стандарт и что-то туда добавить это очень очень сложный и геморный процесс, тут много чего от кого-то и чего-то зависит, поэтому разработчики сами договариваются о каких-то новых вещах и реализуют их в виде расширений, а потом уже это доходит спустя лет 20 до стандарта и то частично. Не могут же разработчики 20 лет ждать пока им там в стандарте дяди одобрят нужный функционал и потом только это разработчики компиляторов реализуют и потом только это дойдет до них. Так всегда все устроено в этом мире, кто у руля тот и диктует правила и остальные только вынуждены с этим соглашаться, чтоб не остаться у обочины прогресса.
Конечно такой подход не идеален и может вносить хаос и идиотию, как например с ситуацией в вебе, где теперь чуть ли не каждый день появляется новый модный фрейворк от фейсбука или кого-то подобного и все начинают это бездумно использовать, ибо у обычных резрабов выхода нету либо учить новое говно, либо сидеть голодным без работы.
Но к счатью, в сообществе разрабочиков ОС и компиляторов языка С, ситуация намного лучше и более менее стабильна, т.к. тут никто не гонится за модными технологиями и прочему позерству, тут людям нужена надежность и стабильность, поэтому новые изменения более менее органично вписываются и принимаются в сообществе. Да и предметная область куда более серьезная и зачастую связанна с производителями железа.
В общем, хочу сказать, что не стоит возводить то что написанно в стандарте ISO за святую и единственно возможную истину. Я вполне считаю GNU C, таким же стандартом как и ISO C с разницей лишь в том, что GNU мне может предложить куда больше возможностей чем ISO.
>Значит собираются они за круглым столом и начинают типа "А давайте добавим Х в язык?" и все начинают галдеть типа "Нет, это не нужно давайте лучше Y добавим!!1"?
вроде так в с++ делают - там целый комитет, собирают мнения по всему миру, потом добавляют - это у них на потоке. в с видимо тоже так будет.
> лямбды зауячить в С
Осталось каких-то два-три года. Ну, если примут, конечно.
> декларации посреди кода
Ничего, рано или поздно, но ты поймешь, насколько это удобно, когда при удалении куска кода не нужно компилировать, читать про неиспользуемые переменные, править и снова компилировать. Это нормально в каком-нибудь паскале, который создан, чтобы держать детей в строгости. Но Си - это язык для написания программ, а не для садомазохизма.
> __builtin_expect
Очень хорошо. Так же как in и out, которые очень любит Microsoft. Все это будет в виде атрибутов в следующих стандартах. И, к счастью, все это абсолютно не должно ломать код, потому что можно будет сделать:
#if __STDC_VERSION__ >= 202113L
#define likely [[likely]]
#else
#define likely
#endif
> сотня различных аттрибутов и билтинов
Атрибуты должны быть заифдефанными кейфордами, интринсики - штука очень полезная, но опасная, ибо не все и не везде есть.
> Тот же inline которого до С99 небыло в стандарте
Теперь он есть, а на него по-прежнему всем насрать. И под всеми я имею в виду в первую очередь компиляторы.
> Значит собираются они за круглым столом и начинают типа "А давайте добавим Х в язык?"
Примерно так все и происходит. Вот Microsoft громче всех галдела, и нам дали сраный memset_s с прочей честной компанией, а теперь их почти нет, и, надеюсь, их добьют в C2x. Алсо, можешь тоже предложить что-нибудь этакое (правда, уже слегка поздновато), чтобы все охуели, как ты можешь http://www.open-std.org/jtc1/sc22/wg14/
>Теперь он есть, а на него по-прежнему всем насрать. И под всеми я имею в виду в первую очередь компиляторы
так незачем, если есть static. да даже без него - компилятор может продублировать тело.
весь дрочь же только за системы где считают байты - там, наверно, компилятору не пофиг.
>лямбды зауячить в С
Никогда не понимал, зачем нужны лямбды если есть указатели на функциюделегаты
Как я понимаю они в основ нужны для того, чтобы создавать функциональные объекты по случаю. Ну то есть не определять к примеру функцию, которая будет у тебя вечно в памяти. А определить эту лямбду, которая очистится из памяти после её выполнения.
Но. Мне не нравится просто ебанутейший вырвиглазный синтаксис этих выражений.
ИМХО более читаемо будет определение функции, а потом, если нужно эту функцию куда передать, например как компоратор при сортировки, то просто передать указатель на эту функцию. А не городить в этой скобочки ещё миллионы скобочек, превращая вызов функции в что-то похожее на размазанное гавно в ASCII графике по твоему монитору.
ПИТОН ЭТО СИ С САХАРОМ
>и нам дали сраный memset_s с прочей честной компанией, а теперь их почти нет, и, надеюсь, их добьют в C2x
вот это не понял, что честной компанией?
На счёт не для эмбедеда не знаю. Но устроится всяким пругрумистом stm и вообще омк достаточно легко. У нас в Ростове к примеру точно легко.
Я в обороночку вкатился. Моделирую всякое говно на сях + мкл.
Правда, основой все-таки является мкл. Си можно не знать и заменить его, например, фортраном или плюсами.
Для си/фортрана написаны тонны мат. либ. вылизанных до байтика.
Не знаю что он там моделирует, но я сталкивался с моделированием динамических системосцилляторов если быть точнее в реальном времени. Код был чуть больше чем полностью на С. В коде было fft и решение ОДУ достаточно большой жесткости. Про скриптопарашу ты это про пайтон?
>про пайтон
ну или перл. любую си либу можно подключить да и пердолинга с конпеляцией нет. я вот перл всегда для прототипирования пользую.
На испытательном сроке 35, после 45. Дс2.
>>1079250
Полагаю, потому что сколь-нибудь относящиеся к реальному миру задачи будут решаться на петухоне пару недель. Даже со всеми математическими библиотеками этого мира.
На питоне я пишу прототипы. Более того, после первых месяцев анальных страданий я решил, что ни в коем случае нельзя прикасаться к си, покуда не готов питоновский вариант облегченной задачи потому что я криворукий даун и не способен осознать, где ошибка является следствием "неправильной" математики, а где - моего незнания языка. На питоне проблем от незнаний языка не возникает.
Семейство _s функий, они же Annex K, они же TR 24731-1.
Я просто не шарю. Когда я что-то слышу про микроконтроллеры, я представляю мужика в свитере и с паяльником.
Сейчас есть отладочные платы и макетки. А проектировать схему и паять ее за тебя будут другие. Твое дело говнокод писать.
Предвосхищая очевидное предложение: с исходниками Го я пытался ознакомится, но моих способностей не хватило.
>Как запилить многопоточность на манер того же Go?
нахуя? юзай потоки, процессы и poll и select
Я для себя интересуюсь, c целью повышения компьютерной грамотности. Ну и вдруг кому-то попиздеть захочется за разные аспекты, а я полсушаю.
>c целью повышения компьютерной грамотности
а читать книги про многопоточное программирование тебе типа в западло?
Ну нахуй ты начинаешь? Заняться нечем - починил бы шифты на клаве. А знаешь литературу, порекомендовал бы. Я, впрочем, уточню: меня не в принципе многопоточность интересует, а конкретно реализация пользовательских потоков, т.е. без совсем низкоуровневых возможностей, например, переназначить адрес странице.
А ты хули борзый такой? Тебе че-тут все должны по твоему хотению сразу броситься и начать разжовывать и в ротик класть? Пиздуй в свой пидорский go тред и выебовайся там. Совсем охуели.
мимо другой анон
> Пиздуй в свой пидорский go тред
Ну и причем тут го тред?
>мимо другой анон
Лучше бы дальше бочку молча делал.
Любая книга по основам ОС и вообще по ОС тебе даст понимание того, как работают процессы и потоки.
К примеру
Таненбаум Э., Бос Х. Т18 Современные операционные системы. 4-е изд.
Рихтер Дж., Назар К. - Windows via C C++
>Ты распаковал свой файл?
Да, но толку 0, т.к. когда перепаковываю ресурсы обратно игра вообще не запускается.
Там кроме оффсетов и длин в каталоге ресурсов в начале файла еще длины распакованных данных и чексуммы.
Прога offzip. Так-то всё распаковало, я данные которые мне надо изменил, но когда запаковал обратно игра не запускается. Попробовал не изменять ничего т.е. тупо распаковать и запаковать, тоже не запускается.
>>1079663
>Там кроме оффсетов и длин в каталоге ресурсов в начале файла еще длины распакованных данных и чексуммы.
Вот я и не пойму, их получается распаковывать не надо?
Ты дебил? У тебя ресурсный файл с нестандартным форматом. Либо ты пишешь свой распаковщик/упаковщик, либо ты идешь нахуй. Никакие проги тебе не помогут (кроме сделанных под эту конкретную игру). Прога, скорее всего, просто тупо натравливает zlib на все офсеты в файле, и если что-то распакуется, сохраняет. Т.е., это подходит, чтобы посмотреть, что там внутри, но не подходит для моддинга никаким местом.
в го они такие. или , в смысле, почему не pthread?
Тебе не надо ничего запаковывать. Тебе надо подставить другие данные. Хули ты такой простой, ага распаковал/запаковал, и всё пиздец, должно заработать. Разрабы ну, специально игру делали чтобы ты смог распокавать, запаковать. Не будь наивным.
K&R читаю, пока на 50 странице, но уж очень этот вопрос мучает.
> откуда gcc знает, где лежат имплементации тех функций
Во-первых, когда ты делаешь #include, ты не включаешь реализации, а только объявляешь, что есть такие функции. Реализации добавляет линкер из либ или объектных файлов уже сразу в бинарник. Во-вторых, как компилятор узнает пути до стандартных инклудов или либ, зависит от компилятора. Где-то жестко прошиты, где-то в переменных окружения лежат. В gcc нестандартные пути для поиска инклудов ты можешь указать с помощью -Idirectory_name, а для либ -Ldirectory_name.
Подключаемые хедеры просто вставляются перед кодом программы уже при препроцессировании.
Ты ещё спроси, откуда он знает, что ты функции ему объявляешь.
Если <...>, то файл ищется по дефолтным путям компилятора, их может быть несколько, сначала одни проверяются, потом другие, если нет в первых.
Если "...", то по относительному пути "..."
gcc -E -W -v -
Вот, нужно анпакер написать для файла (ссылка на файл: http://rgho.st/6mdpkV8YV ) со следующими данными: "Количество ресурсов в файле (0x47==71) лежит по смещению 8. Список описаний ресурсов начинается со смещения 0x0C. Описание каждого ресурса размером 0x34 байта, для приведения в читаемый вид надо 4-хбайтовые фрагменты поксорить на 0x25 0x24 0x74 0x05. После ксора будут видны имена ресурсов, смещения в файле, упакованный и оригинальный размер. Сами ресурсы упакованы zlib."
Буду очень благодарен.
>надо 4-хбайтовые фрагменты поксорить на 0x25 0x24 0x74 0x05
А ты пробовал ксорить hex-редактором?
Я сам не пробовал, просто знаю что там есть что-то вроде обработать файл xor, да и операция простая же.
Так сделай, блять, там задача на 15 минут. Ты не написал ни строчки кода за несколько дней, только ходишь и клянчишь. Даже неполное описание формата, которое ты выше постишь, ты и то у кого-то выпросил.
В чём затык то у тебя? Что не получается поксорить?
Есть 2 массива s[num] и t[num]. Нужно скопировать содержимое первого во второй. Почему нужно инкрементировать счётчик именно в массиве s а не tt[i++] = s;:
while (i<num)
t = s[i++];
> while (i<num)
> t[i] = s[i++];
Вот это будет работать неправильно. Прочитает значение по s[i], инкрементирует i, и потом уже запишем по t[i]. А вот:
> while (i<num)
> t[i++] = s[i];
Как раз прочитает, запишет, и потом уже инкрементирует.
>Как раз прочитает, запишет, и потом уже инкрементирует.
Давно такое поведение гарантировано, лалка?
Ты че ебанутый? Ты в курсе вообще как постинкремент работает? Он возвращает копию (в теории на самом деле давно уже копии не возвращаются ) текущего значения а потом инкрементирует. Так что выражение:
t[i] = s[i++];
равнозначно выражению
t = s; i = i + 1;
i++ сначала эвалюэйтит выражение, а потом добавляет единицу
t[i] = s[i++]; равнозначно
n = i;
i = i + 1;
t = s[n];
http://rgho.st/6GDN4cjcZ
1 читает байт
2 xor 0x25
3 читает следующий байт
4 xor 0x24
5 читает следующий байт
6 xor 0x74
7 читает следующий байт
8 xor 0x05
9 записывает в новый файл
10 -> 1
Это нужно?
тебе же уже сказали что нет - неопределённое поведение.
Пасиба, оно
Качай не ссы
В треде есть аноны, способные переписать код с питона на Си с небольшими изменениями? (там парсер веб страницы, плюс консольная запускался бинарников в зависимости от результатов. Под никсы на ncurses.)
С чем придется возиться, смотреть тут.
https://gitlab.com/salfter/mph_switch
Оплата в криптовалюте, обращаться на почту foor@rfakeANUSy}fLandexPUNCTUMrNwlu
В рублях-то не проблема заплатить. Это было написано для тех, ебанашка, кто, возможно, не желает светить своими доходами перед сбером.
смотри почту
(gt = green tree, rbt = red black tree).
.h файлы у меня есть, так что нужно написать только .с
Цена впроса = 3к рублей. Сроки = 10 дней, но лучше поскорее. Если можешь помочь и немного заработать - отпиши фейкомыльце
А как это реализованно, есть ссылки на вайтпейперы или статьи? Гугл тоже ничего об этом не знает.
>может хранить одинаковые значения
а разница какая? это же вопрос использования - хочу записываю одинаковые, хочу нет.
Ну в общем-то да, но чтоб это называли зеленым деревом ниразу не слышал. К тому же чтоб хранить одинаковые ключи в бинарном дереве тебе нужно хранить ноды в виде списка, а это уже практически не бинарное дерево а B tree.
> К тому же чтоб хранить одинаковые
да ничего тебе не нужно, просто определяешь для себя в какую сторону класть одинаковые и всё.
Так это уже черт чего, а не бинарное дерево. Тем более без балансировки это может превратиться в обычный лист со временем лукапа O( n ).
> Так это уже черт чего, а не бинарное дерево
Вполне бинарное дерево, балансировку тебе никто не мешает делать, если тебе похуй на позицию элементов с одинаковым ключом.
Проще тогда хеш таблицу сделать один хуй профит от использования в таких случаях деревьев абсолютно нулевой.
Я тут перечитал еще раз задание, и мне кажется что нужно просто считать количество дубликатов, а не записывать их в древо. Тоесть создаем древо и записывает туда значения, как обычно, а при отображании пишем, что этих элементов двое
Ну если говорить о задаче, то там повторяющиеся ключи нахуй не вперлись, если можно просто увеличивать счетчик повторов в ноде.
чё ты хуйню какую-то несёшь. если в обычное дерево последовательно передавать ключи, то оно будет таким же списком. это уже вопрос вероятности или типа того.
Помоему это ты хуйню несешь. Что ты подразумеваешь под "обычным деревом"? Бинарное? Без балансировки? Если ты передашь в такое дерево ключи в виде последовательно возрастающего/убывающего списка, то это не вопрос вероятности, это блять 100% лист. Т.к. без балансировки все ноды будут вставляться либо в лево либо вправо. Типа того у него пиздец.
вопрос вероятности это его использование, дунич. решил он тут
> Проще тогда хеш таблицу сделать один хуй профит от использования в таких случаях деревьев абсолютно нулевой
да я сам не знаю о чём мы тут все.
#include <stdio.h>
#define NUM 10
int bigofarray ( int mas[], int i);
int main (void)
{
signed int ar[NUM] = {-123,-221,-3,-4124,-123,-312};
printf ("%d\n",bigofarray(ar, NUM));
return 0;
}
int bigofarray (int mas[], int i)
{
int big,j;
for (j=0,big = mas[0]; j<i; j++)
big = (big < mas[j])? mas[j]: big;
return big;
}
Результат выполнения: 0
На всякий случай https://pastebin.com/raw/9ADash3e
#include <stdio.h>
#define NUM 10
int bigofarray ( int mas[], int i);
int main (void)
{
signed int ar[NUM] = {-123,-221,-3,-4124,-123,-312};
printf ("%d\n",bigofarray(ar, NUM));
return 0;
}
int bigofarray (int mas[], int i)
{
int big,j;
for (j=0,big = mas[0]; j<i; j++)
big = (big < mas[j])? mas[j]: big;
return big;
}
Результат выполнения: 0
На всякий случай https://pastebin.com/raw/9ADash3e
Размер массива у тебя десять, а числов всего шесть. Недостающие элементы забиваются нулями. Ноль больше всех твоих чисел. Запили себе countof: #define countof(array) (sizeof(array) / sizeof((array)[0])) Выпили NUM (int ar[] = { ... }), а вместо NUM в вызове bigofarray используй countof(ar).
> К тому же чтоб хранить одинаковые ключи в бинарном дереве тебе нужно хранить ноды в виде списка
Вовсе не обязательно. Можно выделить массив структур и написать функции left, right, parent, а новые данные записывать в пустую ячейку с наименьшим индексом. Так гораздо быстрее будет.
Сигфолтит. При вызове "abort();" в начале main'а всё равно сигфолтит, abort не отрабатывает. GDB говорит "Program received signal SIGSEGV, Segmentation fault." "0x0000000000403495 in main ()" и всё.
Как это дебажить?
Не тебе верхний пост, не тебе.
Хотя нет, если убрать abort(), то в gdb подробный лог появляется. Дальше сам справлюсь.
Но почему вместо "Aborted", или вообще любой информации(принты по началу ставил), в сонсольку выводится только сигфолт? При аборте он не должен и выполняться, т.к. явно находится дальше него в коде. При принте этот самый принт в любом случае должен выводиться раньше оповещения о сигфолте. Но я получаю только сраный сигфолт.
Понятно. Сигфолт происходит на первом любом вызове. Будь то abort, printf, вообще что угодно. Снова прощу помощи, почему так может происходить?
Проблема найдена. Это происходит при попытке создать слишком большой массив. Но почему gcc не говорит мне об этом?
прост)
Спасибо!
И, если не затруднит, объясните, почему так считаете.
С99 принес некоторые хорошие фитчи некоторые плохие типа как mixed declarations.
С11 Вроде бы ничего так, но я им особо не пользуюсь, половина компиляторов его не поддерживают а в другой половине половины нету. Но кроспатформенные треды, выглядят ничего для простеньких приложух, ну еще атомимики наконец-то завезли.
Юниттесты : Cmocka?
Static code analysis : есть что-то вроде lint или чего другого?
Code coverage : Cobertura?
Mem leaks : Есть по типу valgrind?
Что еще в помощь используете в проектах?
quickcheck
Install Gentoo
Любой линукс. Для начинающих обычно советуют минт или убунту, еще опенсуся хороша.
Традиционно отвечаю итт, что похуй и на ос, и на компилятор, и на IDE/редактор. Плюсы линуксов - скорее всего, компилятор и все необходимое будет установлено вместе с системой. Плюсы винды - интуитивно понятные отладчики с графическим интерфейсом (при этом возможность ебли с gdb никуда не девается), и не менее понятные инструменты для мониторинга от System Internals.
Ошибка типа:
Нет подходящей функции, чтобы вызвать в конструкции:
if (pDialog->getChangedFontFamily(&pszFont))
Как я могу быстро найти описание структуры pDialog?
> pDialog
Ну это либо локальная переменная, либо параметр функции (глобальные переменные так не именуют). Ищешь определение перменной, ищешь ее тип в хедерах grep-ом или еще как. Но так как ты ошибся тредом, то это может быть еще и член класса - смотри определение класса.
Вызов метода же. Если бы был указатель на функцию, то ей бы скорее всего передали что-то кроме параметра, в который пишется результат.
В шапке. K&R или Prata.
Prata
#include <stdio.h>
#define CAL 4
void printm (int c, int target[][c]);
int main (void){
int i;
int array[][CAL] = {1,2,3,4,5,6,7,8,9,10,11,12};
i = sizeof array / sizeof array;
printf ("%d\n", i);
printm(CAL, array);
return 0;
}
void printm (int c, int target[][c]){
int i;
i = sizeof target / sizeof target;
printf ("%d\n", i);
}
Выводит:
3
0
Почему не 3 3 ? Заранее спасибо.
Вот на всякий:https://pastebin.com/L9Ab8STH
#include <stdio.h>
#define CAL 4
void printm (int c, int target[][c]);
int main (void){
int i;
int array[][CAL] = {1,2,3,4,5,6,7,8,9,10,11,12};
i = sizeof array / sizeof array;
printf ("%d\n", i);
printm(CAL, array);
return 0;
}
void printm (int c, int target[][c]){
int i;
i = sizeof target / sizeof target;
printf ("%d\n", i);
}
Выводит:
3
0
Почему не 3 3 ? Заранее спасибо.
Вот на всякий:https://pastebin.com/L9Ab8STH
и ещё погугли арифметику с переполнением
А в каких языках длинная арифметика по умолчанию? Я только про питон знаю. В си так не делают, потому что потери производительности противоречат принципам языка.
переменные безграничного размера в регистр не засунешь
В верилоге.
в кернигане и ричи есть про стеки, память и всю ету не понятную ебалду? вот например дано 2 массива
[5][6][3][4]
[20][0][4]
как найти чо там между ними или скока памяти занимает есть гайд? где крч инфу всю по стекам макс понятно найти можно
1) Это вопрос про ОС, а не про стек. В Си стека нет - есть автоматические переменные, и компилятор волен их хоть маллоком выделять. Все, что ты должен знать - это то, что переменная - это некий объект, у объекта есть адрес (исключение - storage class register) и размер, из объектов могут быть составлены другие объекты (массивы и структуры, например), у них тоже есть адрес и размер.
2) Для вычисления длины в байтах есть оператор sizeof. Адрес тебе выдаст printf("%p\n", &something).
3) Странная у тебя нотация массивов, никогда такой не видел.
Про стеки и память читай Петцольда, Таненбаума, Ultimate Memory Guide и документацию на ОС.
от души
О расскажи как Ростове с вакансиями на С-программиста
Ключ для gcc или clang, превращающий все предупреждения в ошибки (пока не исправишь, программу оно тебе не соберет). Добавлять, очевидно, в командную строку, которой ты вызываешь компилятор.
спасибо
Читаю даблы scanf-ом, а на выводе оно их округляет, причем если последний знак числа был 2, вообще ету 2ку скипает
А число точно можно представить в формате с плавающей точкой без округления? Показывай код и числа.
кароч на вводе 3 координаты точек
я их этим сканирую
double koord ( double x1, double x2 )
{
char hran;
if(((scanf(" [ %lf , %lf %c", x1, x2, &hran_prava)) != 3) || hran != ']' )
{
printf("Invalid input.\n");
exit (0);
}
return 0;
}
потом мне нужно провести над ними несколько операций, но даже эти точки на выводе округлены к примеру для [1495.952,934.023]
будет [1495.95,934.023]
Может быть, ты что-то делаешь не так при выводе? Потому что https://ideone.com/Y9Reqz у меня ничего не округляется.
а попробуй вывод через g, а не через f
А ты точность не пробовал указывать? Точность по умолчанию - 6, %g показывает (6 - (e + 1)) цифр, то есть (6 - (3 + 1) = 2 цифры для первого числа и (6 - (2 + 1) = 3 цифры для второго. Именно это и происходит: https://ideone.com/EjLA9B
но там ведь оно по-прежнему округляет .129 к .13
у меня там дальше в программе умножение и деление этих чисел и в итоге выходе совсем не то
Ты ведь осознаешь, что числа округляются при выводе, и это никак не влияет на твои умножения и деления? Ты ведь осознаешь, что точно представить все множество чисел всего лишь 32 или 64 битами нельзя, и поэтому в числах с плавающей точкой может храниться достаточно близкое (относительно порядка числа), но все же отличающееся значение? Тебе все равно придется округлять результаты, это нормально. Алсо,
> совсем не то
выходить не может, если ты не делаешь глупых вещей (типа катастрофической потери точности при применении последовательных преобразований числа в цикле).
Алсо, код снова обновил.
может быть это нормально, соре, если не понимаю правильно, но лучше я тебе объясню,
Мне нужно узнать лежат ли точки на одной прямой и если идет округление выходит так, что даже маленькая неточность как .13 вместо .129 играет роль (там в формуле есть деление, может быть(скорее всего) ето и сливает весь результат)
я в целом почитал про арифметические операции над числами с плавающей точкой, но кроме как >такое случается
я ничего не нашел скорее не понял
да, и точнее сформулирую вопрос, как можно избавиться от етого хвоста?
> Мне нужно узнать лежат ли точки на одной прямой
Выбери абсолютную или относительную погрешность (относительно порядка сравниваемых чисел), которая достаточно маленькая, чтобы с ней мириться, но при этом больше, чем погрешность, которую привносят вычисления. Сравнивай точки с учетом этой погрешности. Это нормально, когда ты работаешь с плавающей точкой. Более того - по-другому никак. Рекомендую вот этот цикл статей: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ (покрути ниже, там будет содержание). Там дохуя, зато найдешь ответы на все свои вопросы.
> да, и точнее сформулирую вопрос, как можно избавиться от етого хвоста?
Округлять.
Спасибо большое, сча прочекаю статью
Ты там, ёпта, трип-коды дешифруешь?
Дрова к чему? Я так понимаю, нужно ведь ещё нужное желез приобрести, чтобы было на чём тестировать.
Если в *bsd для твоего железа все дрова уже написаны, то в линуксе и подавно.
Не шарю в стандартах, но часто видел в коде ядра объявления переменных в середине функций. Есть также мнение, что такие проекты как раз стандарты и двигают.
Алсо, как гуглить вопросы по Си? Вечно вылазит С++.
> В чём пишите код
Пишете Саблайм 3 для себя и для всякой мелочи, Visual Studio для рабочих проектов.
> многие обходятся
Ты тоже можешь обходиться, а можешь кодить, рефакторить и отлаживаться с удобствами - выбор за тобой.
> как гуглить вопросы по Си
"c language", "plain c", "ansi c"
> VS Code.
Софт для программистов, сделанный на HTML? Блять, тебе самому-то не противно упоминать такое в этом треде?
>Подскажите примеры сишных проектов с наилучшим качеством кода, и где возможности языка задействованы широко.
Кстати, скажите, какие из этих проектов возникли в последние 10 лет?
>Софт для программистов, сделанный на HTML? Блять, тебе самому-то не противно упоминать такое в этом треде?
JS же, нет? Что поделать, такова судьба десктопа сегодня. Зато кроссплатформенность - удобно, когда постоянно переключаешься между виндой и линупсами.
Алсо Visual Studio которая обычная вообще слабо предназначена для написания кода на Си. Плюсы и то с натяжкой. А вот как IDE для сисярпа очень даже ничего.
Хотя я понимаю, что всё это вкусовщина и дело привычки. Но надо же о чём-то в треде общаться, чтобы он не тонул.
что плохого в html? можно рассматривать его как такой ui-фреймворк.
кстати, как обычно майкрософт сделала такие html-приложения в виндовс черт знает еще когда, а идея взлетела только сейчас
>Quake III Arena is a multiplayer-focused first-person shooter video game released in December 1999.
Стало быть написана без использования С99 и С11.
>сишных проектов с наилучшим качеством кода
Что в твоём понимании наилучшее качество кода? Техническая простота или наоборот, обилие синтаксического сахара? Множество хитровыебанных костылей ака СМЕКАЛОЧКА разрабов или паттерн на паттерне?
То, что одни называют "code smell" для других является руководством для программирования. Например встречал кукареки, что "обилие комментариев - признак дурного кода и низкой культуры программирования". Хотя если глянуть Nasa C styleguide или любой другой промышленный сишный стандарт по оформлению кода, увидишь, что в файлах зелёного текста больше, чем непосредственно кода.
>Что в твоём понимании наилучшее качество кода?
Вот я и спрашиваю об этом здесь опытных сишников, которые могут отличить говнокод от высококачественного кода. Как-то же надо начинающим учиться на хороших примерах.
>таких нет. большие проекты на си - это нечитаемый пиздец. современные высокоуровневые языки не просто так придумали.
А из годных небольших что порекомендуете глянуть?
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c#n603
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c#n883
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c#n1023
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c#n1111
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c#n6143
они все в начале блока, это не противоречит C89
Я начал писать комментарии после того, как к вернувшись к проекту через какое-то время я не понимал что этот код делает.
perf tool неплох, как по мне (это часть linux репы, но может рассматриваться отдельно от самого ядра):
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf
Ну ты то конечно пишешь волшебный код, который понятно только взглянув.
Такие высказывания говорят только о твоей неопытности, как программиста.
Алсо, OpenBSD.
простой эксперимент. скочай код какого-нибудь проекта и попробуй разобраться в его архитектуре
Двачую этого. Но тут еще важно, чтобы код-стайл был на уровне, понятные имена функций и т.п.
Комментарии нужны, для описания общих принципов работы твоего кода, описание полей структур и т.п Но хороший код стайл должен работать заместо комментарий в самом коде. В идеале в коде не должно быть вообще комментов посреди функций.
>большие проекты на си - это нечитаемый пиздец.современные высокоуровневые языки не просто так придумали.
Неужели обязательно придётся обмазываться крестами/жабой/шарпом/питоном? В современном программировании без этого bloated никак не обойтись?
Не слушай этого долбоеба.
Нормальные проекты на С намного чище, понятнее и яснее чем на всяких крестах и жабах.
>В идеале в коде не должно быть вообще комментов посреди функций
Чушь. Комментарии внутри функции логически делят ее на части, у функции появляется логическая структура более простая для понимания. Ты можешь просто визуально скипнуть не нужные тебе части и начать разбираться в нужной тебе части.
т.е. комментарии вида
// ищем залупу
// применяем залупу на хуй
описывает что делает нижеследующий код. без таких комментариев нужно будет сидеть и самому разбираться в коде
> Комментарии внутри функции логически делят ее на части
Братан, тебе сержант запрещает разбить лапшефункцию на несколько хороших, малых функций?
>>1088459
Господи, какой же ты нуб. Не позорился бы.
>Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, as we all know), and do one thing and do that well.
На вот почитай, как пишут действительно умные дяди. А свой манямирок можешь засунуть себе в жопу и не кукарекать тут в чем не шаришь.
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#functions
>ко-ко-ко
Простите, но я пишу реальный код для реальных программ, в которых не все так идеально, как в вашем манямирке
>>1088475
Лишний раз доказывает мое предположение, что ты долбоеб.
Во-первых, то что написано в коде стайле не mandatory требование, на то это и код стайл.
Во-вторых, линукс пилят тысячи разработчиков и ежедневно коммитятся тысячи строк кода которые невозможно контролировать и чистить, все лежит на плечах самих разрабов.
В-четвертых, в линуксе есть и примеры уебищного кода похуже твоих высеров, их там оставляют по двум причинам: 1. никто это не собирается переделывать ибо это какие-то легаси драйвера. 2. Для примера как не нужно делать.
В-четвертых, то что ты высрал выглядит легитимно и не засирает читабельность кода.
> Зато кроссплатформенность
Саблайм написан на крестах использует Skia для рендера. И кроссплатформенность.
> Visual Studio которая обычная вообще слабо предназначена для написания кода на Си
Ну давай, обоснуй.
>>1088247
> кстати, как обычно майкрософт сделала такие html-приложения в виндовс
Они еще тогда были говном, виджеты ActiveDesktop роняли рабочий стол вместе с explorer-ом, таскбаром и систреем, а .hta работали через раз и годились только для пасхальных яиц и туториалов по обращению с мышью.
Как можеть читабельность кода то, что призвано улучшить эту самую читабельность?
Сдается, что из нас двоих действительно кто-то долбоеб, и это не я.
>Как можеть читабельность кода то, что призвано улучшить эту самую читабельность?
Ты по русски умеешь писать, долбоеб, я нихуя не понял, что ты высрал там.
>Они еще тогда были говном
Ну я где-то читал что у них была какая-то эспериментальная версия ОС с хтмл-интерфейсом давно. Может напиздели.
Ну еще были виджеты в windows 7 и полноценные metro-приложения.
И сейчас UWP можно делать с html и javascript
> Не все так просто и можно разбить на функции.
Братан, так тебе сержант запрещает? Или марсиане, может, запрещают? Или бесы запрещают? Некоторым кгбшники вон запрещают - а тебе кто запрещает, братан?
Давай ты сам подумаешь и нам расскажешь, как могут ухудшить читабельность хуевые, out-of-date комментарии. Вообще-то такие вещи люди обычно на первом курсе\проекте узнают, но ты же у нас ПРОМЫШЛЕННЫЙ ПРОГРАММИСТ, первый курс не для тебя, да?
>out-of-date комментарии
Зачем ты пишешь out-of-date комментарии. Ты что, ебанутый?
Пишет хуйню и ругает само средство.
Иди свою laba1 дальше пиши, нуб. Даже комментировать не буду, постарайся сам догадаться.
виртуоза бескоментариевого кода с идеально именованными функциями строго выверенной длины разорвало. найс.
>Ну давай, обоснуй.
Может потому, что это изначально среда для разработки на языках .Net?
Там даже создать Си проект нельзя, а проект под С++ называется "Visual C++", что намекает.
> Может потому, что это изначально среда для разработки на языках .Net?
Лолшто? А винду по-твоему в виндовом блокнотике писали? А ты когда-нибудь слышал о знаменитой Visual Studio 6.0 (она же 98)?
> а проект под С++ называется "Visual C++"
Намекает, что студия называется Visual, потому что умела в RAD посредством таскания контролов и заклинания (крестового) MFC. Компилятор под Си в ней всегда был, и никуда не денется - сохраняешь файл с расширением .c, и компилятор соберет его, как написанный на C.
>Так ли нужен IDE в Си?
Для начала хватит emacs/vim/geany. А когда поднаберётся опыт, то сам поймёшь, что лично тебе нужно от IDE.
Сохрани с файл мэйн.с и запусти:
#include <stdio.h>
int main()
{
#ifndef __cplusplus
printf("Nahuuy poshel");
#else
printf("Soryan, antosha");
#endif
}
>>1088623
Что пишется на Си под винду, кроме школьных laba1.с?
Для разработки под микроконтроллеры есть Keil4, IAR и всякие специализированные IDE вроде Visual DSP++. Там поддержка JTAG и ассемблера практически из коробки. Системная хуита пишется для линукса на линуксе. Не знаю ни одного долбоёба, который бы пытался запустить Visual Studio на юниксах или сконфигурировать MSBuild для работы с кросс-компилятором.
Я конечно понимаю, что всё - дело привычки. Но нехуй свою привычку выдавать за истину в последней инстанции. Я сам пользуюсь Visual Studio, когда пишу десктопную хуиту на C# или драйверы на С++. Но использовать студию для Си?
Лишь бы комментариев в функциях не было
Возьми да проверь.
Занулять не должна. При возврате из фукнции, просто смещается текущий указатель на стек, данные никто не затирает по крайней мере так делает гцц.
Другое дело, если ты работаешь с потоками. Если ты функцию инициализируешь как независимый процесс/поток, то в принципе стэк для этого процесса может быть определён где угодно самой осью, и будет ассоциирован только с этим потоком. Внутри же потока работа со стэком будет идти стандатно "сверху-вниз".
В любом случае, нахуя тебе нижележащий стэк?
не, я лонгджампами балуюсь. стексмешинг или сегементацию ловлю.
Допустим у нас есть потрёпанный жизнью список, из которого уже удалили дохуя элементов в разных местах. Добавление новых элементов будет увеличивать общее пространство, которое занимает этот список, или они будут записываться в те места, где располагались удалённые?
Я понимаю, что здесь больше решает то, как реализована рантайм либа, а точнее malloc в ней. Но просто интересно стало, можно ли вызвать переполнение кучи, если долго насиловать простенький связанный список.
никогда об этом не задумывался, я всегда заранее выделял буфер под узлы. и через обёртку над инструкциями bsf bsr их выделял - массивом битов.
Список тут ничем не отличается вообще от выделения памяти. Если у тебя malloc при выделении и удалении одинаковых блоков памяти ведет к переполнению, то это хуевый malloc
size_t fu(void) {
int v;
return (size_t)&v;
}
это типа специально так, чтобы быстрей ошибка выловилась?
>return (size_t)&v;
Ты пытаешься разыменовывать переменную или у тебя просто звёздочка проебалась в int v;?
А какая разница, что возвращает эта функция? Ты никак корректно не можешь использовать аддресс.
Это что такое?
Переменную не используешь, компилятор ее оптимизирует нахуй. Наверное. Подробнее в дизасме. Лучше передавай аргумент, удостоверься, что передается в стеке (можешь variadic-функцию сделать) и возвращай его адрес. Будет надежнее.
Ну сделай ее extern, скажи __attribute__((noinline))__, че ты как маленький-то. Ну и variadic-функции хуево инлайнятся, если что.
тогда так:
void zalupa(uintptr_t huibes)
{
int v;
v=v;
huibes =(uintptr_t)&v;
}
int
main(void)
{
uintptr_t huibes;
zalupa(&huibes);
printf("zalupa govorit huibes = %p", huibes);
}
https://m.youtube.com/watch?feature=youtu.be&v=iHzqPHVRLX0
Тут звёздочку перед хуибесом двач не распечатал - должна была стоять (там хуибес курсивным стал почему-то).
Ну я там выше примерно это и предлагал. Да, тут компилятор не осилил... пока.
uintptr_t zalupa(void)
{
int volatile v;
register uintptr_t r1 = (uintptr_t)&v;
return r1;
}
Нельзя, т.к. ты до сих пор не понял, что драйверы — и есть основное назначение языка (хотя бы уже из-за того, что во многих ОС на низком уровне отсутствуют возможности более крутых языков).
И у тебя, скорее всего, неправильный стиль кодирования на нём включая скобочки
Ну ладно, освою гтк и забью тогда.
со своим уставом в чужой монастырь не ходят, поэтому стиль соблюдаю
Кстати, почему названия функций стандартной библиотеки так сокращены сильно? Почему не string_length вместо strlen и т.д.? Иногда бывает совсем неочевидно из-за этого. Это связано с давними временами и ограничениями какими-то?
ограничением мозга. советую более крутые языки.
В те времена, когда си был популярен, было модно писать так, чтобы никто не понял. Чем меньше людей понимают твой код - тем ты круче как разработчик. Сейчас все наоборот.
>Сейчас все наоборот.
Чем меньше людей понимают твой код - тем твои подвороты круче среди смузихлебов
> Кстати, почему названия функций стандартной библиотеки так сокращены сильно? Почему не string_length вместо strlen и т.д.?
Ну и чё? В питухоне тоже есть всякие len, chr, repr. Стандартная либа на то и стандартная, что её заучиваешь наравне с языком. Для меня лично профит в том, что более сокращённые именования функций не загромождают код лишний раз. Но когда свои функции пишешь, наверно, такое именование плохая практика.
я уже блядь заебался геттеры писать, если ещё один геттер увижу- переебу кому-то. пикрелейтед работает, но такая декларация засирает класс ещё мощнее.
макросами как-то можно получить имя класса? может дружбу по другому можно организовать?
На x86 при входе в функцию указатель стека всегда на адрес возврата указывает. Просто call так работает. На каких-нибудь ARM с ихними link register-ами не так.
ясно. а тут можешь объяснить что происходит после вызова? я часа 2 уже просто нихуя не понимаю. https://pastebin.com/uXHsnuSg
или в мейне и возврат какой-то хитрый?
ну вроде срастается картина. я чё-то сразу не всосал, что там сначала декремент.
Ну короч у тебя есть source encoding (кодировка исходника) и execution encoding (кодировка, с которой работает программа), и при компиляции строковые литералы преобразуются из первой во вторую. u8 - это специальный тип строковых литералов, хранящит только UTF-8, при компиляции их содержимое преобразуется из кодировки исходника в UTF-8. Это все не имеет особого смысла под Linux (там по умолчанию source charset = execution charset = UTF-8), а вот в винде у тебя может быть исходник в UTF-16 и execution-кодировка Windows-1251 (например, в студии UTF-8 в качестве execution-кодировки нихуя не поддерживается). И если ты хочешь, например, генерить какой-нибудь HTML в коде, то u8 для тебя.
> На Windows u8 отображает кракозябры
Потому что интерфейс и консоль в UTF-16 (-W функции) или в Windows-1251 (-A функции).
Да в джаве вообще нихуя нет.
Джаву просто делали слегка позже, учитывая ошибки предшественников. В том числе и эту.
480x636, 0:09
все байтоебствуете, ироды?
Спасибо!
> Когда складывается float с маленьким значением и float с большим, то это работает дольше
С чего бы вдруг?
Решил написать скрипты CMake для микроконтроллера по образцу https://github.com/ObKo/stm32-cmake Проблема в том, что я не до конца понимаю как и когда выполняется код из тулчейн файлов. Например, когда я вставил в https://github.com/ObKo/stm32-cmake/blob/master/cmake/gcc_stm32.cmake#L15 строку:
>message("TOOLCHAIN_PREFIX = ${TOOLCHAIN_PREFIX}")
Получилась ерунда (на картинке). Почему этот код выполнился несколько раз? Почему в эту переменную переданный параметр попадал не всегда? Когда выводилось "/usr", этот скрипт очевидно давал неправильный результат, но в итоге в кэше cmake оказались правильные значения. Если при отсутствии этой переменной не выставлять значение по умолчанию, а выдавать ошибку и останавливать выполнение, то оно в таком виде работать не будет. Так как правильно делать?
> Что делать
Ничего. Если у тебя возникают денормализованные флоаты, то они либо тебе нужны, либо у тебя баг в вычислениях.
в мэйк есть флаг вывода отладочной инфы, где можно понять почему сработало правило, в симэйк думаю тоже такое есть.
char 卐names[] = {"LANG", "DISPLAY", "USER", "PWD", "HOME", "TERM", "SHELL", "LOGNAME"};
All rigth.
char 卐卐names=...
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
note: (near initialization for ‘names’)
warning: excess elements in scalar initializer
Сегфолт при старте.
char names[][]
error: array type has incomplete element type ‘char[]’
Заодно оставил себе заметку https://a.pomf.cat/esrkyu.c
А, ну, почему [][] не работает, ясно - там со второго должны быть указаны размеры, да?
А что не так с names?
Есть один весьма объемный кусок кода на Ruby который течет, и течет, видимо, из частей писаных на C, т.к. при растущем как на дрожжах RSS рубишная куча в объеме не меняется. Задумал я слазить в кучу сишную, и столкнулся с проблемой.
Допустим выставляю я MALLOC_CONF='prof_leak:true,lg_prof_sample:0,prof_final:true,stats_print:true', запускаю свой код. В самом стартовом состоянии это все вместе с фреймворком для обработки фоновых задач весит 200+Мб. Жму Ctrl+C, получаю статы и нихуя не понимаю:
https://pastebin.com/RiMLtqA6
Это значительно меньше чем я ожидал, и эти цифры не меняются несмотря на реальный вес процесса. Очевидно где-то я наебался когда jemalloc заводил. В чем дело может быть?
Господа, иногда пишу под микроконтроллеры на си, но основной язык для меня - кресты. Как повысить свою грамотность в си? Что читать в качестве справки, чтобы стать профессионалом?
Прату, стандарт.
или это конструкция на уровне компилятора - он определяет и препятствует этому всему?
тогда что, написать самому лонгджамп - нереально?
setjmp сохраняет позицию стека, но не его содержимое. Если ты после setjmp изменил значение локальной переменной и сделал longjmp, значение переменной может остаться измененным (чтобы изменения гарантированно произошли, перенменная должна быть volatile).
> написать самому лонгджамп - нереально?
Реально, берешь ассемблер под целевую архитектуру и пишешь.
Как мне подставить переменную на место "$'H'"? Подскажет кто?
>3 makefile
Не используй инлайн-ассемблер! Не используй его, сука. Если не можешь обойтись без ассемблера, сделай отдельный .S файл рядом и ассемблируй его отдельно. Тогда тебе не будет мучительно больно пару лет спустя этот асм из кода вычищать. Но в целом, в GCC на всю голову ебнутый инлайн асм, требующий указывать входные и выходные переменные примерно так: https://ideone.com/8da7N
>>1093631
> первый скрин
Ты объявил функцию puts внутри функции print_str. Но не вызвал. Объявления от вызовов отличаются наличием типа возвращаемого значения (видишь int слева?) и типов формальных аргументов (видишь const char ∗ в скобочках?). Скажи так: puts(str). А объявлять ее вообще не нужно, она уже объявлена в stdio.h, и stdio.h у тебя заинклужен.
сук случ приклеилось
но а как же невидимые временные переменные, типа расчёта смещений? например до сет джампа пушется указатель на массив, а после в него производится add до конкретного - и всё, посос.
> невидимые временные переменные
Такие вещи обычно не перемежаются вызовами функций. До вызова у тебя либо уже посчитан ебаный указатель, либо еще не посчитан и будет посчитан в ветке if. Или я хуй знаю, что ты там имеешь в виду, показывай код - обсудим.
Хотя вообще-то ты прав, компилятор может, например, реюзать переменные, и если он вообще не знает, что такое setjmp, какие-нибудь оптимизации могут все испортить.
смотри, есть 3 поля, первое говорит о выходящих, второе о входящих, третье говорит что внутри кода изменятся используются конкретные регистры - они изменятся.
при указании в первые 2 поля, можно указывает в какой регистр из задвигать, или в любой, или что это указатель на память.
короче как-то так:
__asm__ ("addl $12 , %0\n"::"a"(va):);
в %0 уже будет нужное тебе значение, это будет регистр eax.
ах да, если используешь входящие значения, тогда регистры придётся указывать через 2 %.
херово, не хочется всю функцию в асемблере писать. может как-то порезать код на функции...
причём странно, эти функции с проверкой стека, подставляются только после -O (приписка _chk). я говорю про gcc и linux.
Чего ты добиться-то пытаешься? Ты ведь можешь стейт setjmp в глобальной переменной хранить или вообще в контексте, вызывать дочерние функции, передавать туда свой стейт и выпрыгивать из них наружу при необходимости. Алсо, про временные переменные и реюз переменных я говорил в контексте абстрактного не соответствующего стандарту компилятора,-который не знает про существование setjmp, но на практике он знает и обязан сделать так, чтобы поведение соответствовало предписанному сепецификации.
>>1093671
Ты там сплоит пишешь или что? setjmp должен работать независимо от -O и проверок. Если не работает - это баг компилятора.
просто стандартный лонгджамп не предполагает такие прыжки. прыжки в какбы мёртвую функцию, но на деле она специально огорожена куском своего стекпространства.
Ну отключай тогда оптимизации для функции, в которую впрыгиваешь. #pragma GCC optimize, вся хуйня.
Ну ты же понимаешь, что с оптимизирующими компиляторами нельзя делать никакой магии, выходящей за пределы стандарта, если только ты сам не пишешь этот компилятор?
Как выбрать количество global work, которое указывается в clEnqueueNDRangeKernel? Делаю простой тест, чтобы опытным путём выяснить оптимальное значение для алгоритма и, чем больше его выставляю, тем больше получается скорость. Например, при 1024 скорость около 9000 в секунду, если поставить 4096, то уже возрастает больше, чем в 2 раза и составляет около 22000, если 16k, то прирост уже не так значителен, примерно до 24000. Как высчитать его, да и ещё не только для моей видеокарты? Пробовал через clGetKernelWorkGroupInfo с параметрами CL_KERNEL_WORK_GROUP_SIZE и CL_KERNEL_COMPILE_WORK_GROUP_SIZE (подсмотрел в hashcat), но он выдаёт очень маленькое значение 256.
спрашивай в /gd. здесь только школьники сидят,а там может и есть шанс
*i = 0;
Что это значит?
* разыменовывает указатель, т.е., работает с тем объектом, на который указывает указатель. Т.е., пиште 0 по адресу, который хранится в i.
>>1094069
> И почему внутри sizeof можно нулевой указатель разыменовывать?
Потому что sizeof не выполняет фактического доступа, вся необходимая информация существует уже на этапе компиляции. Исключение: для VLA sizeof обращается к счетчику элементов в массиве в рантайме.
>* разыменовывает указатель, т.е., работает с тем объектом, на который указывает указатель. Т.е., пиште 0 по адресу, который хранится в i.
Блять. Тупонул. Конечно так можно. Вот на пике проблема в чём? Указатели разыменовываются при передачи в функцию, а она ожидает указатель, а не значение, а поскольку значение нули, то в функцию передались нулевые указатели?
>Потому что sizeof не выполняет фактического доступа, вся необходимая информация существует уже на этапе компиляции. Исключение: для VLA sizeof обращается к счетчику элементов в массиве в рантайме.
А результат почему возвращает такой, который возвращает?
У тебя на пике s и c указывают на мусор, т.к., ты их не инициализировал. Затем ты записал два числа с плавающей точкой (нули) по рандомным адресам в памяти. Или оно свалилось при попытке это сделать. Алсо, printf не печатает указатели на float, тебе во-первых их нужно дереференсить, а во-вторых, указать форматную строку первым аргументом (printf("%f %f\n", ∗s, ∗c);
Алсо, ты скорее всего имел в виду float s = 0.0f, c = 0.0f; frenel(1337.0f, &s, &c); printf("%f %f\n", s, c);
> А результат почему возвращает такой, который возвращает?
Какой-то непонятный вопрос.
Ты мог подумать, что я новичок. Но я не новичок! Просто давно си не пользовался. И вообще код не мой. Если забыть про printf и то, что присвоение мусорным указателям может выбросить segmentation fault, то в функцию попадут нулевые указатели?
>Какой-то непонятный вопрос.
Если внутри sizeof разыменовывать нулевой указатель, то он вернут какой-то результат. Этот результат где-нибудь определен?
> Если внутри sizeof разыменовывать нулевой указатель
Ты чего-то явно не понимаешь. sizeof() насрать на значения, он работает с типами. Если ты передаешь внутрь sizeof значение, сначала вычисляется его тип (и кроме случая с VLA это отлично делается во время компиляции). Например, у тебя int ∗foo = NULL; sizeof(int ∗) вернет размер указателя на int;
sizeof(int) вернет размер инта;
sizeof(foo) посмотрит, что у foo тип - int ∗, далее см. выше;
sizeof(∗foo) посмотрит, что при дереференсе int ∗ получается int, далее см. выше;
sizeof(1) значет, что тип численного литерала int, далее см. выше;
sizeof(1.0) знает, что тип численного литерала double, ну ты пони;
sizeof("foo") вычисляет размер типа char[4];
int ∗bar = malloc(100500); sizeof(bar) вернет размер указателя на int, sizeof(∗bar) вернет размер инта, ему абсолютно фиолетово, сколько ты там выделил и выделял ли вообще;
и т. д. Не нужно ничего дереференсить, чтобы посчитать размер!
Вопросы для самоконтроля:
void ∗ptr = NULL;
printf("%zu\n", sizeof(ptr));
printf("%zu\n", sizeof(∗ptr));
printf("%zu\n", sizeof('x'));
Это стандартный пролог - создать кадр стека, и адресоваться внутри него относительно rbp/ebp, вне зависимости, сколько там локальных переменных выделено и сколько пушей с аргументами для дочерних функций.
С чего ты так решил? Чем main() особенная? У тебя там нет автоматических переменных и аргументов?
main это зачастую не первая выполняемая функция.
То, что обычно компилируется cc *.c теперь требует многочасовой ебли с макросами в попытках заставить эту ебанину компилироваться - программист занят, программист получает зарплату, все счастливы.
Еще не видел ни одного проекта, который стало бы проще собирать после перехода на CMake. Вот проекты, которые внезапно стало невозможно собрать на какой-нибудь винде - видел в ассортименте.
Вот же её прототип, не:
FILE fopen(const char fname, const char *mode)
Возвращается же указатель. Вот я и погорячился подумав было что память для таблицы потока должна выделяться динамически, пардон.
Вакаба звёздочки поела.
Никто не запрещает стандартной библиотеке выделять память динамически, но обычно там табличка (не)достаточного размера: https://ideone.com/V5fQJo
> где погуглить-то?
https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/libio/iofopen.c#L72
Такие дела.
> В обработчике сигнала теперь файлы не пооткрывать.
А то иначе бы ты пооткрывал. Если сигнал вызван не raise(), то ты вообще не имеешь права вызывать из стандартной библиотеки что-либо, кроме signal(), exit() и товарищей. Даже за использование какого-нибудь сраного memcpy() тебе обещают UB. Именно из-за подобных обещаний Си - говно, как и его стандартная библиотека, а кроссплатформенность этого языка - миф.
>Именно из-за подобных обещаний Си - говно, как и его стандартная библиотека, а кроссплатформенность этого языка - миф.
каков накал, какая экспрессия.
Анон, перевел одну большую машину состояний из стандартной таблицы указателей на функции в кучу switch-case. Получилось что-то такое https://ideone.com/vGnMEu . Размер таблицы стал намного меньше (в предыдущей реализации она вобще хранилась в ОЗУ вместо кода), компилятор прекрасно соптимизировал, это добро работает быстрее, чем таблица указателей. Единственный минус - слишком много кода, 2000 строчек вместо сотни, аж kdiff3 подвисает когда грузит файл. Вопрос: можно ли препроцессором задефайнить хороший макрос, который сократил бы эти switch-caseы для каждого события в одну строку? Или не стоит ебаться со всем этим?
Что мешает тоже самое написать в CMake? И чем мне собирать проекты чуть выше уровня laba1.c для микроконтроллеров?
> Что мешает тоже самое написать в CMake?
Адская магия при выборе тулсета? Адская магия при попытке воткнуть нужные ключи тулсету? Адская магия при попытке отучить его тестировать тулсет? Адская магия и невероятное количество захардкоженных путей внутри тысячи файлов, которые обеспечивают его работу? Уж лучше SCons взять.
QBS или тот же CMake. Какая нахуй разница для какого железа твой компилятор.
Создать два потока и в каждом pipe или сокет.
Отправить из первого потока сообщение во второй.
Выполнить задание и отправить из второго сообщение в первый.
.
.
.
PROFIT!!!
придумай многопоточную сортировку.
В общем-то да, макросами препроцессора таки хуй что получится сделать без перепиливания кода, так что можно потерпеть.
> без пространств имён
В хедерочках интерфейсы, в с - внутренняя кухня. кухня с кухней общаются только через интерфейсы в хедерочках. Если в коде не будет никаких extern - вот тебе и инкапсуляция.
> перегрузок
см. OpenGL
>куда девать глобальные переменные?
В с-файлы, очевидно жеж. Всю внутреннюю кухню как-нибудь ___huitka обзывай.
Заодно си избавят тебя от головного мозга и научат cache-friendliness и data-oriented design. И ты больше не будешь конструировать невлезающих в кеш монстров а будешь их по разным мемори пулам раскладывать.
Вот так не делай:
https://github.com/orangeduck/Corange
sprintf тебе в помощь
Спасибо. Скажите мне напоследок, почему тот же sprintf нормально записывает 4-значное число в массив состоящий из двух элементов(array[2])? С маллоком та же история.
Хули ошибки нет?
находите ошибке сами.
Иногда - это когда неаллоцированная память будет занята кем-то другим?
Мне казалось, что такие выходки на уровне компиляции должны отлавливаться.
> Всю внутреннюю кухню как-нибудь ___huitka обзывай.
Очень плохой совет. Идентификаторы, начинающиеся с подчеркивания, поголовно зарезервированы (с двух подчеркиваний - стандартом, с одного - компилятором). Лучше выдумать короткий префикс (2-4 символа).
>>1095642
> почему тот же sprintf нормально записывает 4-значное число в массив состоящий из двух элементов
Потому что тебе везет, вот почему. Компилятор, скорее всего, выравнивает размер массива на 4. Или не выравнивает, но ты перезаписываешь что-то не очень важное. То же и с маллоком. Никогда так не делай, не полагайся на особенности компилятора и вообще не стесняйся просить -fsanitize=address объяснять тебе, что ты криворукий уебан.
пользуйся статическими анализаторами, валгриндом. компилятор не должен знать что там произойдёт с указателем который ты передал.
ПЕРЕКАТ: >>1095677 (OP)
ПЕРЕКАТ: >>1095677 (OP)
ПЕРЕКАТ: >>1095677 (OP)
ПЕРЕКАТ: >>1095677 (OP)
Это копия, сохраненная 12 декабря 2017 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.