Вы видите копию треда, сохраненную 11 июля 2022 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ https://wandbox.org/ или https://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Brian Kernighan, Dennis Ritchie "The C Programming Language": http://www.cypress.com/file/56651/download
- Stephen Prata "C Primer Plus, 6th Edition" (2014): относительно свежая, знает про C89/C99/C11, описывает различия, объемная (около тысячи страниц), годная, с вопросами, упражнениями и ответами. Читать после K&R или до.
- Zed A. Shaw "Learn C the Hard Way" (2015): годное пособие для гуманитариев для гуманитариев!
- Немного примеров хорошего стиля: http://www.oualline.com/books.free/style/index.html
- ООП, например: http://www.cs.rit.edu/~ats/books/ooc.pdf
- Стандарт ISO/IEC 9899:1999 (C99): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf (драфт)
- Стандарт ISO/IEC 9899:2011 (C11): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (драфт)
- Черновик стандарта ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf (февраль 2020, с диффами)
- Последний черновик ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf (декабрь 2020)
Чем компилировать:
- Очевидный GCC.
- clang: оче годно, батя рекомендует.
- Intel C++ Compiler: оптимизации, тысячи их.
- Visual Studio Community Edition: внезапно этим стало можно пользоваться, особенно с тулсетом clang/C2. Поддержка C11 на уровне "есть все, что тебе понадобится в реальном проекте плюс кривая библиотека". Анализатор кода в комплекте.
- Pelles C (шиндоуз онли): поучиться, вкатиться в C11 (стандарт полностью реализован, имеются в том числе threads.h и прочие stdatomic.h), но количество багов в оптимизаторе и редкие апдейты напрочь отбивают желание собирать этим что-то сколько-нибудь серьезное.
- TCC: очень маленький компилятор с багами и поддержкой C99. С ключом -run умеет компилировать код в память и запускать его, что позволяет писать скрипты прямо на сишечке.
Что еще почитать:
http://c-faq.com/
FAQ из comp.lang.c. Древний, но все еще актуален.
Samuel P. Harbison, Guy L. Steele Jr. "C: A Reference Manual, 5th Edition" (2002)
Ебаный пересказ стандартов C89 и C99 (включая стандартную библиотеку). Для не осиливающих стандарт в оригинале. Читать в качестве подготовки к собеседованиям (есть задачник с ответами) и для ознакомления с масштабами пиздеца перед написанием своего парсера/компилера.
Peter Van Der Linden "Expert C Programming. Deep C Secrets" (1994)
"Си: грязные истории". Смехуечки, немного объяснений, чем обусловлены особенности языка, всем известные подводные камни кто там ругал косяки в JS? у нас в сишечке их гораздо больше, просто они лучше спрятаны, немного байтоебли и непонятно откуда взявшаяся глава про старинные плюсы. Читать в качестве сказки на ночь (на пару вечеров хватит).
Richard M. Reese "Understanding and Using C Pointers. Core Techniques for Memory Management" (2013) - почитать, вкатиться в указатели.
Ben Klemens "21st Century C: C Tips from the New School" (2012)
Paul Deitel, Harvey Deitel "C for Programmers with an Introduction to C11" (2013)
Stephen G. Koch@n "Programming in C (3rd Edition или 4th Edition, если найдется)" (2014)
MISRA Ltd. "Guidelines for the Use of the C Language in Critical Systems" (2013)
Набор рекомендаций по написанию надежного кода на C (промышленный стандарт). Читать - однозначно, следовать - вдумчиво и без фанатизма. Также можно посмотреть https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard и http://web.archive.org/web/20190213011655/homepages.inf.ed.ac.uk/dts/pm/Papers/nasa-c-style.pdf
Еще более длинный список: http://www.iso-9899.info/wiki/Books#Learning_C
https://github.com/kozross/awesome-c
Онлайн-утилиты:
- https://godbolt.org/ - Compiler Explorer позволяет посмотреть выхлоп компиляторов для введенного куска кода (больше полусотни разных версий компиляторов).
- http://cdecl.org/ - С Gibberish ↔ English помогает читать сложные сишные декларации.
Прошлые треды:
- №68: http://arhivach.net/thread/667171/
- №69: http://arhivach.net/thread/688454/
- №70: http://arhivach.net/thread/713839/ >>2119301 (OP)
FIFO?
С++ уже почти нормальный язык, за некоторыми исключениями оставшимися от наследия си.
Rust нормальный язык, вполне годный для замены первого говна.
Единственный вопрос треда - Нахуя вы продолжаете жрать говно?
А почему ты считаешь что всем одинаково не нравится жрать дерьмо? На вкус и цвет как бы.
Си лучший из лучших, прошло 40 лет, но лучше си врядли что-то появится.
С++ уже почти нормальный язык, за некоторыми исключениеми добавлеными поверх си
Rust самый конченый язык, создан СЖВ скамом, чтобы выебать программиста в жопу своим борроу чекером и конченым синтаксисом, чтобы пополнить ряды пидорасов.
Единственный вопрос треда - почему мы тут все такие пиздатые?
Глянь проекты трансух и фурриебов, обнаружишь, что почти все они железнячники и пишут на си. Про трансух на cppcon все знают. На расте же пишут белые цисгендерные мужчины. Даже на rust survey были диаграммы, в которых 90% растоманов не относили себя к меньшинствам.
> Глянь проекты трансух и фурриебов, обнаружишь, что почти все они железнячники и пишут на си
так раньше было, да пидоры писали на С, как и все, ничего плохого в этом не вижу. Но вскоре времена поменялись, пидоры фемки и вские другие залупские меньшинства начали вещать свои извращеные идеи громче всех, эмулируя своим ором массовую поддержку (на самом деле их как было 1% так и осталось). Это сказалось на многие вещи, БЛМ, поблажки неграм и пидорам почти во всех сферах, также и в программистской среде это тоже случилось (пример - замены master slave). Из-за общего тренда (а не из-за своих личностных качеств) эти никчемные фемки и пидоры дорвались до власти, и смогли навязать что надо написать свой раст. Т. к. идея его создания высосана из пальца, а истинная причина - (они даже это во всех статьях так и пишут) убить детище белых гетеросексуальных мужчин (с с++), то новый язык получился как и собственно идея его создания - КУСКОМ ГОВНА.
> Даже на rust survey были диаграммы, в которых 90% растоманов не относили себя к меньшинствам.
ага, спасибо что посчитал по головам тупых ебланов. Будет новый тренд ебать своих мамок - увидишь теже лица
>Си говно говна, хуже чем си вряд ли что-то есть.
Си это такой высокоуровневый ассемблер. Например, когда я пишу на Си, я знаю какой машинный код сгенерит компилятор.
Си++ это (Си + синтаксический сахар). Почти всегда я тоже знаю что сгенерирует компилятор. Но только почти.
Во-первых, это слова Линуса Торвальдса. Во-вторых, давай будем честны друг с другом, ты ничего такого низкоуровневого не пишешь, чтобы знать какой там ассемблер будет сгенерирован.
Смысл высокоуровневых языков, в том, чтобы во-первых, разработка конечного продукта происходила быстрее, и во-вторых, чтобы в этом конечном продукте было меньше багов. Говносишка как ты и сказал это реально высокоуровневый ассемблер, где среднестатистическая макака наделает сотни багов с доступом к памяти, мемори ликов и если дело происходит в многопоточной среде кучу data race'ов. Я конечно понимаю что среднестатистическая макака считает себя ассом и думает что она не наделает ошибок, но как показывает статистика это далеко не так.
К тому же нормальный человек видит задачу и решает ее высокоуровневым методом, а говнари на си, будут 90% времени ублажать компилятор и процессор. А на выходе получат только баганное говно которое будет постоянно падать и жрать память из-за мемориликов.
libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain@16'
В интернете пишут, что типа делается не в консольном приложении и нет функции main. Проект не мой, но нужно скомпилировать. Если тупо засунуть в рандомный файл эту функцию - то, конечно, компилируется и получается экзешник но программа там не работает.
Обычно линкер отлично сам детектит, какая функция есть (main или WinMain), подсовывает соответствующий стартап, и все работает. Без исходников сложно понять, что ты делаешь не так, и что именно ты сломал. Попробуй -mconsole сказать.
>>165865
> нормальный человек видит задачу и решает ее высокоуровневым методом
Он на 100% не знает, что там внутри высокоуровневого метода, документация почти никогда четко не описывает контракт, и мы получаем что? Правильно, вот это твое
> сотни багов с доступом к памяти, мемори ликов и если дело происходит в многопоточной среде кучу data race'ов
Особенно последнее. И как он будет это решать? Отладить все эти мегатонны говна невозможно, поэтому он бездумно натыкает мьютексов, но ничего не изменится, все станет только хуже.
Плохой код на крестах писать гораздо проще, чем на сишке. А если заодно вспомнить, что кресты - это не один, а четыре разных языка (C с классамии и три основных стандарта), становится ясно, что лучше на крестах не писать вообще.
Как лучше это сделать:
1. extern my_data_array
и инициализировать этот массив в файле, включённом только в нужном таргете
2. void register_data_array(_type d, size_t s) { my_data_array = d; my_data_size = s;}
и вызвать её во время старта, передав туда нужные данные (выбранные по какому-то принципу
3. Пойти вопреки гайдлайнам и вынести объявление и инициализацию этого static массива в другой .c файл (где уже и будет ветвление в зависимости от таргета) и просто сделать "#include my_data_array.c"?
(Код для мк stm32, но их тред умер.)
Минусы первых двух вариантов в том, что размер массива уже не известен на стадии компиляции и становится проблематичным создание второго массива того же размера, разве что опять же делать его extern или передавать в register_data_array. Уж не знаю, как этого можно избежать.
При чем тут С++. Я согласен, что на С++ нахуевертить по незнанию можно так же как и на Си а то еще хуже. Я говорю о высокоуровневых языках типа хаскеля, где проблемы решаются высокими абстракциями, без всяких там мутексов и прочей низкоуровневой хуйни. Где априори не может быть дата рейсов, сегфолтов и мемориликов.
Но даже если брать с++, то во-первых, мы не берем в расчет всяких джунов, а берем в расчет среднего мидла, которы уже умеет программировать на своем языке и знает где вставить мутекс и т.д. и если взять такого же среднего разработчика на си и дать им одну и ту же задачу, шанс того что на си будет больше багов намного больше и время которое он затратить реализуя какую-то сложную вещь на си написывая все с нуля начиная от примитивных дата стракчерс будет вообще не сопоставимо со временем которое потратит С++-Чэд, просто заинклюдя в свой проект буст и реша проблему в пару сотен строк.
>Си говно говна, хуже чем си вряд ли что-то есть.
>С++ уже почти нормальный язык, за некоторыми исключениями оставшимися от наследия си.
>Rust нормальный язык, вполне годный для замены первого говна.
На новой архитектуре/платформе компилятор и окружение раста не собирается без компилятора си и плюсов, вот и думай теперь.
И нахуя ты это высрал?
На новой архитектуре без реализации компилятора хоть какого-то языка нихуя не соберется. При чем тут си?
Хуйню не неси
> размер массива уже не известен на стадии компиляции
Есть еще четыре возможных решения:
- вместо register сделать функцию-геттер, которой будет видно определение, и она сможет возвращать и указатель, и массив (плюсы - не нужно заботиться о том, не забыли ли вызвать register при инициализации);
- создавать переменную с размером с помощью макроса и магии (вполне нлом, если стайлгайд осуждает макросы);
- положить массив в отдельную секцию и считать размер секции
(типичное решение в embedded, когда и компилятор тебе известен, и линкер ты контролируешь)
- ну и возможно стоит подумать о том, нужен ли тебе вообще размер - возможно, нуль-терминатор в конце тоже подойдет.
Я бы сделал register, раз уже известно, что код будет переиспользоваться. Тем более на STM32 писать подобное в традиции.
Примеры первых трех вариантов https://wandbox.org/permlink/qTi8ZGJFSNXYQkY4 (вкладка array.c в редакторе).
>И нахуя ты это высрал?
>При чем тут си?
При том, что где будет раст, там всегда будет Си и плюсы. А вот в обратную сторону это не работает. Тогда встает вопрос, нахрена он нужен и как он может заменить си, если сам без него не собирается?
Ты несёшь абсолютную хуйню. Ты походу вообще не врубаешься как работают бинарники в ос
>Во-первых, это слова Линуса Торвальдса.
Может быть. Но это, пожалуй, единственное в чём я разднлю его взгляды.
>Во-вторых, давай будем честны друг с другом, ты ничего такого низкоуровневого не пишешь, чтобы знать какой там ассемблер будет сгенерирован.
Если ты давно тут тусуешься, то наверно видишь вот такие скриншоты. 75% из них мои. С учётом того, что обычно я не использую плавающую запятую, а только целочисленную арифметику (данный скриншот исключение и проект не мой) то вполне хорошо представляю что сгенирует компилятор.
>А на выходе получат только баганное говно которое будет постоянно падать и жрать память из-за мемориликов.
Если ты больше 20 лет пишешь на Си, то твои программы не будут падать и течь, потому что это всё пройденный этап.
>Эти FPU инструкциии
Лол, а че sse не завезли?
>Если ты давно тут тусуешься,
Нет, я тут особо не тусуюсь и не знаю кто ты и что ты делаешь, я иногда забегаю засрать макак от нефиг делать.
Но твои маняпуляции с ассемблером лишены смысла, ибо где нужна пиздецовая оптимизация берут интринсики и пишут на них, тут хоть на с++ пиши хоть на расте хоть на хуясте, ассемблер будет одинаковый. В остально смотреть что там высрал компилятор - бесполезное занятие. Я в свое время тоже и на си писал и на ассемблере и интринсики юзал в хеви оптимизированных функциях. Но я пришел к тому что си - это говно которое несет вред и по-хорошему его надо запретить вообще.
>Если ты больше 20 лет пишешь на Си, то твои программы не будут падать и течь, потому что это всё пройденный этап.
Если ты больше 20 лет пишешь на си, то с тобой явно что-то не так, при чем сильно.
>Если ты больше 20 лет пишешь на си, то с тобой явно что-то не так, при чем сильно.
А кто тебе сказал что я пишу ТОЛЬКО на Си? Зарплату мне платят за C#. На сях и плюсах я пишу для души.
На давай, расскажи мне как ты будешь компилятор раста и прочее окружение портировать на новую архитектуру.
Ты еблан. Даже объяснять тебе что-то лень. Иди учи матчасть. При чем здесь новая архитектура и си? Твой компилятор ( любого языка ) должен преобразовывать высокоуровневый код в машинные инструкции этой архитектуры и взаимодействовать с операционной системой через syscalls, в стандартных люнуксах за это отвечает glibc или аналоги, но никто не мешает тебе сделать тоже самое на другом языке. При чем здесь си еще раз?
>Brian Kernighan, Dennis Ritchie "The C Programming Language":
Хотел бы совета насчёт перевода данной книги, какой самый лучший из всех ? В ориге не осилю, ибо слабо знаю английский.
Есть переиздание 2017 года. Насколько я знаю, там все более-менее норм (кроме цены). Ну и в целом все переводы говно по определению.
>Во-первых, это слова Линуса Торвальдса
А можно пруф? Желательно ссылкой на английскую версию, на lkml.
Правильно ли я понял, что если создать другой указатель pptr и присвоить ему ptr: int pptr = ptr, то я смогу делать все с указателем ptr через pptr, в том числе и free(pptr)=>очищу так же и ptr, т.к. все это ссылается на один адрес в памяти, это справедливо будет?
прочитал как Керриган.
Тут проблема есть.
printf("10.12 = %.15lf\n", 10.12);
printf("10.14 = %.15lf\n", 10.14);
Выдает ненужные числа после запятой. Это связано с байтами но я не вдупляю.
Эти числа нельзя представить точно в виде суммы положительных и отрицательных двойки. Округляй или ограничивай количество цифр после запятой более вменяемым числом. Алсо, lf тебе не нужно, ты печатаешь дабл, это просто f, а long double это уже Lf.
*степеней двойки
На ptr твои манипуляции не повлияют, они влияют на объект, на который ссылается ptr. Просто после free объект удалится, но ptr не "очистится", оба указателя будут продолжать одинаково указывать на невалидный объект. Захочешь очистить - пиши NULL в каждый по отдельности.
Спасибо
Нахуй нужны индексы в массиве? Я что, не могу без них обойтись чтоли? Указатели на обычных машинах - это индексы в массиве байтов под названием память.
Проблема в том, что после ассемблера сложно понять, почему нельзя float x = 3.14f; printf("%08lx", ∗(uint32_t ∗)&x).
А кто сказал что нельзя? Может быть тебе надо на экран вывести адрес стека, на котором лежит переменная x.
А в чем тут собственно проблема?
Да, неизвестно какие байты ты получишь, на бульбуляторе с не IEEE-шным флоатом и/или little endian. Правда при условии что размер и выравнивание у типов одинаковое.
мимо из крестотреда
> А в чем тут собственно проблема?
strict aliasing. Стандарт не гарантирует возможность доступа по несовместимому указателю, а компиляторы этим пользуются. В таком простом коде, конечно, не сломается, но в каком-то другом - обязательно.
>>168901
>>169103
Тогда нужен каст не в uint32_t, а хотя бы в uintptr_t (а то сломается на 64 битах) или поменять формат на %p. И с этим после ассемблера тоже сложно смириться. Ты знаешь, что там лежит, а компилятор Си выделывается и не хочет.
> И с этим после ассемблера тоже сложно смириться.
Ой, да ладно. Я сначала Бейсик выучил, потом ассемблер, затем ассемблер другой архитектуры, затем паскаль, затем Си. На Си сложно было переходить, но ассемблер тут не при чём.
> И с этим после ассемблера тоже сложно смириться. Ты знаешь, что там лежит, а компилятор Си выделывается и не хочет.
Вот поэтому я и не осилил си. Слишком много букв а толку ноль.
Один хуй никакой совместимости в реальных проектах между архитектурами не существует, все равно нужно править и переписывать код при любой смене окружения. Что именно даёт си, что все так любят его,мне не ясно. А вот отнимает он очень порядошно.
>strict aliasing.
Отключается параметром компилятора. В майкрософтовских компиляторах его нет вообще.
RUST!!!!!
>Один хуй никакой совместимости в реальных проектах между архитектурами не существует
Сморя чего пишешь, если GUI, то не существует. в остальном хватает #ifdef
Ну и как бы выносишь интерфейсные части в отдельную сущность, а логика платформонезависима. Для многопоточности пишешь свой враппер. И проблема совместимости исчезает.
По сути есть лишь две платформы Windows и Posix-like.
Наконец, если интерфейсная часть твоего проекта получилась больше, чем логическая, то это повод задуматься - нахуй нужен такой такой проект. С вероятностью близкой к 100% это очередная "свистоперделка".
> По сути есть лишь две платформы
"Две" платформы - только для хелловорлдов (даже для хелловорлдов уже две).
На самом деле есть x86/ARM (там уже куча вариантов, у кого какие интринсики есть, какие требования к выравниванию и прочая подобная хуйня). Кроме того, даже процессорных архитектур у тебя все равно сильно больше: как минимум, рано или поздно придется MIPS, RISC-V вон наступает. Плюс у всего этого есть разные разрядности. И ОС. И версии ОС. И разные версии либ.
> в остальном хватает #ifdef
Ты забыл рассказать, сколько строк кода в тех ifdef. В этом вся суть. От того, что ты сложил разные реализации в один файл, они не перестали быть разными, и сишка переносимее не стала.
> логика платформонезависима
Да, пока ты пишешь тормозное говно на жс.
cmake -DCMAKE_YOBA_ABC=1 -DCMAKE_HELL_KNOWS_WHAT=zzz -G "ХуйПоймиЧто". Ошибка! CMAKE_YOBA_ABC теперь надо писать как CMAKE_YOBA_DEF, и похуй, что во всех гайдах утверждается обратное. CMAKE_HELL_KNOWS_WHAT не поддерживается престарелой версией CMake. CMAKE_C_STANDARD=17, я такого не знаю, идите нахуй. И вообще компилятор не найден, зато вот у вас sh.exe есть, поэтому я собирать не буду.
Нет ни одной вменяемой системы сборки. Это как с лефтпадами в жс. Тебе их рекомендуют для не того, чтобы решать проблемы, а для того, чтобы у тех, кто рекомендует, была работа.
>(даже для хелловорлдов уже две
Пиздёжь.
printf есть везде. За редчайшим исключением, типа прошивой для какой-то экзотической ёбы. Да то не факт, что его там нет, скорее всего будет через JTAG писать в терминал.
блять, там ещё указатель стоит перед zalupa, на дваче не отображается, и в принтф перед zalupa разыменователь стоит
Ну и че ты скинул, оно тоже Н выдает. Для справки цлев, компилю через мсвц.
Я же тебе выше отписал, что там звёздочка должна быть, на дваче она не отображается
А лол, ну так на вопрос то ответь, какого хуя с двойными кавычками такие фокусы нужны, схуя они не эквивалентны одинарным для ситуации одного чара.
Я сначала скинул, потом обновил тредю
Потому что 2 кавычки это строка, а когда ты бля выводишь через %c ты выводишь СИМВОЛ, %c - char/charachter/символ
Вот тебе пример с %c и двойными кавычками и %s.
Это я понимаю, я не понимаю почему Н выводится без фокусов с указателями. Что вообще такое Н? Ну ок я дебс в чар строку запихнул и решил ее через %с вывести лулзов ради. Почему оно не кидает ошибку или первый символ строки, а кидает какой-то Н. В чем смысл?
Просто потому. я сделал такой же пример как и у тебя, у меня вывело j, не придавай этому большого значения
> Ну ок я дебс в чар строку запихнул
Это как?
В твоём примере zalupa это указатель на строку. Когда ты перед ним пишешь звёздочку, это разименовывание указателя называется, на выходе будет первый символ.
А у тебя 'A' кириллическая или латинская? Вероятно кириллическая, потому что другой ошибки быть там не может.
Понял, пасиб
>Но я пришел к тому что си - это говно которое несет вред и по-хорошему его надо запретить вообще.
Можешь подробнее разложить, почему говно?
да он шизик, сбежал с соседнего треда по расту самоутвердиться
Сап, нюфажеский вопрос. Есть алгебраическая функция, непрерывная, ф1. Есть функция, которая считает производную от этой функции, назовем ее ф2. Но вот есть функция, которой нужна и функция ф1 и функция взятия производной ф2, пусть будет ф3, например разложение в ряд или что-то еще. Как добавить ф2 в ф3 в качестве аргумента чтобы ничего не сломалось?
Сам нашёл - https://gcc.gnu.org/onlinedocs/gcc/Structure-Layout-Pragmas.html.
Заодно и ответ на >>170308-вопрос тоже здесь
оказывается в дваче есть не все ответы
Выделять на стеке можно (не забывая, что стек не резиновый), передавать мелкие тоже можно (например, чтобы наколхозить именованные аргументы), крупные/разнородные лучше передавать указателем.
Ты не в том треде интересуешься.
Тут нужен код.
А вообще гугли "указатель на функцию".
Его можно передавать как аргумент функции.
И чтобы не ебацца понапрасну, объяви его как typedef, инвче хуй голову сломает - получится нечитаемая конструкция, которую даже автор кода не поймёт.
А через typedef указателя на функцию получится вполне читаемое.
Нет. Можешь сделать typedef структуре из трех байтов, но арифметики к ней конечно не будет. Нативно 24 бита будет только там, где 24-битные инты. Старые dsp например.
Да, структура из трёх char'ов без packing'а.
typedef struct {
unsigned i:24;
} int24_s;
main(){
int24_s s;
s.i = 1u<<24;
printf("%x\n",s.i);
printf("%x\n",--s.i);
printf("%x\n",++s.i);
}
Учусь в шараге, учат сям (точнее, гибриду сей и с++, так как препу не хочется учить нас сишному вводу-выводу).
Задание: решить методом хорд уравнение arctg(x)-0.5=0.
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double f(double x) {
double y = atan(x) - 0.5;
return y;
}
double h(double a, double b, double d, double e) {
double c, dprog, eprog;
int i = 0;
while ((abs(f(b)-f(a))>e)&&(abs(b-a)>d)) {
c = a + fabs(f(a) / (f(b) - f(a))) (b - a);
if (f(a)f(c)<0) a = c;
else b = c;
i++;
eprog = abs(f(b) - f(a));
dprog = abs(b - a);
}
cout << dprog << endl << flush;
cout << eprog << endl << flush;
cout << i << endl << flush;
return(c);
}
int main() {
double a1, b1, c1, d1, e1;
cin>>a1; cin>>b1; cin>>d1; cin>>e1;
if (f(b1) * f(a1) >= 0) {
cout << "ERROR";
return 1;
}
else {
c1 = h(a1, b1, d1, e1);
cout << c1 << endl << flush;
return 0;
};
}
При a1=-1, b1=1, d1=0.1, e1=0.1 работает нормально, но если задать иные значения - виснет. Если компилировать пошагово непонятно, что с ней - тоже виснет, как только переходит на вычисления.
Это у меня глюки на ноуте или у программы проблемы? Прошу о помощи.
Да, я знаю, что хуй и быдлокодер, но я только учусь
Учусь в шараге, учат сям (точнее, гибриду сей и с++, так как препу не хочется учить нас сишному вводу-выводу).
Задание: решить методом хорд уравнение arctg(x)-0.5=0.
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double f(double x) {
double y = atan(x) - 0.5;
return y;
}
double h(double a, double b, double d, double e) {
double c, dprog, eprog;
int i = 0;
while ((abs(f(b)-f(a))>e)&&(abs(b-a)>d)) {
c = a + fabs(f(a) / (f(b) - f(a))) (b - a);
if (f(a)f(c)<0) a = c;
else b = c;
i++;
eprog = abs(f(b) - f(a));
dprog = abs(b - a);
}
cout << dprog << endl << flush;
cout << eprog << endl << flush;
cout << i << endl << flush;
return(c);
}
int main() {
double a1, b1, c1, d1, e1;
cin>>a1; cin>>b1; cin>>d1; cin>>e1;
if (f(b1) * f(a1) >= 0) {
cout << "ERROR";
return 1;
}
else {
c1 = h(a1, b1, d1, e1);
cout << c1 << endl << flush;
return 0;
};
}
При a1=-1, b1=1, d1=0.1, e1=0.1 работает нормально, но если задать иные значения - виснет. Если компилировать пошагово непонятно, что с ней - тоже виснет, как только переходит на вычисления.
Это у меня глюки на ноуте или у программы проблемы? Прошу о помощи.
Да, я знаю, что хуй и быдлокодер, но я только учусь
А ещё не могу в разметку двача.
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double f(double x) {
double y = atan(x) - 0.5;
return y;
}
double h(double a, double b, double d, double e) {
double c, dprog, eprog;
int i = 0;
while ((abs(f(b)-f(a))>e)&&(abs(b-a)>d)) {
c = a + fabs(f(a) / (f(b) - f(a))) (b - a);
if (f(a)f(c)<0) a = c;
else b = c;
i++;
eprog = abs(f(b) - f(a));
dprog = abs(b - a);
}
cout << dprog << endl << flush;
cout << eprog << endl << flush;
cout << i << endl << flush;
return(c);
}
int main() {
double a1, b1, c1, d1, e1;
cin>>a1; cin>>b1; cin>>d1; cin>>e1;
if (f(b1) * f(a1) >= 0) {
cout << "ERROR";
return 1;
}
else {
c1 = h(a1, b1, d1, e1);
cout << c1 << endl << flush;
return 0;
};
}
А ещё не могу в разметку двача.
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double f(double x) {
double y = atan(x) - 0.5;
return y;
}
double h(double a, double b, double d, double e) {
double c, dprog, eprog;
int i = 0;
while ((abs(f(b)-f(a))>e)&&(abs(b-a)>d)) {
c = a + fabs(f(a) / (f(b) - f(a))) (b - a);
if (f(a)f(c)<0) a = c;
else b = c;
i++;
eprog = abs(f(b) - f(a));
dprog = abs(b - a);
}
cout << dprog << endl << flush;
cout << eprog << endl << flush;
cout << i << endl << flush;
return(c);
}
int main() {
double a1, b1, c1, d1, e1;
cin>>a1; cin>>b1; cin>>d1; cin>>e1;
if (f(b1) * f(a1) >= 0) {
cout << "ERROR";
return 1;
}
else {
c1 = h(a1, b1, d1, e1);
cout << c1 << endl << flush;
return 0;
};
}
> учат сям (точнее, гибриду сей и с++, так как препу не хочется учить нас сишному вводу-выводу).
вся суть снгшного образования
плюнь в лицо этому преподу от меня
>виснет
Очевидно, что у тебя никогда не заканчивается цикл
>while ((abs(f(b)-f(a))>e)&&(abs(b-a)>d))
Так что напихай туда принтов да посмотри, чему равны твои f(b), f(a), abs(b-a).
В строку входит несколько составляющих, но какие именно должно быть - пока неизвестно.
Думаю, с с можеством аргументов поможет vsnprintf... Но как их накопить?
Потому что не Си.
Не надо мудрить. Деды просто используют динамическую типизацию:
if i_flag printf %d i;
if s_flag printf %s s;
Пробовал увеличить размер массива а[] тогда "pa" становится больше.... но не равны.
Чел, ты сравниваешь адреса.
Это сравнение равносильно сравнению a и b (e.g. pa > pb <=> a > b)
тогда посмотри пож-та на 24-ю строчку.
там вроде тоже адреса сравнивают? Эта строчка должна определить какая строка больше и укоротить её до размера destination.
Такие махинации возможны в пределах одного массива. Точно не помню, но стандартом гарантировано, элементы массива распололжены в памяти последовательно, поэтому адрес n-1 элемента меньше/больше это зависит от системы адреса n-го элемента на определённое число байт.
Скомпиль с оптимизациями.
>меньше/больше это зависит от системы
бля, обосрался. Стандарт гарантирует, что адрес меньше.
>адрес n-1 элемента меньше/больше
меньше
>на определённое число байт
на sizeof элемента, если приводить к char #
там же memmove написано. если адрес dst больше src, значения пишутся типа от конца, если нет, то к концу.
len может быть любым неотрицательным, но есть риск записать больше и что-нибудь испортить.
Алсо, не ясно, что происходит при перекрытии адресов в ходе записи.
>значения пишутся типа от конца, если нет, то к концу.
конца же два поэтому
В сторону уменьшения адресов, иначе в сторону возрастания.
Оказывается, что в методичке неправильно указан метод хорд, потому программа и улетает в цикл. Заебись/10.
stdarg
В си есть какой-то быстрый метод перевода числа из любой системы (условно n), в десятичную? Интересно как это тут работает
Как это скомпилировать? Ошибку выдает
Спасибо, отличная идея. Написал прогу по твоей наводке, но немного изменил.
n - так получал:
fgets(n, 30, stdin);
Я из C# треда, но лучше спрошу тут, т.к. вопрос для байтолюбителей.
Есть два массива: int[] src и int[] dst (вместо int можете подставить что вы там любите, типа uint32_t).
Как мне скопировать произвольное количество битов, заданных позицией первого бита start_bit_index_in_src, количеством битов bit_count и позицией в которую начинаем копировать в получателе: start_bit_index_in_dst.
При этом, все прочие биты в массиве-получателе, должны остаться неизменными.
Я начал писать код, и он оказывается очень сложным. Приходится писать отдельную логику для первого элемента массива, для последнего и для внутренних. Приходится писать отдельную логику для случаев, когда смещение первого бита в первом элементе в src больше, чем в dst, для случае - когда меньше, и когда равно.
Вроде бы задача тривиальная казалась на первый взгляд, но что-то я закопался.
Есть одно очевидное решение в лоб, сделать метод для чтения и присваивания отдельного бита, типа bool get_bit(int[] arr, int offset) и void set_bit(int[] arr, int offset, bool value). Оно простое в реализации, но вероятно будет намного медленнее, чем если копировать целыми кусками int.
В составе стандартной библиотеки armcc есть _membitcpybb() и сопутствующие, но это не является частью стандарта. Погугли, может кто-то запилил кастомную реализацию.
Я делал на питоне частный случай, когда битовое поле помещается в целое. И то получилось громоздко.
> Приходится писать отдельную логику
Страшно-то как. Так же как и в реализациях memcpy: если хочешь быстрое блочное копирование, ты пишешь отдельную логику (читай: побитовое копирование или ебля со сдвигами и переменными-аккумуляторами) для невыровненной части данных в начале и в конце. Другого не дано.
>>183611
>>184277
Если кому интересно, вот такое решение получилось:
https://pastebin.com/Wh1KM5dN
Что бы ты сделал по-другому?
Объявление байто-хранилища:
extern const uint8_t server_cert_pem_start[] asm("_binary_mosq_serv_crt_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_mosq_serv_crt_end");
Функция:
esp_tls_set_global_ca_store(server_cert_pem_start, server_cert_pem_end - server_cert_pem_start);
Что она принимает: https://github.com/espressif/esp-idf/blob/master/components/esp-tls/esp_tls.h#L578
Это тоже самое, что подсчитать кол-во символов в массиве?
Да, но в идеале надо ещё делить на размер элемента массива, если размер каждого элемента массива больше минимально адресуемой единицы памяти.
Ок, спасибо.
Намедни приятель попросил меня поставить ребёнку Minecraft. Ох, какое же говно эта Java - на его ноуте один кадр в секунду. Вообще играть невозможно. Тогда я почти случайно нашёл Minetest - тот же Minecraft, переписанный на С++. И о чудо - графика работает плавно и ничего не тормозиит. Это я ещё не говорю о потреблении памяти, которую Java тупо жрёт как не в себя.
Более того, волею судьбы пришлось знакомиться со всемы модными кластерными технологиями. Заставили на работе. Это, простите, пиздец. Сотни мегабайт ОЗУ и терабайты бесполезных логов. Тысячи TCP соединений между модулями. Накладные расходы на поддержание инфраструктуры могут доходить до 30% а иногда даже и больше. Тот, кто пишет на Си (даже на С++), может понять мою боль.
Думаю, нам нужен мировой кризис, большой кризис, чтобы цены на память, оперативную и дисковую, подскочила до небес. Чтобы смыло всё говно, включая неразработчиков, пиздоменеджеров и ебаные "технологии". Чтобы остались лишь гуру, которые пишут маленькие быстрые надёжные программы.
Кажись выговорился. "Энерпрайз" - говно.
>Minecraft
Ты просто дебил и нихуя не пони маешь.
Именно говноджава дала возможность
1) делать моды
2) несмотря на истеричную РРРРЯЯЯЯЯЯ сначала жирного пидора а потом и мелкомягких они все, конечно, утверждали что моды норм и совсем не бомбит - очень смешно выглядит это всё
То есть манякампф состоялся исключительно благодаря говняве.
Вот такой вот дерьмовый мир.
Убей себя.
Благодарю.
лучше сишарп
Transactional memory (n1961), асинхронщина на уровне языка (n2017). По мелочи - атрибуты функций теперь будут в стандарте, а не расширением GCC, неименованные параметры функций, decimal типы.
Потому что k&r вышла за двадцать лет до первого стандарта, в котором были функциональные поинтеры.
Я правильно понимаю, что если начну учить кресты, то фактически смогу кодить и на обычной сишке и учебники непосредственно по Pure C НИНУЖНЫ, или это осталось давно в прошлом и после плюсов, если захочу пощупать просто Си, придется листать учебники по нему?
Это разные языки с разными паттернами, все
Учебники наверное не так важны как просто код на гитхабе читать, чтобы видеть как идиоматичный код на обоих языках пишется
С++ слишком высокоуровневый. Вопреки сложившемуся мнению, что Си мешает учить С++ (а он действительно мешает), ты не сможешь оптимально писать на С++, не зная Си.
Смотри на приложенную картинку. Если извратиться, то на С++ можно писать без указателей. И новички неосознанно это делают. Много костылей налепишь, прежде чем поймёшь как это работает.
Короче, если хочешь стать крутым системным программистом, то учи в следующем порядке:
1. Ассемблер(ы)
2. Современный Си.
3. Классы С++
4. Использование шаблонов С++
И если очень хочется, но не обязательно, то
5. Написание шаблонов С++.
Или иди традиационным сценарием вкатывальщика - учи использование шаблонов и класссы. Но тогда С++ нахуй не нужен, если не понимаешь чего тебе генерирует компилятор. Тогда это ничем не будет отличаться от знания других языков. Будешь, условно, говнокодить и формашлёпствовать.
p.s. Переход с Си на С++ тяжёл, но зато в результате ты сможешь оптимально писать на С++.
>1. Ассемблер(ы)
Двачую. А то вырастают люди, не знающие нюансов сдвига отрицательных чисел.
>2. Современный Си.
А с какого года начинается современный и чем плох C89?
С 99, как минимум. C89 - архаика, деревянные игрушки к полу прибитые.
Спасибо.
И еще вопрос: нахуя так много учебников? Касается как просто C, так и C++.
Видел, как люди успешно вкатывались в язык после одной-двух книг, но также видел мнение, что без чтения минимум 10 штук ты хеллоуворлдщик.
Например, если у C я решу пройти K & R и, возможно, Прату после него, то что я потеряю если не буду читать остальные книги из шапки?
То же самое с крестами - неужели Липпмана, Праты и Шилдта будет недостаточно? Опять мнения разделились и кто-то говорит, что после одного только Страуструпа для ньюфагов успешно работали над сложными проектами и вообще стали профессионалами в языке, а кто-то говорит, что это только примитивная база, которой недостаточно, и нужно еще штук 20 книжек прорешать.
Почему в конце нет endl? Я что, как долбоеб, должен смотреть на
апельсинарбузвишняклубникаананаспомидорanon@pc123:~/codefrom2ch$ _
?
Алсо, нахуя false через функцию возвращать, и вообще нахуя вот это вот с ифом? enum, кстати, вообще не используется.
И ещё вопрос: нахуя так много лекарств?
Видел, как люди успешно вылечивались после одного-двух, но также видел мнение, что без долгой терапии минимум 10 таблетками ты помрёшь.
Например, если я решу выпить кетопрофен и, возможно, азитромицин, то что я потеряю если не буду пить остальные таблетки из ЖНВЛП?
Идеальных книг не существует, анон, потому что у каждого свой бэкграунд, и могут быть как пробелы в знаниях, необходимых для усвоения нового материала, так и "лишние" знания из других источников, из-за которых некоторые главы книги будут скучными. А пишется книга не для тебя, не для меня, и даже не для ОПа, а для десятков тысяч студентов. У тебя никогда не было чувства, когда тебе кто-то что-то неравнодушно объясняет, что этот чел умнее любого хорошо продаваемого автора? А он всего-навсего лучше попадает в твои слабые места. С книгами же придется выбирать. Либо берешь хардкорное чтиво и активно гуглишь непонятное, либо берешь исчерпывающий томик на 1000 страниц и пропускаешь хорошо знакомое, бегло ознакамливаешься с частично знакомым и вдумчиво останавливаешься на качественно новом материале. А такое избыточное разнообразие естественно при свободном (да-да, "свободном") рынке. ИМХО, прям от корки до корки, как первоклассник, читать надо ровно до тех пор, пока не начнешь комфортно плавать в области, а там уже сам разберешься, где хороших практик подсмотреть, где про матчасть какой-то штуки полистать и т.д. и т.п.
Там еще и опечатка в 31 строчке.
> что думаете о книгах/учебных пособиях издательства O'Reilly
Хорошие.
> Конкретно: Head First
Хуйня.
Обещают завести лямбды и typeof. Может хоть теперь можно будет воспользоватся макросами нормально.
>>190811
Тем что там по крайней мере завезли нормальные типы целочислиных с нормальным размером, restrict, анонимные структуры и юнионы, static assert. Есть ещё потоки, но они нигде из коробки не работают.
Можно с таким же успехом на сололерн курс по Си посмотреть.
>Лямбды и typeof
В принципе смотрю добавляют все то, что в gcc было сделано расширениями. И эти штуки не исключения. Можно сделать лямбды на базе gcc nested functions и typeof в си через расширение там тоже есть.
Проблема в том что в gcc вложеные функции запилены через костыль который даёт немножко ебёт безопасность.
стивен прата норм учебник
Дело в том что обычные вложеные функции требуют либо костыль, который отключает no execute бит, либо менять ABI. Ну или можно
а) никогда не брать адресс функции
б) не использовать в фунции адреса внешних функций
Лямбды какбы обходят это. Плюс анонимность лямбд полезна при написании макросов или когда надо отправить одну фунуцию в qsort. Вообще об этом можно почитать здесь https://medium.com/program-practical/blocks-procs-lambdas-oh-my-8c636a54757c
аа забейте, я супер еблан, я же к какой-то рандомной не инициализированной памяти что-то присваиваю
Быстро ты разобрался. Одобряю.
шапку глянь
Хочу подключиться к порту динамика и работь с ним как с потоком, то есть я посылаю какую-то частоту и она воспроизводится через динамик. Все это я бы хотел сделать используя язык Си на Windows, не подскажите как это сделать или можете скинуть литературу, статьи или другие формы источников, а то я пытался найти решение как на русском, так и на английском, но ничего не нашел, буду очень Вам благодарен.
Можешь, пожалуйста, точно сказать как именно это искать, чтобы именно хуйню не найти?
может за тебя ещё и код написать
Можно использовать http://sox.sourceforge.net/ И никакого winapi не потребуется, тупо в stdout писать отсчеты и всех делов то, проще некуда. Но это конечно смотря для чего тебе все это нужно.
Не ебу, что ты хочешь. Для винды есть wasapi, directsound, winapi, плюс сторонние либы.
Ты хочешь типа вывод на аудио перенаправить? Чтобы писать write(fd,buf,c)?
Обращение к несуществуему участку пвмяти
Если так, то я тебе уже писал >>200953 прямо так и работает.
Вот пример того как оно работает подобным образом https://www.reddit.com/r/RTLSDR/comments/4jt4uk/transfer_sdrsettings_to_rtl_fm_sox/
Он я так понял написан на C99 и если его используешь, то уже, как я понял, нет смысла брать C89?
на плюсы проект переводить никто не будет, а вот повысить стандарт с 89, который сейчас используется, до 99 - это возможно. Поэтому и спрашиваю
Учусь в ВУЗ'е и я дегенерат, почти не шарю за языки, почему все так хвалят ООП и С++, если это говно лютое, говорят, что код легче писать, чем в структурном программировании, но типо все равно же если какую-то деталь меняешь/добавляет код переписывать нужно?
Сам очень люблю Си, как и многие, но, конечно, знаю где-то на 3%, все его охуенные фичи не знаю
В msvc поддержки c99 почти что нет, поэтому вулкан должен работать и с c89
>>202402
Абстракции легче строить. Попробуй фп, там похожие ощущения, и не потому что не надо думать о модели памяти, а потому что абстракции строить и поддерживать проще и удобнее.
В низкоуровневых апи, как вулкан, много бойлерплейта, от которого можно частично избавиться с помощью абстракций.
>>202404
Какие охуенные фичи? ub?
> В msvc поддержки c99 почти что нет, поэтому вулкан должен работать и с c89
да в msvc уже давно C11 завезли
сейчас проверил покомпилить с vulkan, там все комменты в стиле C99 написаны, поэтому как минимум их придется тогда менять во всей либе, глубже пока не раскапывал
Всех особенностей языка, ну, могу немного работать с паматью, но вот на потоках(если не считать работу с бинарками и текстовыми файлами) остановился.
Как кстати узнать свой уровень владения языка?
Ну как давно, год назад, в самой последней версии студии. Это ж майкросовт, ёбаный рот.
После пистона, BRE - лютая агония.
Начинаю думать, что городить велосипед на основе функций из string.h - не такая уж и плохая идея.
pcre
с тем же растом, например
Дано подробное объяснение, почему Си нужно закопать.
https://youtu.be/3pKL4YEa4_Y
Подробное объяснение от Александра Викторовича Григорина, почему Си будет актуален ещё лет 50, как минимум.
себя закопай петух
лучше си и асма ничего нет
а уж когда компы на кубитах попрут вот тут то петушки вы и соснёте
Вот ещё пара ссылок, уничтожающих Си:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
https://blog.regehr.org/archives/213
Почему уничтожающих? Наоборот, подробно расписывают один из самых крутых механизмов языка. Если ты его не осилил, это ещё не значит, что си "уничтожен".
Датчик давления даёт 6 байт 0-FFFFFF надо убрать 3 разряда ни как не пойму на сколько нужно поделить
то есть ffffff = 16 777 215 а нужно получить 16777, сдвигать не могу это пердуина и она усрется сдвигать (ну или могу но все равно не знаю как)
тип long
>пердуина
Твоя дурина это AVR (а они далеко не все на AVR)?
>усрется сдвигать
Если у тебя AVR и ты загрузишь свои 6 байт в uint32_t, а потом сдвинешь на один бит вправо, то получится примерно вот такая последовательность команд:
lsr r1
ror r2
ror r3
ror r4
Номера регистров конечно могут быть другими. Каждая из этих команд выполняется за один такт. Ну и поскольку тебе нужно сдвинуть на три, то эта последовательность будет повторена три раза, может быть в цикле. Итого ну максимум тактов 20 в худшем случае, не считая загрузку-сохранение. Ахуеть как много! Да у тебя на загрузку одного байта из ОЗУ тратится три такта.
Не знаю почему ты решил что сдвиг это сложная операция, но разрешите доебаться.
Чтобы отбросить три десятичных разряда действовать нужно нихуя не сдвигом.
Разделить на 1000, это ты правильно догадался.
Кстати я раньше думал что пердольщики микроконтроллеров это такие суровые байтоёбы, думающие шестнадцатеричными дампами. Но ардуино-тред и обсуждения на других форумах развеяли это заблуждение и чуть не погасили веру в человечество вообще. Теперь я просто задаюсь вопросом как у вас в принципе хоть что-то работает.
>как у вас в принципе хоть что-то работает
У меня отлично работает потому что я не программист
Ну и чтиво, конечно... Помню, как-то сам напоролся на strict aliasing с полями структуры и кастом в void, если не изменяет, и анон итт посоветовал мне не страдать хуйней, если не
>знаешь что делаешь и умеешь в -fstrict-aliasing
но я с самоуверенностью Даннинго-Крюгернутого продолжал пукать в ответ на критику UB. Теперь стыдно стало. Прости меня, двачик, за нехорошие слова.
А при чем тут LISP?
Пиздец, на картинке сравниваются два указателя - один в сегменте данных, другой на стеке. Они по определению не могут быть рядом.
А здесь попробуй вычесть единицу, а не прибавить. Но никто тебе не гарантирует что указатели будут лежать рядом. Ебаный компилятор может их положить как угодно в стеке, как он сочтёт нужным.
А вычесть вместо прибавления потому что стек растёт в сторону уменьшнния адресов.
Чел.. Ты разделил на 100016 т.е. на 409610. Оставить ссылку на википедию по системам счисления или сам найдешь?
А в чем прикол? В том, что по наивному ожиданию результат будет 4 независимо от порядка выполнения первоочередных выражений с их сайд-эффектами? Сайд-эффект же, вроде, вообще не обязан выполняться до ближайшей запятой или точки с запятой?
а если malloc вызвать внутри функции и передать указатель на этот участок памяти из этой функции то будет ли эта память защищена от изменений или это UB?
Например, есть изначально enum alpha { A = 0, B = 1}
и вот чтобы в какой-то точке программы вызвать какой-то магический макрос, чтобы оно уже было вида скажем enum alpha { A = 0, B = 1, C = 2}
Вроде как это технически нереализуемо, но может все же я что-то не учел.
а нахуя использовать флаг который незнаешь что делает в функции с 1 принтф?
Они хранятся одинаково, но один бит для знака отрезается. Поэтому надо указывать, знаковое оно или беззнаковое.
Потому что %d это знаковый формат, а пердоговно кривое как всегда, им лучше не пользоваться.
Функция getenv
#include <stdlib.h>
char getenv(const char name);
Функция getenv() возвращает указатель на данные о среде, которые хранятся в строке, адресуемой параметром name в таблице характеристик среды, определенной конкретной реализацией. Ваша программа не должна изменять значения, хранящиеся в этой таблице.
Среда программы может включать такие данные, как пути и подключенные устройства. Формат данных определяется конкретной реализацией, поэтому для уточнения деталей необходимо обратиться к руководству пользователя, прилагаемому к компилятору.
Если при вызове функции getenv() значение аргумента не совпадает ни с одним из данных в описании среды, возвращается нулевой указатель.
Пример
Предположим, что определенный компилятор поддерживает информацию среды относительно устройств, подключенных к системе, тогда следующий фрагмент возвращает указатель на список устройств:
char p
/ ... (/
p = getevn("DEVICES");
Зависимые функции
system()
Потому что твой цикл по vars - это типичное UB (пункт 6.5.6 C99, параграф 8), а после UB в программе может происходить всё, что угодно.
Пожалуйста. Уж "не ходить за границы массива", мне кажется, можно как-то уже запомнить.
Просто для меня не было очевидным где он тут выходит за его границу, поэтому и не понимал сначала. Еще раз спасибо
Хочу считывать из stdin самый свежий символ. При этом после того как считал записываю null чтобы если пользователь ничего не нажал я в следующем вызове в ответ получил null и ждал пока он таки сделает ввод. Но оно почему-то не записывает null, или я читаю не самый свежий ? Помогите пжлст
Вот этот вариант работает. Пущу ее в отдельный тред и будет заебись
> но на указателях понял
А чего всех так пугают эти указатели? В свое время изучал си как первый яп по базовому курсу c++ от шилдта и все было ясно с первого раза. Может тебе лучше в python?
есть такое, жизнь потрепала :)))
>пока молодые шутливые питонисты получают 300кк дата-сциентистом и ебут сочных зумерш-тестировщиц, сишники пердолятся в срачечку с говнолегаси на пару с петровичем из НИИ-ХУЯ
Пиздец, что ты с таким мышлением в Си-треде забыл, болезный? По твоей логике обычный васян или хач, которые по КД солевых шмар ебут - это высшая стадия человека и предел мечтаний.
ну извините, ухожу обратно в /b деградировать
дальше по коду можно как-то макросами/директивами чекнуть объявления ли она?
типа:
#ifndef A
printf("NO");
#endif
Нет, макросы раскрываются препроцессором, который кроме лексического анализа и некоторых преобразований ничего не делает
Но можешь оформить заголовочник подобным образом:
#ifndef STRUCT_A
#define STRUCT_A
struct A;
#endif
а потом уже в коде:
#ifndef STRUCT_A
printf("NO");
#endif
а он и не должен, в начале мейне detach. Эта функция нужна до конца программы
Подождите, mutex нужен чтобы определенный участок кода мог выполняться только из одного треда. Зачем мне статический объект mutex'a ?Я должен что-то с ним делать из другого?
Блять, ты тролишь что ли?На стековерфлоу пишут именно так. Если ты экспэрт то просвети тупого
Ну так он там static. Каждый поток увидит один и тот же экземпляр мутекса - и только так они смогут синхронизоваться (shared state).
т.е ты хочешь сказать что auto mutex это бред т.к, если я запущу два треда на эту функцию, будет 2 отдельных не связанных между собой mutex'a. Ну ок, звучит логично, пойду поправлю
можно
А потом ты в своём проекте из миллиона файлов поменяешь один .c-шник, и твой петушиный скрипт либо обосрётся и будет заново всё пересобирать, либо обосрётся и ничего не будет пересобирать, бинарник вот же он, готовый лежит.
ну да, в этом случае башскрипт делает сасай, чет я не подумал. Я просто хеллоуворлдщик, мб поэтому не подумал
> почему для билда програми обычно юзается мейк
потому что это стандарт такой по умолчанию, чтобы везде люди могли собрать его под любую ОС и чтобы синтаксис все знали
поэтому сейчас пишется только CMakeLists.txt, а все остальное уже само делается под нужную систему: хоть яблоки, хоть андроиды (да, они тоже уже на make как альтернативу перебрались)
На самом деле мейк могли написать на шелле, но проще это было сделать на С.
он скипает файлы натыкаясь на #error в #if отложенных на всякий случай.
This file is not analyzed. Cppcheck failed to extract a valid configuration. The tested configurations have these preprocessor errors:
я даже свежий скомпилировал - всем похуй или проблемы на самом деле нет (/решается)? но я вроде прочитал хелп.
может есть что-нибудь пободрее, но без платы шекелей? а контрол кстати плотный тул, ни одного фелзпозитив не словил ещё.
и как это обычно бывает, сходу решилось. не увидел что у этой ошибки есть тег, по которому можно заигнорить. я думал что это и не ошибка даже, к тому же в хелпе: Suppress a specific warning.
cppcheck -v --enable=all --suppress='noValidConfiguration' --force --std=c89 --std=c99 --std=posix --platform=unspecified > /tmp/cppcheck.log 2>&1
Нет конечно.
потыкал ещё и похоже упёрся в то, что и прежде. например, у меня много проверок на случай если какого-то типа нет или он не того размера - #error. cppcheck не видит объявления необходимых, а подбирает как-то по особому сочетая, как если бы это были опции компиляции. нужно инклюдить хедеры, но от -I/usr/include/ -I/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/ , ему ещё больше сносит крышу (в частности от sdl). остаётся только точечно: --include=/usr/include/limits.h --include=/usr/include/assert.h --include=/usr/include/stdint.h --include=/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/stddef.h. и то, это принудительный инклюд в каждый файл, что как-бы не очень хорошо. и конечно, встаёт вопрос: а нахуя мне всё это надо и к чему это приведёт?
cppcheck -v --enable=all --force --std=c89 --std=c99 --platform=unspecified \
--enable=warning,performance,portability,information,unusedFunction,missingInclude \
--include=/usr/include/limits.h --include=/usr/include/assert.h --include=/usr/include/stdint.h \
--include=/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/stddef.h \
> /tmp/cppcheck.log 2>&1
>>218458
не пробовал линтер жидов. откуда у сишника деньги?
Ну имеется ввиду не то, что там этот _Generic ввели, а хотя бы уровня слизанного с плюсов (или даже выше)
шаблоны можно(и делают) сделать через инклюд файла.
> Что тебе не так с _Generic?
например, нужно реализовать библиотеку для векторов, ну что-то аналог STL, сейчас есть вариант только накрутить это все через макросы в очень неудобном виде, что нужно в стороннем коде при использовании этой библиотеки для создания вектора своей структуры:
1) задекларировать такой вектор
2) объявить переменную для такого вектора
3) инициализировать вектор
и потом уже очень неудобно работать
ну теперь пробуем применить _Generic, как написать через него вектор произвольного типа с общим поведением? Допустим какие-то мы объявили в этой библиотеке, ну а пользователь в своем коде что должен делать?
> Используем магию ##
ну это и был единственный, но очень кривой вариант, для написания подобной либы у нас, но чтобы оно работало через синтаксис макросов в этом виде - уж больно много ненужного хлама дополнительно генерится в асм выхлопе, поэтому и был такой крик душа, что когда уже..
деструктор бы еще, ну хоть defer может все же скоро завезут
не знаю что там в stl (поэтому возможно пишу глупости), но вектор (геометрический) специфичная же штука. вот например у меня 16 бит на дробь и 16 на целое, как поможет то, что я его объявлю типом long? остальное же: списки, очереди - они не зависят от типа.
Ну вот смотри, например, у меня есть слой(таблица из 100 записей) и я их занесу в буфер. Допустим, что таких слоев в файле 10, которые я буду записывать в буфер по мере необходимости. Мне нужна возможность переключать эти слои в двух направлениях(представляю как реализовать), а как быть после простотра последнего слоя в файле? Тупо переключать файловый поток на следующий/предыдущий файл? Или же есть более трушное решение.
>>219364
>nmap
Вот это уже выглядит ближе к теме, пойду курить маны.
Сделай базу в любой субд (в том же mysql), загони туда свои данные, выгрузи в файл.
Пригодится, если у тебя не высоконагруженная имиджборда 10k соединений в наносекунду
> не знаю что там в stl, но вектор (геометрический) специфичная же штука
да, речь шла про вектор как один из видов контейнеров (например, vector в C++)
да здравствует тред
Там всё пишут.
Может написать какие нибудь проги в портфолио, или на гите искать работу? ДС2 23 годиков. Вообще хочу игры кодить, но есть желание в будущем системками заниматься.
Я просто хочу сидеть и кодить сутками.
> Собираюсь после уверенного знания Си перекатиться в кресты
Так и учи кресты, это разные языки.
Слишком размыто ты написал. Какие задачи решаешь, какие алгоритмы изучаешь? В какую сторону планируешь развиваться? У меня ощущение, что ты фундаментальные вещи сейчас учишь, не более.
Неебические знания включают в себя, например, анализ сложности алгоритмов, всякий разный матан, короче, то, что учат в вузиках. В принципе, это можно и самому освоить, но будет сложно.
И да, пиши сразу на крестах, выучишь ооп, научишься всякие шаблоны проектирования делоть.
Именно так, база. Хочу поступать на физмат, но нужно работать. Алгоритмы очень базовые, а еще всякие ADT. Закончил Пратовский учебник и сейчас тонкости языка изучаю, а еще либу стандартную ну и дебагер. Алгоритмы по известной книжке пытаюсь писать сам на Си, на c-faq нашел много инфы, но вот практический опыт надо где-то брать.
Спасибо анонче, буду кресты изучать.
>физмат
Это если ты потом хочешь в машоб идти, речёрчами заниматься или еще что-нибудь матаноёмкое. Ну скажи, нах тебе, программисту, знать функциональный анализ или какие-нибудь сплайн-аппроксимации? Если пилить игры, то это пригодится для разработки движков, что весьма специфично при наличии тонн готовых. Если системное программирование - тебе нужны знания об архитектурах, ассемблерах и битоёбстве, что на физмате тоже не очень хорошо изучается. Тебе матан или ехать все-таки?
А на кого мне пойти учиться в вузе если я в геймдев пойду? Дико интересно было кодить симуляции с кружочками и платформеры. Какой нибудь software engineer? Посмотрю сегодня еще раз опции в МФТИ. В любом случае если в будущем будет интересно продолжить изучение матана, уже хотя бы будет понимание. Программировать дико интересно.
На данный момент у меня 9 классов в 23 годиков и в этом году хотел закончить школу экстерном, но материала оказалось много особенно по математике, в этом году собираюсь все догнать хотя бы до линейной алгебры и в следующем сдавать.
https://pastebin.com/PvKsrJY3
Как зарегистрировать драйвер на шине в sysfs?
Как зарегистрировать устройство на шине в sysfs?
Реализовал ioctl интерфейс, как теперь обращаться к нему в запущенном драйвере? Отправлять команды?
Что сделать чтобы антивирус не пиздел на запуск кода в Code Blocks?
Контест передавай через войд звездочка, и будет тебе счасте (касты писать не надо, поведение определенное, код идиоматичен).
Спасибо, всё работает как надо, правда компилятор ворчит на incompatible pointer type, потому что коллбэк должен принимать unsigned char звёздочка первым аргументом, a loop() - последним. По логике можно игнорировать, но напрягает немного.
если тебе по задаче это требуется - нет не плохо
handle - дескриптор, handler - обработчик, а у тебя по смыслу наоборот. В остальном вполне нормальный подход.
Задаю тупые вопросы.
Правильно ли я понимаю, что если мы создаем типа динамический массив, потом переопределяем его размерность, то он может перезаписать информацию, которая могла уже быть записана по определенным адресам идущим после него, или же он переопределяет новый пул адресов и каким-то образом переносит массив?
realloc может тебе вернуть тот же вдрес, если в блоке достаточно места. Может вернуть любой другой с копированием.
Понял, спасеба.
Не, мне не столько ООП нужно, сколько просто возможность собрать несколько однообразных функций и данных в массив для итерации по нему в "общем" коде.
Например, есть устройство с каким-нибудь колесом, лампочкой и звуковым сигналом. После какого-то события нужно их все включить (процедура включения, допустим, сложная, а не напряжение на пине поменять в одну строку). Но есть точно такое же устройство, в котором нет лампочки, а в остальном логика идентичная. Вот "общий" код отвечал бы за, собственно, обход связного списка "контроллеров", созданного/инициализированного в коде уже конкретного устройства.
То есть, хочу избежать кучи ifdef'ов типа
>enable_wheel();
>#ifdef HAS_LIGHT_INDICATION
.>enable_light();
>#endif
>enable_sound();
Засунь ифдеф внутрь enable_light(). А компилятор потом повыкидывает пустые функции.
В твоем варианте ядру придется перезаписывать pc, сбрасывать конвеер и ждать, пока новые инструкции поступят на исполнительные блоки. Хотя если производительность не важна - то пох.
Всё правильно, анон. Ты почти придумал драйверы и дерево устройств.
{ "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
Что в ней блять значит {.i64 = FF_MOV_FLAG_FASTSTART}? Это должно стандартное значение. В другом файле нашёл #define FF_MOV_FLAG_FASTSTART (1 << 7)
Сдвиг единицы на 7? Как такое возможно если параметр по умолчанию выключен? И что значит .i64? Почему к нему обращаются с точки?
>#define FF_MOV_FLAG_FASTSTART (1 << 7)
Это значит, что везде, где ты видишь FF_MOV_FLAG_FASTSTART на самом деле подразумевается (1<<7), т.е. 128.
>Как такое возможно если параметр по умолчанию выключен?
Кто выключен? Этот дефайн — это просто способ дать какому-то числу название (для понятности), не вводя переменных. То, что faststart по-дефолту не исопльзуется будет влиять лишь в процессе работы, где ffmpeg пропустит какую-то часть кода, а у тебя в этой строке лишь описание выставляемого флага (который и будет проверен далее).
>И что значит .i64? Почему к нему обращаются с точки?
Вероятно, там union, поэтому указывают, какому именно варианту значение дают. Типа вот так — https://ideone.com/z2loWI
Хотя можно и просто структуры инициализировать с именами мемберов, даже в любом порядке — https://ideone.com/GVMe42
сколько ты запросил у менеджера динамической памяти, когда malloc вызывал
У одних есть заголовок перед тем адресом, который тебе вернули.
У других есть таблица страниц, которая говорит, на какие равные куски разбита страница.
Вот я создал массив на десять элементов, arr - это же получается указатель на 0 элемент. Так вот, почему в main тогда sizeof(arr) указывает 40 байт? Я понимаю, что это размер всех элементов внутри, но почему тогда в функции in sizeof(arr) равен 8? и там и там же указатель...
Майн говорит, сколько он выделил под весь массив.
в одном случае размер указателя, в другом случае размер массива.
Если не догоняешь, переименуй аргумент в ptr вместо arr.
Что я упускаю? Мне нужно в определённой структуре хранить представление целого числа в форме последовательности байт, размер числа будет храниться в ней же. При этом при попытке преобразования происходят вот такие приколы.
Перед сдвигом uint8_t приведи его к типу uint64_t
На signed вообще забей - приводи его к unsigned. В твоём случае это роли не играет.
Твой код не учитывает big_endian и low_endian - при портировании на другие архитектуры получишь сюрпризы.
И вишенка на торте - раз ты забил хуй на endianness, то и циклы не нужны - достаточно поиграться с указателями и приведением к типу. Ещё и в 20 раз быстрее работать будет с тем же самым результатом.
Раскурить фолиант с пучеглазыми зверушками.
неофит
Погугли да скопируй эти 10 строчек со стековерфлоу.
Ебать, в С-треде уже сравнение строк велосипедом называют. Что дальше, пикрил?
>пикрил
Да, как-то делал на нодежс одну прогу впервый раз, и надо было получить текст из клипборда. Вместо того, чтобы вызвать нативную функцию винапи за микросекунду, эти уроды выложили в этот говностор приблуду, запускающую павершелл, потом в нем команду и берущую её результат. Еще бы блять вставили компиляцию винды из исходников сначала, что размениваться на мелочи.
Возможно ли перекатиться в США/Европу/Китай, будучи Embedded-программистом? Я понял, что эта тема - наиболее интересная для меня из всего айти, к тому же, когда я только начинал заниматься программированием, я уже знал, что кодить можно под микроволновки/чайники/переносные устройства, и хотел заняться чем-то подобным.
поищи получше
чёт я так это поварил в закромах. а нахрена тебе динамический массив? берёшь мемори пул + список, делаешь обёртку:
struct v {
size_t tsize, toffset;
list_head hl;
memory_pool hp;
};
дальше понятно.
>>220226
а и, почему вспомнил. как тебе https://sourceforge.net/projects/tstl2cl/files/tstl2cl/
такие вещи делаются через union вообще то..
неужели это настолько сакральные знания стали а я типо мамонта-дурачка который еще что то там бормочет для вкатывающихся школьников..
лучше придерживайся правила "не обобщай до пяти"
то есть для каждого случая пиши новый код
а когда таких случаев будет больше пяти то уже пытайся выделить общий код
все компонентное программирование (com, gtk, и десятки других библиотек) на этом и основывается
ты идешь по тропе протоптанной десятками тысяч программистов до тебя но тебе кажеться что это дикий первозданный мир
>нет, ты просто тупой, если делаешь это через union.
с хуя ли? если видишь что прогер работает с внутренним представлением чисел через смещения а не через объединения - это сразу признак низкой квалификации
> Очевидный GCC
Не могу разобраться какие флаги оптимизации следует использовать. Что юзает анон?
это мидл квалификация. юнион требует больше кода и ебли с головой - в стандарте, указатель может указывать на конец объекта, выравнивание.
но это всё в идеальном мире, где всё рационально, весь современные код как есть - это проблема переполнения знаковых таймеров времени - всем похуй.
-O3 в некоторых случая может порождать более медленный код, поскольку всё что можно разворачивает и инлайнит, вследствии чего плохеет кэшам проца и может быть деградация производительности. Не обязательно это случится, но может быть. В зависимости от того, что именно ты компилируешь и как это написано. За остальные ключи ничего не скажу - у меня не было необходимости выжимать такты из кода. Предпочитаю поднимать скорость алгоритмами и стилем написания кода, это несложно, если ты понимаешь ассемблерный код, генерируемый компилятором.
Ну а ежели ты занимаешься "числодробильными" задачами, типа матмоделированием, то не пользуй gcc, а возьми компилятор от Intel - он заточены как раз под оптимизацию больших вычисленй.
ты на амд то не гони, у них тоже есть компилятор.
> матмоделированием
возбуди во мне животное чувство - расскажи что это такое.
Приветствую всех присутствующих. Сейчас пишу курсовую по программированию. Gentoo, CodeBlocks, GCC.
После внезапного аварийного завершения работы компа во время редактирования кода (в компе нет батарейки, а шнур от зарядки такого говённого качества, что любое резкое движение может вырубить комп) программа вообще перестала компилироваться. Когда я в CodeBlocks нажимаю "собрать и запустить", выдаёт пикрилы.
Причём если я команд, указанные в логе, ввожу непосредственно в консоль - всё компилируется нормально. А если я то же самое делаю через кодблок - нихуя, файл .o почему-то не создаётся. Что делать?
Как бы сделал я - забил нахуй на этот codeblocks и шел бы в командную строку на виме писать
Дело в том, что у меня эта программа крайне криво работает, мне её дебажить нужно. А дебажить в консоли - мазохизм.
Дебажь printf'ами, чё ты как баба
make clean уже пробовал? Пересоздать проект и скопировать туда весь код?
Отладь в Visual Studio, что ты как маленький. Наверняка же у тебя консольная программа, которой похуй - Windows или Linux. За исключением маленьких нюансов.
> А дебажить в консоли - мазохизм.
а как по другому? как вы получаете трейс? у вас есть кнопочка прописывает команду из 4х букв?
которая*
это условность, зачем ты начинаешь
Не, ну реально же мазозизм. Особливо ежели юникод. А в VS мышку подвёл и всё на виду.
Вот понял я как работают указатели в C, и отсюда возникает вопрос, как в более высокоуровневых языках где нет указателей, компитятор/интерпретатор понимает, где идет речь о значении, а где о адресе?
Вопрос два:
Была такая проблема: выделяю память динамически через malloc в программе, компилирую используя gcc i686 4.8.4, запускаю - все заебись.
Далее беру тот же код, компилирую через gcc x86_64 4.8.4 - компилируется нормально, запускаю, ввожу тот же тест и получаю Segmentation fault (если заменить динамическое выделение памяти на автоматическое, то ошибка пропадает), и так не только с одним тестом, а в целом скомпилированная одной и той же версией компилятора, но под разные платформы программа просто не работает нормально. Загуглив, что такое i868 я нихуя не понял, челы с stackovwerflow пишут, что это просто разновидность x86, зачем тогда существует отдельная версия gcc под нее? правильно я понимаю, что я могу и то, и то использовать на 64-х битной системе?
>компитятор/интерпретатор понимает, где идет речь о значении, а где о адресе?
ну там же есть понятие объекта и способов к нему обращаться.
> Вопрос два:
это не один вопрос.
> Далее беру тот же код, компилирую через gcc x86_64 4.8.4 - компилируется нормально, запускаю, ввожу тот же тест и получаю Segmentation fault
хз, может ты это делаешь на 32хбитно системе.
> что это просто разновидность x86, зачем тогда существует отдельная версия gcc под нее?
это не отдельная версия, а отдельный билд.
> правильно я понимаю, что я могу и то, и то использовать на 64-х битной системе?
нет. можно, если ос имеет к поддержку (библиотеки 32хбитные и какую-то там совместимость - в теории)
но это не точно всё.
Легко уехать в ЮВА, вплоть до Самсунга. В России тоже можно, но запралата будет ниже чем у "формошлёпов".
>компилируется нормально, запускаю, ввожу тот же тест и получаю Segmentation fault
Классическое описание undefined behaviour. Ищи, где объебался, ворнинги компилятора, ub sanitizer и valgrind в помощь.
вот мой код
https://pastebin.com/yGkDBY8x
скармливаю любой пример из задания. например:
11111
19991
19191
19991
11111
то на 6 степе валится сегфолт.
если дебажить то на выходе из функции octos_next_step дебагер ругается
> Cannot find bounds of current function
я так понимаю стек закораптился, но я не понимаю почему.
У меня там рекурсия, но поидее это не должно влиять, там не так уже и много вызовов рекурсивных должно быть.
>int main(int argc, char* argv[argc+1])
Взвизгнул.
Автор, чому ты намешал все фишечки С11, не усвоив БАЗУ из книжки K&R?
бляааадь, а с чего я взял что так можно писать?
кажется фляга уже совсем свистит. Пожалуй сегоня без компа проведу выходной.
Спасибо, братик. Я реально хз откуда я это высрал.
Ну дела, конечно.
>>235590
> Взвизгнул.
а что, сильно все хуево кроме этой залупы 0<nrow<rows?
> Автор, чому ты намешал все фишечки С11, не усвоив БАЗУ из книжки K&R?
Я хз, я си еще давно в универе учил, тогда мне не зашло, на отъебись его тогда сдал.
Не так давно решил узнать, что в си нового, да и старое вспомнить.
И вот как-то так вкатился заново уже с новыми фишками языка. За K&R я как-то сел , но не вхатило терпения что-ли. В сотый раз читать про что такое тип, переменная, функция супер скучно.
Удобно.
А нахуя там ub делать? поч не дать считать как с указателя и получить вылет? Буквально вместо падения приложения делают тихое игнорирование..
у меня вылетает
Что "делают", дубинелло? Если твое число как адрес случайно указывает в наличную память, оттуда что-то будет прочитано как строка. Если нет - вылетит.
ну так, то что ты написал - понятное мне поведение, а выше чел писал что это UB. Вообще я не подумал, наверн чтение мимо это тоже UB, тогда тут все очевидно. Я сначала решил, что там какой-то специальный случай UB для va_args, типо ожидет строку, а передает int, и компилятор хуйню придумает. В примере 1ого чела не вылетело, а у него число 5, какбы сомневаюсь что на 5 там можно читать ему.
Pattern matching на конструкторе натурального числа, ведь там не может быть zero.
Ты можешь пояснить нормально почему так происходит и как эта залупа внутри работает? Или больше чем на пук ты не способен?
Чувак явно только вкатывается, а ты ему исходники кидаешь. Что ещё ожидать от харкачеров...
Пиздец ты тупой блядь.
>>236208 (Del)
спасибо)
>>236212
предполагаю, что printf когда доходит до %s вызывает va_arg(args, const char*), и так как "If the type of the next argument in ap (after promotions) is not compatible with T, the behavior is undefined" (цитата с cppreference - C docs). Поэтому UB. Реально же (не по стандарту, но на обычном компе), va_arg тупо копирует со стека столько байт, сколько было бы, если бы там был указатель. На x64 у тебя скорее всего в int'e 4 байта и в указателе 8 - ты получишь указатель, который наполовину будет 5, наполовину - мусор со стека.
а? не понимаю твой текст. Я конешн на Си никогда не писал, но про указатели и литерал строковый знаю из плюсов. На пике cppreference (раздел про Си), пишет что ожидается указатель на char, какие вопросы?
что не понятно тебе?
Конечные автоматы используй.
перед сканф проверь строку на валидность
>Как на этом блядском языке нормально хендлить инпут пользователя?
Как и на всех остальных - читаешь строку а дальше сам думаешь что с таким вводом делать
> scanf("%d",operation),
Сканфу нужно указатель передавать.
scanf("%d",&operation);
И как ты получил единицу? Он вернёт тебе единицу, поскольку это количество считанных переменных.
А значение должно попасть в operation
Сделал вот так — https://ideone.com/qYkgwU и вроде всё норм работало (gcc компилировал). Это нормально так делать? У коллеги затем (тоже gcc, только другой немного версии и на винде) почему-то работать перестало, и значения *ptr как-то плавно перетекли в 0x5555 после нескольких повторений записи (пока дебажили, почему неправильное значение после азпуска. При этом value остаётся нормальным, т.е. сама память-то вроде правильная, а вот если к этой же области обратиться как к uin16_t — нет.
Что-то я понять не могу, что это вообще такое и почему происходит? Запускается всё на идентичной плате, но у меня почему-то работает (с -O0).
При этом на ideone видна та же самая проблема, ptr выводится мусором. Однако, если я чуть изменю лишь один принт, чтобы и адрес выводил, то всё нормально становится — https://ideone.com/UG7rmg / https://ideone.com/r2kyZW. Что за херня вообще?
>Однако, если я чуть изменю лишь один принт, чтобы и адрес выводил, то всё нормально становится
Люблю запах Undefined Behaviour по утрам. Это запах... нуба.
Прекрасно, а объяснить что именно тут undefined-то можешь? Или только язвить горазд?
Это я, конечно, провафлил, но этот массив только в примере на ideone существует (чтобы код выполнялся) и к никак делу не относится. На самом деле там адрес флеш памяти указан, естественно. В принципе, это в примере вообще лишнее, для полноты оставил.
Вот тут пару вариантов протестировал — https://ideone.com/Ph67mH
>uint16_t u16_2 = (uint16_t)&value;
Выдаёт правильное значение. А вот
>uint16_t ptr = (uint16_t)&value;
>*ptr
Уже нет. Я не пойму, в чём разница между этими двумя вариантами, кроме того, что во втором случае на две строки разделено?
Как только я пытаюсь вывести адрес value или значение указателся ptr, чтобы убедиться, что они действительно на одну точку указывают (мало ли там с alignment'ами что), всё магическим образом начинает работать. Будто тут какая-то квантовая физика с суперпозицией.
Может такое быть, что uint16_t ptr указывает на, скажем, 0xff00, а ptr+1 будет не 0xff02, а 0xff04 по какой-то причине? И даже если такое возможно, первые два байта-то уж точно же должн читать правильно? Да, указатель может указывать как на начало, так и на конец области памяти, вроде как, но ведь изначально они оба указывают на одну точку, до инкремента ptr'а он обязан взять те же данные, что в value записаны, разве нет?
Точнее, как можно увидеть по ссылке, до цикла значение ptr'а выводится правильно, а вот в первой же итерации, до всяких манипуляций — нет. Обзывайте меня как угодно, только объясните, пожалуйста, что происходит.
>ptr может быть 64 бита, а ты кастуешь на 16 битный указатель.
В смысле? В прошлом сообщении макаба сожрала звёздочки, я нигде 64 бита в 16 бит не кастую. Сам ptr имеет размер указателя, но указывает он на переменную типа uint16_t.
Вот сделал без _t (ну, за тайпдефал стандартные типы) — https://ideone.com/aKGYoJ Всё то же самое.
Возможно, проблема из-за "dereferencing type-punned pointer", gcc на сайте даже ворнинг выдаёт. Раньше читал, но до конца толком не понял, что это такое. Ну, кроме того, что "нельзя" одну и ту же область указателями на разные типы читать. Только если не char•, там можно почему-то.
Вот только почему идентичный принт на разных строках до изменений переменной выдаёт разный результат это не объясняет. Раз уж ломается, почему так выборочно?
godbolt.org
беды с башкой
> Я тебе пидор что сказал, заменить типы на дефолтные, а ты что сделал?
А чем short не дефолтный?
> Вот так правь и уебуй
> typedef unsigned long long int uint16_t;
С чего это uint16_t будет long long? Сделав uint16_t == uint64_t, понятное дело никаких проблем при кастах и возникнуть не может, потому что они просто ничего не делают, типа идентичны. Сам-то вообще понял, что сделал, заменив все типы на один и тот же?
В STM32 запись во флеш идёт только по half-word'ам (16 бит), так что мне нужен был именно 16-байтный тип. Т.е. строка
>٭(uint16_t٭)addr = data;
В любом случае будет, и если эта data другого типа, то опять проблемы могут появиться. Суть моей задачи была разделить 64 бита данных на 4 16-битных куска и позаписывать их в память. Теперь-то я, конечно, переделаю всё на простые сдвиги без подоных алиасингов, чтобы точно правильно работало.
Через union работает без флага.
>В твоем случае если бы ты использовал стандартные инты то было бы проще, ну или заморочился с кастами.
Как я могу использовать int в 32-битной системе для переменной, которая должна хранить 8 байт?
>Как я могу использовать int в 32-битной системе для переменной, которая должна хранить 8 байт?
typedef union { long long my64; struct { int hi; int lo; } } my_int64_t;
как-то так, но не проверял.
Паяльник, ты имеешь право кастовать указатель на uint64_t только в указатели на войд или чар.
Что значит не должна, с чего ты это взял? У меня есть 64-битный айдишник, который я получаю откуда-то там, и вот с ним дальше работать. Это начальное условие задачи, что есть 8-байтная переменная с данными.
>>236960
Ну можно и так, но через юнион проще тогда сразу на uint64_t и uint16_t [4] делить, инты эти мне совсем не нужны.
Короче, есть одна проблема.
Нужна копия массива на этапе компиляции. Масив генерируется из matlab .h файла(весь контент через #define).
Как это сделать?
Просто из матлаба это грузится в мк, где это инит конфигурация, которую надо сверить правильно ли загрузилась.
Я долбоёб и без плюсов constexpr контейнеров не умею.
Не собрался я копировать масив в макросе.
У меня есть .h файл, куда матлаб сбрасывает готовую глобальную переменную массив. Но мне нужна копия этого массива, так как эту переменную как только пройдет 10 мс микроконтроллер изменит и мне надо сверить что изменилось(должно быть также).
Срака в том, что я не могу узнать даже в каком месте поставить memcpy() чтобы копировать в другую глобал переменную, у меня нету кода места записи этого массива, кудя я бы захуярил этот memcpy
>У меня есть .h файл, куда матлаб сбрасывает готовую глобальную переменную массив.
Ну сделай разбор .h файла.
Задача вполне решаема.
Заебца, так и сделаю на питоне хуёне скрипт и в makefile скопирую это говно.
>>237139 (Del)
Ну это я и раньше понял,
>>237117
Идея неплоха, но каждый раз там хуй знает сколько символов и всегда меняются названия.
Сап /clang/ . Можете посоветовать интернет ресурсы где я могу изучать криптографию? Желательно с примерами на C/C++
У тебя криво установлен valgrind, файлы исключений не соответствуют твоей libc. Похоже, что пришло время переустанавливать генту
Спасибо.
Мне нужно принимать данные с ацпшки(10 бит)с частотой 13 мгц. Т.е 10 проводов с ацпшки подключены с 10 пинам GPIO, как мне считывать пины с такой частотой? Пните в какую сторону вобще мне посмотреть. Я уже с ног до головы обмазался документациями никак не могу хоть как-то подобраться к этому вопросу.
ps. Используя библиотеку pipgio у меня получается запустить апаратный шим до 20Мгц. Но опять же никакого понимания как к этому подвязаться нету.
используя библиотеку wiring pi.
Бесконечный цикл while(true) с двумя командами подать 1 на пин, подать 0 на пин, работает с частотой ~470кГц.
https://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/ - вот тут у чела на чистом СИ получился 14 Мгцовый адекватный шим. Когда я скомпилировал у себя у меня получилась говносинусойда на 30 мгц, лул. Опять же как к нему прицепиться?
Если подытожить: как сделать чтобы while(1) работал с частотой 13мГц ? это задержка 0.074 микросекунды, лол, это вобще возможно?
Я буду вам очень благодарен за любую помощь.
Возможно я документацию жопой читаю, т.к мой английский далек от идеала, и есть какое-нибудь решения на готовой библотеке. Может быть вообще нужно делать все как-то по другому.
>это вобще возможно?
Почему нет. Скорость там ограничивается шиной, на которой сидит gpio.
https://github.com/hzeller/rpi-gpio-dma-demo#direct-output-loop-to-gpio
Я не он, но у тебя по ссылке судя по всему не совсем то что требуется. Данные там же синхронные, они должны приниматься не когда попало, а по переднему или по заднему фронту внешнего (для одноплатника) сигнала.
А в обратную сторону можно? Допустим, указатель на чар я могу кастануть в указатель на uint64_t?
>uint8_t arr[8] = {0};
>uint64_t v = ⚙︎(uint64_t⚙︎)arr; ?
Ведь обращение к хардварным адресам/регистрам как-то работает, всякие там ⚙︎(uint32_t⚙︎)addr = data, каст "железного" адреса периферии в структуру с полями её конфига и т.д.?
В чём разница между
>#define GPIOA ((GPIO_TypeDef ⚙︎) GPIOA_BASE)
Где GPIOA_BASE это просто какое-то число, и
>uint32_t addr = &somevar;
>some_type⚙︎ var = (some_type⚙︎)addr;
Ведь в обоих случая просто берётся какой-то адрес: либо "из головы", захардкоженный, либо в рантайме считается, беря адрес какой-то другой переменной. Суть одна и та же — взглянуть на область памяти определённым образом.
Ты немного не так понимаешь.
Есть шина адресов, есть шина данных. Адрес ты можешь вписывать любую хуйню и если она не прокатит, тебе сразу конпенлятор скажет что ты еблан, потому что в .ldscript вписано максимальный адрес и оно не скомпилируется скорее всего или будет бить уведомлениями.
Другое дело, когда тебе производитель, в данном случае STM32 пишет, например, что GPIO это 32 разрядный адрес, это значит что физически к этому адресу есть 32 электронных контакта.
Теперь смотрим что будет:
Ты ставишь указатель с числом куда сказал производитель(оно не будет превышать максимальное число 32 бит, все окей, если бы было больше 64 бит то приложение на МК ушло бы в ресет или что там прошивка мк говорит)
uint64_t gpio = 0xff
Теперь ты берешь и пишешь в ячейку памяти с 32 контактами 64 битное число на запись которой нужно 64 контакта
gpio = 0xf
Что блядь произойдет в конкретной архитектуре конкретного процессора вообще известно только тем кто его сделал. Может два раза перемотать 32 битное число, может процессор послать тебя нахуй и даже не делать такую ебанутую операцию, хуй знает, это undefined behaviour
Как-то не совсем на то ответил, при чём тут запись 64 бит в 32-битную ячейку? Мне ломать ничего не надо, да и я про чтение в основном говорил.
Вот есть там встроенная флеш память. Мне может что-нибудь помешать сделать
>const struct mystruct⚙︎ sp = (struct mystruct⚙︎)addr;
? Вроде работает, да и советы такие на стаке были (с оговорками о совместимости из-за пэддингов и выравниваний, разумеется), но я уже ни в чём не уверен.
Ну и касательно
>ты имеешь право кастовать указатель на uint64_t только в указатели на войд или чар
Вопрос ещё в силе:
>А в обратную сторону можно?
>uint8_t arr[8] = {0};
>uint64_t v = ⚙︎(uint64_t⚙︎)arr;
Работая только с оперативной памятью.
Если я сделаю, скажем, malloc, он найдёт нужное количество байт и вернёт void указатель, который я затем должен кастить в нужный мне тип. Если я создаю переменную в стеке, то он там так же "выделит" память. Почему я не могу её адрес так же в любой (совместимый, так сказать) тип кастить? Я вот этой разницы понять не могу, откуда вообще берётся этот UB из-за type-punning'а. Адрес и адрес, какая разница, откуда он взялся? Если он будет не выровнен как надо, то SIGBUS, да, но я с тем же успехом могу и руками ввести неправильный адрес, при этом компилятор ругаться не будет. В остальном-то что не так?
Еидснтвенное, что приходит в голову, это если из-за оптимизаций он вовсе не создаёт никакой переменной, соответственно и адреса как такового нет, хотя что он в таком случае делает с тем, что я как бы эту переменную с числом далее вообще-то использую, не очень понятно.
Возвращаясь к моему изначальному примеру.
>uint32_t v = 10;
>uint16_t vv = ⚙︎(uint16_t⚙︎)v
gcc на ideone выдаёт
>warning: dereferencing type-punned pointer will break strict-aliasing rules
Однако, если я сделаю
>uint32_t v = 10;
>void⚙︎ ptr = (void⚙︎)&v;
>uint16_t vv = ⚙︎(uint16_t⚙︎)ptr;
То никакого ворнинга о type-punned поинтерах и нарушении strict aliasing'а нет. Но ведь я делаю абсолютно то же самое?!
Как-то не совсем на то ответил, при чём тут запись 64 бит в 32-битную ячейку? Мне ломать ничего не надо, да и я про чтение в основном говорил.
Вот есть там встроенная флеш память. Мне может что-нибудь помешать сделать
>const struct mystruct⚙︎ sp = (struct mystruct⚙︎)addr;
? Вроде работает, да и советы такие на стаке были (с оговорками о совместимости из-за пэддингов и выравниваний, разумеется), но я уже ни в чём не уверен.
Ну и касательно
>ты имеешь право кастовать указатель на uint64_t только в указатели на войд или чар
Вопрос ещё в силе:
>А в обратную сторону можно?
>uint8_t arr[8] = {0};
>uint64_t v = ⚙︎(uint64_t⚙︎)arr;
Работая только с оперативной памятью.
Если я сделаю, скажем, malloc, он найдёт нужное количество байт и вернёт void указатель, который я затем должен кастить в нужный мне тип. Если я создаю переменную в стеке, то он там так же "выделит" память. Почему я не могу её адрес так же в любой (совместимый, так сказать) тип кастить? Я вот этой разницы понять не могу, откуда вообще берётся этот UB из-за type-punning'а. Адрес и адрес, какая разница, откуда он взялся? Если он будет не выровнен как надо, то SIGBUS, да, но я с тем же успехом могу и руками ввести неправильный адрес, при этом компилятор ругаться не будет. В остальном-то что не так?
Еидснтвенное, что приходит в голову, это если из-за оптимизаций он вовсе не создаёт никакой переменной, соответственно и адреса как такового нет, хотя что он в таком случае делает с тем, что я как бы эту переменную с числом далее вообще-то использую, не очень понятно.
Возвращаясь к моему изначальному примеру.
>uint32_t v = 10;
>uint16_t vv = ⚙︎(uint16_t⚙︎)v
gcc на ideone выдаёт
>warning: dereferencing type-punned pointer will break strict-aliasing rules
Однако, если я сделаю
>uint32_t v = 10;
>void⚙︎ ptr = (void⚙︎)&v;
>uint16_t vv = ⚙︎(uint16_t⚙︎)ptr;
То никакого ворнинга о type-punned поинтерах и нарушении strict aliasing'а нет. Но ведь я делаю абсолютно то же самое?!
>А в обратную сторону можно?
Можно. Разрешено ровно то, что необходимо.
>В чём разница между
>#define GPIOA ((GPIO_TypeDef ⚙︎)
GPIOA_BASE)
В первом случае адрес является константой. Это красный флаг для компилятора, т.к. это может оказаться адресом любого объекта. Во втором случае компилятор понял, что ты берешь адрес somevar и наоптимизировал. Кстати, в uint32 адрес превращать непортабельно, используй intptr_t или хотя бы long.
> откуда вообще берётся этот UB из-за type-punning'а
(Тред не читал). UB в стандарте всегда избыточные. Очень сильно избыточные. А причины вот такие, например:
- trap representations - это когда процессор конкретную комбинацию бит не любит обрабатывать, и делает эксепшен на нее (этого нигде нет в современных машинах: можно, конечно, заставить x86 на флоатах трапаться, но требуется много телодвижений).
- выравнивание - например, нужно, чтобы адрес инта был кратен четырем, и если ты кастанешь чар в инт, это будет соблюдаться не всегда, и будет эксепшен. Понемногу это требование становится ненужным: в x86 это нужно специально включать (по умолчанию все работает без выравнивания, ну кроме SIMD и interlocked), в арм раньше было обязательным, но теперь все тоже работает в любом случае. Нормальные разработчики стандарта сделали бы все это unspecified или даже implementation-defined behavior, но комитет любит портить людям жизнь, поэтому это UB.
- третье - это UB-driven оптимизации, когда разработчики стандарта (многие из которых разработчики компиляторов, засевшие в комитете по стандартизации) специально, назло тебе, ради призрачного полпроцента производительности ломают твой код. Например, компилятор может считать, что указатели на int и uint64_t гарантированно ссылаются на разные объекты в памяти (strict aliasing), закладывает на это всякие оптимизации вроде отложенной записи, ты читаешь по неправильному указателю, и читаешь не те данные, что должны были там лежать с точки зрения сишной абстрактной машины.
В целом, если ты знаком с архитектурой и знаешь, что делаешь, все нормально работает и с кастом, и с type-punning через union, диванных не слушай.
#define macroIf(trcod,flcod) if(x<100) { trcod } else { flcod }
int x,y,z;
int main()
{
macroIf(
// 2 строки кода на 1-й аргумент:
y = x + z;
y = z y;
,
y = x z; // 1-я строка кода на 2-й аргумент
y = y - z; // 2-я строка кода на 2-й аргумент
)
}
Обратный слэш не нужен в строках 7...13? Комментарии в строках 7...13 можно обозначать двумя слэшами, а не блоком? Если аргументы или комментарии будут содержать внутри запятые, повлияют ли они на подстановку в макросы? Возможно ли макрос подставлять на место аргумента другого макроса?
а, я не о том вообще..
>в арм раньше было обязательным, но теперь все тоже работает в любом случае.
А у того анона STM32, то есть Cortex-M0/M3/M4 и может быть M7. Для M0 выравнивание необходимо. И никуда Cortex-M0 в обозримом будущем не исчезнет, точно так же как 8051.
>>240876
M4 у меня, и да, выравнивание там всё же нужно, вроде как. По крайней мере я разок с попыткой каста из адреса нечётного элемента чар буфера уже обосрался. При этом, что интересно, ломалось оно только с выключенными оптимизациями (логично), а с -Os он каким-то образом там всё переставлял и у него вполне получалось правильно выполнять код:
>uint8_t buf[9];
>receive_data(buf);
>uint64_t v = ⚙︎(uint64_t⚙︎)&(buf[1])
Смотреть, что он там сгенерировал как-то не дошли руки.
>из адреса нечётного элемента чар буфера
Ты же не думаешь, что чётный элемент гарантирует выравнивание?
>M4 у меня, и да, выравнивание там всё же нужно, вроде как.
Там не все инструкции могут работать по не выровненным адресам, но большая часть может в отличии от ARMv6 и предыдущих.
>и у него вполне получалось правильно выполнять код:
Не слишком ли много лишних действий? Не проще ли было сразу взять uint64_t?
> выравнивание необходимо
Да похуй, у компиляторов арм принято в таких случаях просто читать побайтово и собирать. Так что будет перфоманс дроп в качестве UB.
>>241210
> Возможно ли при использовании макроса в аргументах вставлять несколько строк кода
Полноценно нет, на зачем тебе, если в Си переводы строк почти везде можно заменить на пробел?
> Если аргументы или комментарии будут содержать внутри запятые, повлияют ли они на подстановку в макросы?
Иногда. Зависит от того, где макрос раскрывается.
> Возможно ли макрос подставлять на место аргумента другого макроса?
Да.
Я думаю, что нечётный гарантирует невыравнивание, поэтому так и выразился. А гарантирует, вероятно, нулевой и каждый n-ый.
По крайней мере этот код — https://ideone.com/OtuNQX — у меня выдаёт:
>&a = 0x2000185f, &b = 0x2000185c, &c = 0x20001858
>&d = 0x20001854, &e = 0x20001850, &f = 0x20001848
>&g = 0x20001840, &h = 0x20001838, &i = 0x20001830
>&j = 0x20001824, &k = 0x20001818
т.е. char где угодно выходит, а все массивы обязательно начинаются на байте, кратном четырём. (На самом идеоне, однако, это не так, и каждый массив начинается на следующем за последним "занятым" байтом.)
>>241439
>Не слишком ли много лишних действий? Не проще ли было сразу взять uint64_t?
Там функция принимает байты извне (по onewire), и затем уже я вот как раз это всё дело и соединяю в один удобный инт для дальнейшей работы (а первый байт в данном случае надо отбросить, потому что там отправленная перед этим команда). Не всегда одно и то же количество байт принимается, не всегда из них все вообще нужны, и т.д. То есть, где-то в любом случае придётся вот так собирать целое число из отдельных байтов.
>А гарантирует, вероятно, нулевой и каждый n-ый.
А в станларте такого нету.
union {
uint32_t align;
char buf[9];
} u;
Не совсем понятно, что тут должно произойти. Типа, выделив под этот юнион 12 байт, нужные для буфера 9 могут оказаться где угодно внутри этого пространства, что ли?
https://ideone.com/0BP8rv до сих пор выдаёт нормальные, кратные четырём адреса:
>&un = 0x20001848, &un2 = 0x20001854, u16 = 0x20001806
>&un.buf = 0x20001848, &un2.buf = 0x20001854
Если тут что-то может пойти не так, то и через union type-punning тоже нельзя, но ведь советуют? Говорят, что всё ок и по спеке — https://stackoverflow.com/questions/25664848/unions-and-type-punning
А если всё по спеке, то как там может быть не выровнен адрес элементов? Не может же он хранить начало буфера в каком-нибудь 0x1 адресе (из которого обычно uint32_t не прочитать), но когда ты обращаешься к uint32_t элементу, каким-то магическим образом всё же получать правильное значение.
Не уровня, напиши функцию складывания двух int, а что то посерьезней и интереснее (с указателями к примеру)
codewars
Книга Crafting Interpreters - вторая половина про написание интерпретатора на С, есть упражнения.
В голове при слове указатель вот такой концепт - память это "массив" байтов (2^64-1) где индекс это номер байта в этом "массиве". указатель это просто индекс (первый) в этом "массиве", а значение это содержимое 'массива' по данному индексу(указателю)
Норм так думать об указателях? или такой концепт в будущем спотыкнется обо что то?
второй вопрос, почему для unsigned чисел реализован механизм операций по модулю, то есть если я выйду за диапазон, оно будет все операции делать по модулю Unsigned_Type_MAX
(пример 0u - 1u) Почему для ансайнт чисел такое есть, а для обычных такого нет. И какой в этом глубинный смысл...
>Норм так думать об указателях? или такой концепт в будущем спотыкнется обо что то?
Норм. Спотыкнётся об виртуальную память, таблицы страниц, TLB и вот это вот всё.
> второй вопрос
https://stackoverflow.com/questions/18195715
профессионально ищу на stackoverflow, дорого. звонить 8-800-555-35-55
>или такой концепт в будущем спотыкнется обо что то?
Комитет не хочет, чтобы ты так думал. Указатель (в мифическом Эльбрусе) может быть сущностью, для которой оперделны операции создания, преобразования, разыменования, индексации...
> Спотыкнётся об виртуальную память
Трансляция адресов никак не пересекается с указателями, а про маппинг в юзермоде можно успешно думать отдельно.
>>243036
Не только в мифическом эльбрусе, но и в реальном x86 под досом far-указатели - не совсем индексы. Но думать об указателях, как об индексах в адресном пространстве все равно очень удобно и наглядно.
>>242891
> Почему для ансайнт чисел такое есть, а для обычных такого нет. И какой в этом глубинный смысл...
Много-много лет подряд, когда уже весь мир хранил числа в дополнительном коде, комитет по стандартизации сишки отказывался фиксировать метод хранения чисел со знаком. А потом компиляторы подтянулись и начали пилить оптимизации, основанные на UB при переполнении знаковых чисел, и уже ничего не изменить. И вот спустя почти 35 лет после выхода первого стандарта в Си наконец укажут, что у нас дополнительный код, но... UB не уберут.
>думать об указателях, как об индексах
Ты указатель с адресом попутал, учитель херов.
>очень удобно и наглядно
Дебилизм какой-то. Что тебе непонятно прямо на пикриле, безо всяеких манямассивов с маняиндексами?
Указатель - это адрес объекта, плюс-минус дополнительные данные у fat pointers. Адрес объекта - это индекс первого байта объекта в адресном пространстве. Он же офсет (смещение) объекта в байтах, считая от начала адресного пространства. На некоторых архитектурах все может быть немного сложнее.
> Что тебе непонятно прямо на пикриле
Ты притащил файл, в нем лишь офсеты, указателей и адресов нет по определению, так как нет памяти.
Адрес объекта - это индекс первой ячейки пам'яти, начиная с которой расположен объект.
> printf("c - \c");
Вывод:
c - c
Если это неизвестная esqape sequence, то куда пропадает косая черта?
Дальше больше, я ввожу такое:
>printf("e:\e");
И оно рисует стрелку вообще, что за дела мудрецы?
Привел табличку ескейпов и там нет \e
\e это расширение в некоторых компиляторах. Оно аналогично \033 то есть стрелочка вверх.
Косую черту съело потому что по правилам \ начинает esq-sequnce . Чтобы нарисовать косую черту делай так : printf("%c",'\\');
>Чтобы нарисовать косую черту делай так : printf("%c",'\\');
printf("\\");
putchar(putchar(92));
Второй способ меньше по коду.
>write не stdout
в смысле не stdout? А куда? Я думал stdout это просто какой-то файл и вывод это собственно запись туда. Если нужно отобразить на экран то fflush. Ну а printf делает то же самое только буферизирует и само смывает когда надо.
В чем я не прав?
Насколько я знаю, кэширование stdout производит libc, а запись в файл небуферизируется. Но это надо уточнить и может зависит от реализации. В моей системе по крайней мере так.
Этот прав, я просто не очень точно выразился. Сишный stdout кэширует, а по \n (или по fflush, или если буфер кончится), пишет буфер через write. Там ниже write на уровне ядра тоже может быть кэш, но, по крайней мере, по умолчанию, если у тебя терминал, то все записанное через write сразу отобразится.
Вы видите копию треда, сохраненную 11 июля 2022 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.