Это копия, сохраненная 13 июля 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ или http://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Классика от Отцов: http://www.cypress.com/file/56651/download
- Stephen Prata "C Primer Plus, 6th Edition" (2014): относительно свежая, знает про C89/C99/C11, описывает различия, объемная (около тысячи страниц), годная, с вопросами, упражнениями и ответами. Читать после K&R или до.
- Годное пособие для гуманитариев: http://web.archive.org/web/20160727235220/http://c.learncodethehardway.org/book/ (автор внезапно захотел денег)
- Немного примеров хорошего стиля: http://www.oualline.com/books.free/style/index.html
- ООП, например: http://www.cs.rit.edu/~ats/books/ooc.pdf
- Стандарт ISO/IEC 9899:1999 (он же C99): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf (драфт)
- Стандарт ISO/IEC 9899:2011 (он же C11): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (драфт)
- man/Dash/zealdocs
Чем конпелировать:
- Очевидный GCC.
- clang: оче годно, батя рекомендует.
- Intel C++ Compiler: оптимизации, тысячи их.
- Visual Studio 2017 Community Edition: внезапно этим стало можно пользоваться, особенно с тулсетом clang/C2. Поддержка C11 на уровне "есть все, что тебе понадобится в реальном проекте плюс кривая библиотека". Анализатор кода в комплекте.
- Pelles C (шиндоуз онли): поучиться, вкатиться в C11 (стандарт полностью реализован, имеются в том числе threads.h и прочие stdatomic.h), но количество багов в оптимизаторе и редкие апдейты напрочь отбивают желание собирать этим что-то сколько-нибудь серьезное.
- TCC: очень маленький компилятор с багами и неполной поддержкой C99. С ключом -run умеет компилировать код в память и запускать его, что позволяет писать скрипты прямо на сишечке.
Что еще почитать:
http://c-faq.com/
FAQ из comp.lang.c. Древний, но все еще актуален.
Samuel P. Harbison, Guy L. Steele Jr. "C: A Reference Manual, 5th Edition" (2002)
Ебаный пересказ стандартов C89 и C99 (включая стандартную библиотеку). Для не осиливающих стандарт в оригинале. Читать в качестве подготовки к собеседованиям (есть задачник с ответами) и для ознакомления с масштабами пиздеца перед написанием своего парсера/компилера.
Peter Van Der Linden "Expert C Programming. Deep C Secrets" (1994)
"Си: грязные истории". Смехуечки, немного объяснений, чем обусловлены особенности языка, всем известные подводные камни кто там ругал косяки в JS? у нас в сишечке их гораздо больше, просто они лучше спрятаны, немного байтоебли и непонятно откуда взявшаяся глава про старинные плюсы. Читать в качестве сказки на ночь (на пару вечеров хватит).
Richard M. Reese "Understanding and Using C Pointers. Core Techniques for Memory Management" (2013) - почитать, вкатиться в указатели.
Ben Klemens "21st Century C: C Tips from the New School" (2012)
Paul Deitel, Harvey Deitel "C for Programmers with an Introduction to C11" (2013)
Stephen G. Koch@n "Programming in C (3rd Edition или 4th Edition, если найдется)" (2014)
MISRA Ltd. "Guidelines for the Use of the C Language in Critical Systems" (2013)
Набор рекомендаций по написанию надежного кода на C (промышленный стандарт). Читать - однозначно, следовать - вдумчиво и без фанатизма. Также можно посмотреть https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard
Еще более длинный список: http://www.iso-9899.info/wiki/Books#Learning_C
Онлайн-утилиты:
- https://godbolt.org/ - Compiler Explorer позволяет посмотреть выхлоп компиляторов для введенного куска кода (больше полусотни разных версий компиляторов).
- http://cdecl.org/ - С Gibberish ↔ English помогает читать сложные сишные декларации.
Прошлые треды:
- №26: https://arhivach.org/thread/315652/
- №27: https://arhivach.org/thread/325831/
- №28: https://arhivach.org/thread/339326/
Шапка: http://piratepad.net/bJ1SdmkZyu
Всё сагоёбишь?
>>56530
Ладно, тогда вопрос по прикладному С:
Сейчас у меня есть массив структур с кастомными функциями под микруху для чтения, которым нужно передавать адреса элементов. Вопрос: можно ли этот код который я наиндусил как-то переписать по-человечески с нормальными указателями структуры?
Ну и всю структуру затягивать через pgm_block_read я тоже не хочу, потому что потом буду писать код в котором нужно будет затягивать/записывать только одну переменную.
Вот описание для функций библиотеки: https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
> переписать по-человечески с нормальными указателями структуры?
Не совсем понятно, чего ты хочешь. Ты разрешения спрашиваешь? Да, можно. Нет, не особо нужно: под капотом при возврате структуры размером больше, чем влезает в один-два регистра, функции неявно передается указатель на результат, функция его туда пишет, все счастливы. Возможно, для авров компиль более тупой, хуй знает.
>Не совсем понятно, чего ты хочешь.
Ну я хочу заменить все эти танцы с бубном и инкрементами указателя на что-то вроде ret_test.wind = pgm_read_word(&Profile[time].wind) и так далее, так можно сделать? Какой правильный синтаксис для таких конструкций?
Да хуй там, оказывается можно указывать на сами элементы массива. Жалко только что нету ассемблерного кода для считывания вообще всего блока.
Вступление к соответствующему стандарту или справка от Pelles C.
> правда нигде не сказано о том как malloc выравнивает левую границу
Сказано. malloc делает выравнивание так, чтобы оно было достаточным для любого встроенного типа. Для всего остального есть aligned_alloc из C11.
> Мне два бита нужно
Чо? Тебе бы что-нибудь по архитектуре компов почитать. Минимально адресуемая единица - байт. А на практике, любым маллоком будет выделено не менее sizeof(uintptr_t).
>Чо?
Мне в указателе, в крайних двух разрядах, необходимо сохранить два флага, в самой переменной, а не в выделяемой памяти я имею в виду.
Ты всё-таки почитай как адресуется память и как происходит чтение-запись.
тут уже один чувак так делал, в в одном заведении учитесь?
по идее гарантий никаких нет. вроде нет соотв. дефайнов на этот счёт. выделяй сразу с запасом. (void@)((uint_ptr)malloc(T + 3) & ~(uint_ptr)3)
у меня кстати по этой теме вопрос, можно как-то сделать обёртку над malloc, но чтобы с тем же именем? или это должна быть поддержка библиотеки, там, альтернативное имя...
>можно как-то сделать обёртку над malloc, но чтобы с тем же именем
Вот тут у мужика что-то вышло, я правда хуй его знает насчёт переносимости.
https://habrahabr.ru/company/mailru/blog/281497/
>но тогда хранить нужно и настоящий адрес
Тут за два бита битва, а ты целиком адрес хранить предлагаешь.
Во догонку ещё вроде бы BoehmGc умеет подменять обращения к malloc,
А как-то статическую переменную по кратному адресу выровнять можно?
Или только инклюдить через ifndef
#define LOH 123
#include "../" + LOH + "/file.h"
родные, покажите реализацию компаратора для типа double, пожалуйста
почему bool а не int?return fabs(a - b) < EPSILON; возвращает + если разность "~0" и - если числа разные, я правильно понял? но ведь компаратор не только говорит разные числа или одинаковые, он еще говорит какое больше
#include <stdalign.h> // C11, но есть расширения и для более старых версий стандарта.
>>58137
Можно.
#define LOH 123
#define INCLUDE_CAT(...) INCLUDE_CAT_(__VA_ARGS__)
#define INCLUDE_CAT_(...) #__VA_ARGS__
// Мы работаем с токенами, поэтому кавычки не нужны, их ставит
// INCLUDE_CAT_, а если нужны <> вместо кавычек, то делаем так:
// #define INCLUDE_CAT_(...) <__VA_ARGS__>
#include INCLUDE_CAT(../LOH/file.h)
>>58442
Ну так добей условие-то, в чем проблема-то?
double delta = a - b;
return (fabs(delta) < EPSILON) ? 0 : (delta < 0) ? -1 : +1;
>>58137
Чета я подумал, что оно так может что-нибудь еще в пути к файлу случайно развернуть, если оно совпадет с именем макроса. Например, #define file ERROR оно будет инклудить ../123/ERROR.h, что не есть хорошо. Лучше разворачивать только LOH:
#define INCLUDE_BUILD(S) INCLUDE_CAT(../test/S/file.h)
#define INCLUDE_CAT(...) #__VA_ARGS__
#include INCLUDE_BUILD(LOH)
Ты про spaceshit? Нету. Как ты в него нужный эпсилон передашь? Ах никак, ах авторы компилятора интерпретатора твоего языка лучше тебя знают, какая погрешность у твоих значений?
да
Я делаю выборку из БД и сколько строк она вернет - неизвестно. Проходясь циклом по результату выборки я каждую строку помещаю в структуру, а структуру в массив. Для этого перед каждой выборкой мне приходится сначала выбирать количество записей и на основании его инициализировать массив. То есть приходится делать два запроса, хотя полезные данные возвращает только один из них. Скажите, как мне затолкать результаты выборки в массив заранее не зная его размера?
никак, певый скюл запрос с каунт закеширует результат в бд, второй будет бесплатно. ну или читай фиксированными чанками.
Хм, ну если на производительности это не скажется то пусть так и остается. Спасибо.
Почти двачую. Список чанков, хранящих по n записей - это правильный способ решения проблемы, если производительность критична аж пиздец как. Если нет - realloc тоже сойдет.
Как в vs2017 (или вообще какими ключами компиляции) смерджить все секции в одну - .text? Я видел в msdn'е статьюю про /merge .rdata=.text, но там не сказано, какой разделитель и как использовать для нескольких секций
> но там не сказано, какой разделитель и как использовать для нескольких секций
Сделай несколько мержей: /MERGE:.rdata=text /MERGE:.data=.text /MERGE:.bss=.text
Наиболее красиво - это выкинуть массив нахуй, и обрабатывать записи по мере поступления. Попробуй, может, получится. В большинстве случаев получается. Тем более что в С++ вроде бэкпортили range из D, так что должно быть несложно. (Не знаю точно так как давно не юзал). Если не получается и по данным надо что-то считать с рандомным доступом, возможно, ты просто хуево знаешь SQL, потому что когда ты его знаешь хорошо, ты выбираешь уже все готовое к применению.
это все еще я, ну вот даже простой пример: подключаю stdio.h вызываю printf все норм, опять же захожу в сборище заголовочных файлов меняю расширение у файла stdio.h на stdio.c в коде тоже все меняю, повторно компилю и опять все норм робит ну и как так
ну тип так и должно быть? это нормально? то есть если я хочу то могу спокойно писать заголовочные файлы с расширением .c??
> в чем разница нахуй между файлами .c и .h
Для Си, как языка - ни в чем, можешь хоть .yoba называть все свои файлы. Другие утилиты, например, make, ожидают, что ты назовешь исходник foo.c, чтобы make foo (без Makefile) смог правильно сработать.
>>64036
> писать заголовочные файлы с расширением .c
Можешь. Некоторые делают кладут static inline функции в отдельные файлы с расширением .inl. В крестах так и вообще разброд и шатания, там есть и .h, и .hpp, и .hxx, и .hh, и даже .h++ раньше было. Ты можешь делать все, что угодно, но старайся быть консистентным и очевидным по мере своих сил.
не знаю принято ли тут говорить спасибо, но спасибо.
Чисто логическое разделение. Грубо говоря в хэдэрах всё прототипизируется, а в файлах кода реализуется. Можешь проект в лям строк хоть в 1 .c захерачить, но будет ли это удобно? (особенно когда дело коснется препроцессора).
Это ты ещё банальным вопросом задался, ведь может быть всякое: .c .h .cc .hh .cpp .hpp .cxx *.hxx и т.д.
Заголовки отдельно нужны, чтобы ты мог использовать чужие _скомпилированные_ библиотеки. И чтобы кто-то мог использовать твои.
Т.е. в заголовках - "интерфейс", всё, что тебе нужно, чтобы использовать библиотеку. Сами исходники при этом - не нужны.
Это как interface в джаве, примерно.
Например, ты можешь взять чужую коммерческую библиотеку, на которую исходников тебе в принципе не дадут, и успешно её использовать.
Это основной смысл, остальное - структурирование кода и т.п. - по желанию.
Возник тупой вопрос. Следующие две команды идентичны или нет?
double (зв)x = (double(зв))malloc(10 x sizeof(double));
double (зв)x = malloc(10 x sizeof(double));
Если да, зачем тогда в таких случаях пишут приведение типов?
Если нет, не является ли вариант с приведением медленнее чем без него?
В Си указатель на void автоматически и неявно кастится к указателю на другой тип (и обратно). В крестах такого нет (у них там type safety типа), поэтому нужен явный каст. Разницы по производительности нет. Каст возвращаемого маллоком значения - классический признак человека, который учил не Си, и не кресты, а некий "си с классами".
теоретически это может помочь при рефакторинге. но мы же знаем, что функции должны быть такого размера, чтобы всё было в ней понятно и видно сразу.
>Если да, зачем тогда в таких случаях пишут приведение типов?
Чтобы обеспечить переносимость сишного кода на кресты.
Бля, посмотрел видео. Смешанные чувства. С одной стороны он прав, хотя блин... Вроде и бредит немного.
2 часа смотреть как какой-то петух рассказывает про свой стиль программирования?
typedef struct govno
{
bool pahnet;
} govno;
govno *today = calloc(sizeof(govno));
if (today->pahnet == true)
{
return(1);
}
else if (today->pahnet == false)
{
return(2);
}
else
{
return(3);
}
Не скомпилируется.
В теории представление _Bool может хранить хоть 'y'/'n', и разворачиваться в 0/1 только при использовании в выражениях, хотя на практике никто такой хуйней не страдает. Поэтому если исправить ошибки, вернется 2.
>>66508
Задай более развернутый вопрос. Конец файла - это специальное значение, выходящее за пределы диапазона, применяющегося для символов. Его возвращают как индикатор того, что символов больше нет. Физически никакого конца файла уже лет 30 как не существует.
ребят простите за ламерский вопрос , но интересно куда возвращает значение return доупстим из мейна или та же функция exit куда они выводя значения и где их посмотреть
> где их посмотреть
В винде (в сосноли):
app.exe
echo %ERRORLEVEL%
В линуксе (в сосноли):
./app
echo $?
(или можно приглашение настроить, чтобы код возврата предыдущей команды автоматически выводило). Алсо, можно получать код возврата программно (для этого он и придуман).
> куда возвращает значение return
В main() return EXPR полностью аналогично вызову exit(EXPR);
https://ideone.com/wLxTJb
Смешно.
Следующий. Только не клоун, пожалуйста.
С помощью маски надо одновременно изменить состояние одного \ нескольких битов в байте, не затрагивая не нужные. Порядок бит (как в самом байте, так и в выбираемых для изменения) - MSB...LSB.
Очевидно, что когда маска зависит от числа, тебе не нужна маска, потому что результат - константа. А если тебе нужно менять биты в рандомном числе, тебе нужно ДЖВЕ маски - для and-not и для or. Такие дела.
В Си++ коде именно так. Поэтому и прошу переписать.
Пусть даже за вознаграждение. Разумное. 300к нет.
Ну бля. Делоешь маску mask, в которой в которой нолики стоят там, где будешь менять биты (в Си литералы все еще не умеют в binary, если что). Записываешь биты bits, где в нужных местах стоят биты, которые нужно установить. Применяешь.
// Будем менять биты 6, 5, 3, 1.
uint8_t mask = ~((1 << 6) | (1 << 5) | (1 << 3) | (1 << 1));
// Будем ставить биты 6 и 3 в 1, а 5 и 1 в 0.
uint8_t bits = (1 << 6) | (1 << 3);
// Какой-то байт.
uint8_t value = (uint8_t) (rand() & 0xff);
// Применяем.
value = (value & mask) | bits;
> Порядок бит (как в самом байте, так и в выбираемых для изменения) - MSB...LSB.
А в крестовом коде LSB->MSB, как у нормальных людей. Ну пиши там (8 - 1 - индекс_бита), если сильно надо.
Спасибо попробую собрать. Хотя не уверен, что получится.
Дай фейкомыльце, а?
Может ещё будут предложения.
> Дай фейкомыльце, а?
suck_my_nerd_co8\BckANUSmaijv%lPUNCTUMrXv\u
> Может ещё будут предложения.
С пошлостями не обращаться.
зы: дятел, за каким хуем ты учишься? Пиздуй сраз в макхряк трудоустраиваться
Ну смотри. Можно абстрагироваться над файлом и представить себе трубу из которой выливаются символы один за другим. Тебе похуй, откуда они там в трубе берутся - может быть, они из файла читаются, может их пользователь ввел, может их другая программа на лету генерирует, а может они через сеть прилетели. И вот ты читаешь символы, а потом тебе прилетает вместо символа хуй (EOF). Тут-то ты и понимаешь, что больше у этой трубы ловить нечего. Вот это потоки. Потоки символов, байтов или еще какой-нибудь хуйни (в Си - потоки символов).
В первый раз слышу про потоки, честное слово. Сравнение канализацией попахивает. Тебе может быть пойти на сантехника отучиться?!
Если по теме, то тебе необходимо читать файл в бесконечном цикле, опционально добавив задержки на чтение (читай про семафоры) при eof == true, кеш организовать, чтобы не читать файл каждый раз сначала.
Посмотри код tail, ключ -f к этой утилите именно то, что тебе надо.
Все тоже самое, что и в скриптовых языках типа пиздона или эрэнэра.
> Расскажите про стандарты языка. Что это и как это. Что значит поддержка компилятором стандарта.
В Си на текущий момент три стандарта. Это такие документы, очень скучно и подробно описывающие язык. Поддержка стандарта означает, что поддерживаются все нововведения по части синтаксиса (компилятором), а в стандартной библиотеке (если она идет с компилятором) присутствуют все новые функции, наличие которых гарантирует стандарт.
>>66915
> Почему тогда раз машинный код для каждого процессора разный
Есть архитектура процессоров и архитектура набора команд (instruction set architecture). Вторая меняется очень редко. Например, твой процессор вполне способен выполнять инструкции, которые применялись в середине 80-х. А вот в обратную сторону это, очевидно, не работает. Современные инструкции старый процессор не осилит. И сейчас ты можешь собрать код для процессора с поддержкой AVX и соснуть на каком-нибудь старом ноуте.
> у меня амд а у приятеля интел
Архитектура команд у AMD и Intel по большей части одинакова.
Подробно писать не буду, ибо заебусь печатать.
Есть некий код, компилятор переводит его в машинный код, чтобы у тебя что то на экране появилось - это уже функция ОС, ну там окошко, текст, картинка. (Я сейчас не гвоорю про прямой вывод на экран текста из ассемблера).
Короче, программа имеет структуру - заголовок, откомпмлированные инструкции к выполнению на ЦП и т.п.
Запуская приложение ЦП анализирует и поэтапно выполняет код(откомпилированные инструкции).
Лень откровенно новоря приводить примеры как Си код вюпревращается в ассемблер, который в виде инструкций поступает на конвеер ЦП и как там память кеш и прочие компоненты задействованы.
Берем, например ци89. Есть там абстрактная комнда fuck(), которая в наборе инструкций интел и амд ЦП будет соответствовать последовательсти jmp ax, cmp e6, e4... и т.п. У интела это будет инструкция нащываться А, а у АМД Б.
Побитовые операции есть даже в javascript, но куда тебе дегенерату знать про это.
В ньюфаг-тред.
Задача - вывести ласт слово задом наперёд.
Вывод: euelueblue
Кто пояснит?
gcc 5.4.0
Или гений выше перепутал компилятор с иде?
Насколько я понял - да, перепутал. Увидил интерфейс моего саблайма и спросил что за компилятор.
Да, перепутал. Всё, придётся выйти покурить в окно. Так дальше жить нельзя.
П.С. Мне вот интересно, тут все обиженки, которые мусолят курьёзные случаи в чатиках \ курилке с такими же чуханами, как и они сами?
Выглядит так, что вам кто-то насрал на голову, а смыть жижу вы можете только типа "язвительными и остроумными" на самом деле - нет ответами в подобных тредах?
Вроде ничего пиздец архи-сложного не спрашивал, лол.
тебя даже никто не трогал, взял ещё и обиделся. тебе лечиться надо.
У структуры прописываешь поле "рефкаунт", пишешь методы "инкреф" и "декреф". Во втором прописываешь логику освобождения памяти.
Во-первых, этот костыль работает только для массива, выделенного на стеке, во-вторых, попробуй вынести этот код в функцию и посмотри, что будет.
Причина "во-первых" и "во-вторых" одна и та же, sizeof(x)/sizeof(*x) для динамически выделенного массива будет использовать только очень особенный пограммист.
>sizeof(x)/sizeof(*x) для динамически выделенного массива будет использовать только очень особенный пограммист.
Ты скозал?
Ну и что же используют господа, обучавшиеся в Хуеле?
Я не настаиваю, конечно, в следующем коде нет ничего противозаконного
int x = malloc(10sizeof(int));
printf("%d", sizeof(x) / sizeof(*x));
Но результат может немного расстроить.
А еще можно после твоего printf сделать x[100]=0xdead. По твоей логике [] зло, нужно написать какую-нибудь array_set(), которая проверяет границы, лишь бы какой-нибудь недоучка не обосрался. Тебе в другой язык с таким подходом.
Так и я о том же.
на степика есть задача, где нужно написать программу, принимающую кириллицу, далее дефолтная работа со строкой и вывод. Решил wchar, сказали збс а теперь без wchar, сказали думать в направлении, что кириллица не помещается в char
Не знаю, кто такая эта ваша степика, но если у тебя нормальный линукс, ты можешь использовать UTF-8 (на винде тоже можешь, но в винде UTF-8 в консоли можно сделать только в десяточке) - если кириллица не помещается в один char, то может поместиться в несколько char. Про подробности кодирования UTF-8 см. википедию. Но без сборки хотя бы одного символа в wchar_t/char16_t/char32_t ты со строкой нормально не поработаешь (ну, конечно, моооожно, но больно).
Что тебе не понятно? Обычный односвязный список.
Правильные ребята пишут так: for (; ∗current; current = &((*current)->next));
Бля, ахуенно жеж.
А потом ты поменял тип x, или не ты, что только увеличивает вероятность внесения ошибки
https://pastebin.com/Pdv3jmv9
> Error in `main': malloc(): memory corruption (fast): 0x00000000013470e0
Посоны, почему возникает ошибка? Видимо, из-за функции f2, она как-то распидарасивает мою память void*. А как тогда правильно?
Ты считаешь адреса неправильно. Сделал бы структурку типа struct { double res, x; int y; } и выделял бы ее. А у тебя вот это ок:
double ∗x = (double∗)memory;
Дальше твой массив y залезает на конец массива x, потому что тебе нужен адрес memory + n ∗ sizeof(double) = memory + 8n, а у тебя сложение (адресная арифметика) для указателя на инт, поэтому ты считаешь memory + n ∗ sizeof(int) = memory + 4n.
int ∗y = (int∗)memory + size;
Дальше ты скипаешь 2n даблов: memory + sizeof(double) ∗ 2 ∗ n = memory + 16n (адресная арифметика для double), что нихуя не равно memory + (sizeof(double) + sizeof(int)) ∗ n = memory + (2 + 4)n = memory + 6n:
double ∗res = (double∗)memory + 2∗size;
Соответственно, в этом последнем блоке ты вылезаешь за пределы массива.
Можешь считать итеративно:
double ∗x = memory;
int ∗y = (int ∗)(x + size); // Адресная арифметика для double∗.
double ∗res = (double∗)(y + size); // Адресная арифметика для int∗.
Это будет работать, если выравнивание, требующееся для дабла равно выравниванию, требующемуся для int. Иначе стоит сложить сначала оба массива даблов, потом уже инты. Но вообще, такой подход говно, не делай так, если не уверен.
> Но вообще, такой подход говно, не делай так, если не уверен.
А как тогда делать?
У меня есть некоторая довольно большая структура
typedef struct {бла-бла-бла} mystruct;
несколько функций типа
int f(unsigned size, бла-бла);
которые:
1. Должны вызываться несколько тысяч раз.
2. Содержат в себе кучу различных маллоков
type ∗x = malloc(size ∗ sizeof(тип));
Препод сказал, все говно (и он прав, ибо сишный код работает по скорости так же, как питоновский прототип), ирл в таких случаях делают менеджоры памяти.
Понятия не имею, что такое менеджер памяти. Потому я добавил в структуру поле void∗, куда засовывается память, которая использовалась бы вместо маллоков внутри функции.
А как следовало поступить тогда?
Небольшой пример в выше я написал просто чтобы разобраться, почему у меня все неправильно работает.
За итеративный способ спасибо, пока так и сделаю.
> Содержат в себе кучу различных маллоков
Ну так уменьши количество маллоков, посчитай, сколько тебе памяти нужно и выделяй заранее, не внутри цикла, а перед ним. А менеджер памяти у тебя уже есть, ты из него маллок дергаешь, и обогнать его чем-то кастомным может быть сложно.
тюрьма психотронная, надеюсь?
А я проверил, "итеративный вариант" дал ускорение в полтора раза. Пожалуй, оставлю.
Ты точно уверен, что malloc(sizeof(mystruct) * size) медленнее? Я вот не верю в такое.
https://ideone.com/iK76G3
https://pastebin.com/qD9yFRMq
Результат:
f1: 28.039000
f2: 19.173000
Завтра проверю в gcc, может другие числа будут.
Добавлю к замечаниям предыдущего анона, что ^ - это оператор побитового исключающего или, а степень - это функция pow().
А еще есть exp.
Откуда у тебя там вторые + size взялись при вычислении указателей? Зачем? Мы считаем относительно предыдущего указателя. y - это память, следующая за size элементами в x, а res - это память, следующая за size элементами в y.
Спасибо что отозвались Аноны, вагон чая и уважения вам. Я поменял но все равно не врубается. https://ideone.com/wgsAbX
Английский язык говорить? Сообщение об ошибка читать? Где переменная a объявлять? Нигде не объявлять? Вот и не врубаться.
>>71018
Алсо, тест-кейс у тебя был очень хуевый. Сумма там заменится на i * 2, а учитывая, что у f1() сайдэффектов нет (она ничего не возвращает, и вообще почти не влияет на мир за своими пределами), нормальный компилятор вообще может выкинуть все ее содержимое на ненадобностью.
Системный вызов open() сам хочет нультерменированную строку. Напиши себе обертку, которая будет копировать имя в массив и по указанному офсету втыкать \0.
Так и придётся делать, спасибо.
Поясните за realloc, нужно free вызывать для старого указателя? т.е если new_ptr = realloc(old_ptr, new_size);
нужно потом делать free(old_ptr);?
Если realloc() сфэйлился, твой указатель остается твоим, и ты должен его освободить. Если realloc() прошел успешно, ты заботишься только о том указателе, который тебе вернули. Старый указатель уже не твой. Кстати, realloc() может вернуть тебе твой же старый указатель, если есть возможность просто добавить памяти в выделенный блок, поэтому было бы странно, если бы тебе нужно было его освобождать.
PortAudio supports audio input and output in a variety of sample formats: 8, 16, 24 and 32 bit integer formats and 32 bit floating point, irrespective of the formats supported by the native audio API.
Алсо, если я хочу написать простую говорилку текста или мелодию из марио, то что мне нужно знать? Надо взять библиотеку полегче или же книжку потяжелей?
Возьми OpenAL и не еби себе мозг.
int some_func(a, b) int *a; int b;
{
....
}
Зачем так делалось?
С double и int вроде норм работает, а вот структуры обмениваются полями. Где я накосячил?
https://pastebin.com/ZZEzmk0C
Это код из проекта, который появился после 2000 года.
Да вроде все норм. Смущает только вычисление длины хвоста массива в последних двух memcpy, не понимаю твоей логики. Покажи минимальный компилирующийся пример, который не работает.
if(ind1 + ind2 < size_result)
{
....if(ind1 < size1)
........memcpy(curr_pos, (char)(arr1) + ind1sizeof_element, (size_result - size2 - ind1)sizeof_element);
....if(ind2 < size2)
........memcpy(curr_pos, (char)(arr2) + ind2sizeof_element, (size_result - size1 - ind2)sizeof_element);
}
return EXIT_SUCCESS;
После того, как прошли цикл, может случиться лишь один из 3 вариантов:
1. ind1 + ind2 == size_result. Тогда места в результирующем массиве не осталось, надо выходить.
2. ind1 + ind2 < size_result, но один из массивов (пусть первый) кончился. Тогда ind1 = size1, в результирующем массиве осталось size_result - ind1 - ind2 = size_result - size1 - ind2 ячеек, которые нужно скопировать из второго массива, начиная с ind2-того элемента.
Я и сам проверил на паре примеров, вроде все норм. Видимо, я с указателями проебался.
> в результирующем массиве осталось
Ну я просто не понял, что именно задает юзер в size_result. Допустим, у нас массивы int a[5] = { 0, 1, 2, 3, 4 } и int b[1] = { 0 }, а size_result 10 элементов (если size_result всегда равен сумме длин массивов, то зачем он вообще?), тогда мы копируем: size_result(10) - size2(1) - ind1(1) = 8 элементов. И у нас случается ОЙ.
В данной функции (она не вещь в себе, а часть некоторой программы для комбинаторной оптимизации) первых два массива в сумме точно больше результирующего.
В первом массиве лежат инициализирующие элементы, во втором -- новые, полученные из инициализирующих. Потом мы выбираем из обоих массивов лучшие элементы и полученный массив делаем новым инициализирующим. Те элементы, что не вошли в новый массив, являются мусором.
Хотя можно было бы добавить что-то типа if(size1 + size2 < size_result) {return POSHOL_NAHOOY;}
Анон, как устроенна работа GPU, у которых есть своя собственная память? Вот я, например, всегда работал с платами с видеокартой, у которой нет встроенной памяти, и здесь всё просто - графика из юзерспейса элементарно копируется в RAM, пинается GPU, который потом по DMA забирает данные, обрабатывает их и пишет результат во фреймбуфер опять же в RAM.
В свопе.
Гитхаб не то. Туда я выложу, и он будет висеть джва года без просмотров.
всю жизнь хочешь провести в зависимости от мнения окружающих?
Благодарю, то что надо.
int
function(char *s)
{
}
Объясните, какие преимущества даёт размещение возвращаемого типа в отдельной строке?
При этом в заголовочных файлах эти же в одной строке.
Конпелятору похуй. Дело вкуса.
Если тип возвращаемого значения длинный, или конвенция вызова указывается, то искать глазами имя функции проще:
const struct myyoba_data_store * MYLIB_CALLTYPE
function(void)
{
}
>>73613
Билд-система для gcc и/или для Makefile уже есть в комплекте, нажми Ctrl+B. При даблклике на сообщение об ошибке оно переходит к нужной строке. Если хочешь ошибки инлайном, скажи "show_errors_inline": true в настройках. Если у тебя кастомный билд, сделай .sublime-build свой, там всего лишь регэксп для сообщений сочинить.
>>73661
В Си - ничего. Какая ОС? Клавиша в графическом приложении или в консоли?
>В Си - ничего. Какая ОС? Клавиша в графическом приложении или в консоли?
В консоли. ОС - Linux Gentoo.
Опиши нормально задачу. У кого ты клавиши перехватывать собрался, зачем? Ты там reptyr какой-нибудь пишешь, или что?
#define PROGRAM program
Почему вместо того, чтобы работать так:
const char msg[]=#PRORGRAM ":Unable to do smth\n"
оно (gcc) выдаёт "stray # in somewhere..."
Оно работает только так:
#define STR(a) #a
const char msg[]=STR(PROGRAM) ":Unable to do smth\n"
И тогда в сообщении будет имя программы, как положено.
Что-то в связи с последовательностью работы препроцессора, порядком раскрытия макросов чтоли, но мне непонятно, что именно ему мешает по-человечески со мной...
До. У тебя же строка
> "stray # in somewhere..."
# - это макрооператор, оно часть препроцессора, а не языка, работает только в макросах.
> #define STR(a) #a
Тоже неправильно, оно всего лишь обернет аргумент в кавычки, не попытавшись его раскрыть:
#define FOO bar
STR(FOO) // Тут получится "FOO", а не "bar".
Для раскрытия макросов нужен еще один уровень:
#define STR_(a) #a // Обернет в кавычки.
#define STR(a) STR_(a) // Выполнит макроподстановку для a.
А про #define PROGRAM "program" уже написали выше, строковые литералы отлично конкатенируются безо всяких операторов.
Эт что за магия!? оО
А то 8 бит мало, а 16 много, чтобы возводить флаги. Контролируемых ситуаций 9.
Хотя каковый в этом смысл, там же всё равно выравниваться в итоге будет по крайней мере по 8 битам, да?
Да.
Открываешь сокет, передаешь. Не забываешь, что send может передать меньше, чем ты ему сказал, поэтому внимательно обрабатываешь код возврата.
Нужно написать Windows драйвер (мне вроде KMDF подходит), который будет считывать значение TSC: Time stamp counter, счетчик тактов (на самом деле не TSC, а MSR мне нужно) регистра процессора и записывать новое значение в этот регистр.
Проблема в том, что я вообще не понимаю как в этом блядском Windows всё работает и не понимаю где взять источник информации.
C Линуксом всё просто и аналогичный драйвер (в линуксе это был модуль ядра) я уже написал, потому что по Линуксу тонна материала в интернете.
Посоветуйте инфы (книги, ссылки, статьи, можно все на англ, но лучше на русском), чтобы разорбаться в том, как писать драйвера (KMDF) для Windows.
В Windows Internals судя по оглавлению не раздела про написание драйверов. А на сайте Microsoft написано мало и не полно как-то, хотя может я и жопой читал
Есть книга про драйверопесание под венду, гугли, лентяй
man netcat
Качаешь DDK (можно, и даже возможно лучше - несвежий какой-нибудь). Читаешь документацию из комплекта (для такой простой хуйни достаточно введение прочитать). Правишь любой простой пример из комплекта. Компилируешь. Алсо, у MS сейчас все свежие примеры на гитхабе лежат.
Правильный ответ: единицу прибавлять не нужно. Если у тебя указатели равны, то их разница 0, и индекс массива тоже 0, ничего прибавлять не нужно. Если у тебя 1-based массивы, то это другой язык, и тебе в другой тред.
Шли их нахуй. Смело, решительно. Может ты задание не так понял? Может, тебе количество элементов посчитать с первого по второй указатель? Тогда будет как раз +1). Иначе шли нахуй.
Поясните за hash функции, как их пишут? Методом тыка? Или есть теория?
Давай для начала определимся, что такое канал. По-английскиПо-человечески оно как называется?
Ты хотя бы википедию почитал прежде чем такой глупый вопрос задавать. Хэш рование, криптография и всякое такое. Там де про алгоритмы узнаешь.
Хэш на пике не имеет никакого отношения к криптографии. Дизайнят руками, смотрят на распределение.
>>76174
Пайп действительно однонаправленный, но если у тебя parent/child, то тебе нужно просто писать в правильный конец. Закрывать дескрипторы нужно не потому, что иначе не работает, а для того, чтобы read() мог отследить EOF на пайпе (если у тебя открыт write-дескриптор на пайп, read() не вернет 0, даже если на той стороне write-дескриптор закроют).
И как тогда мне, спрашивается, "Самостоятельно, используя для синхронизации процессов семафоры, организовать двустороннюю
поочередную (полудуплексную) связь процесса-родителя и процесса-ребенка через канал"? В задании-то канал один. Сделаю через два пайпа, хз.
У тебя два процесса, один пайп. У каждого процесса есть два хэндла - на чтение и на запись. Родитель такой семафором помахал, записал, а потомок читает. Потом потомок помашет, запишет, а родитель прочитает. Получается полудуплекс, ну. Оба могут писать в канал, но в конкретный момент времени - только один. Рации всмомни: - У нас тут какая-то хуйня, приём. - И у нас тоже, приём. - Да ебись оно все конем, конец связи. - вот это тебе и нужно реализовать.
Так вон выше говорят, мол, нельзя, read зависнет. В общем-то о таком и думал, но все упиралось в то, что во всех примерах одна сторона пайпа в родителе/потомке таки закрывалась.
Это я писал. read() зависнет, если ты будешь в цикле читать. Не читай в цикле - смотри через ioctl(..., FIONREAD...), сколько есть и читай. Прояви фантазию, в общем - там вариантов дохуя.
Мы такой хуйни не проходили. Ладно, буду побайтово читать, ожидая встретить нуль-терминатор. Попробую, по крайней мере.
ОС, компиляторы и прочие движки БД.
Advanced Programming in UNIX environment
Programming Applications for Microsoft Windows
Читай документацию по нужной ОС, читай чужие исходники.
> куда реально можно приложить Си
Куда угодно. Если тебе нечего написать, зачем ты вообще учил язык?
Железо программировать. Хотя это немного узкая область, не каждому интересно это
Модуль для питона напиши.
Точно хочешь узнать, что не так в твоей реализации (сейчас не могу), или тебе просто задачу решить. Может, перепишешь? Алгоритм простой: ты читаешь всю строку, сколько ее ни есть, но если прочитанный символ - не таб и не пробел, ты запоминаешь его индекс в переменную. Перед выходом просто пишешь по индекс+1 символ '\0'. Четыре строки на тело getline. Если возвращенная getline строка пустая (по нулевой позиции \0), ты ее пропускаешь.
Хотя, если что, одна из твоих проблем в том, что i ты инкрементишь каждую итерацию, а в массив по i пишешь не всегда. Судя по высказыванию "оутпут просто пиздец", у тебя в незаписанных элементах массива куски предыдущих строк и прочий мусор.
Котаны, почему в файл попадает мусор вместо настоящего содержания конца текста?
>с учетом правки параметров вызова calloc
Ошибка появилась из-за смены malloc/calloc.
Спасибо, попробую дома на линупше с гцц запустить.
Ну, семафор 0 довольно прозрачный. Но вот с первым дела, конечно...
Допустим, родитель первый захватил. Значение семафора 1 равно 1: данных в канале нет, hd=0. Потом сделал семафор 1 нулевым. Освободил нулевой семафор...
Пошёл дочерний. Семафор 1 нулевой => данные есть. hd=1 => Дописали единицу к семафору 1. А это признак отсутствия данных для родителя, да? Родитель ничего не читает, а лишь уменьшает семафор на 1, делает его нулевым для нас, а мы снова ему срём и увеличиваем, а он ничего не читает и для нашего чтения уменьшает
Можно поменять в после родителя и дочку.
Я правильно понял?
Да, в семафоре 1 единица - признак отсутствия данных. Родитель смотрит на него, если в семафоре не ноль - не пытается читать, а сам пишет и ставит ноль. Если же данные были, то он пишет и семафор не трогает. Если данные были, но все свое уже выслано - увеличивает семафор давая понять, что ничего не высылал.
Я хз, что если инициализировать нулём semval в main(), а потом просто читать с sem_op=-1, а писать с sem_op=1.
Так же прозрачнее будет, ИМО.
Вообще, с этой hd как-то некрасиво.
Так у тебя после второго цикла родителя/потомка получается, что выставляется значение семафора "читать нельзя", а при этом пишутся данные.
Зачем?
Потому что нужно выделять на байт больше и дописывать \0 в конец. А вот calloc() там в хуй не уперся, все равно fread() все затрет.
А может быть так, что родитель ни разу не даёт потомку ресурс, а потом в конце if(hd) и ставит семафор 1 в единицу, а потомок потом получает ресурсы, но уже не читает?
Я понимаю, что ты несколько раз прокрутил, но всё же...
Это первое, что я нагуглил и проверил (выделил calloc'ом size+1 элемент), не сработало.
Вообще, что делают нормальные люди, если требуется распарсить несколько тысяч файлов на С, имеющих довольно разнообразную структуру (файл содержит список переменных, которые могут идти в любом порядке, и строки-комментарии, начинающиеся с символа "#")? Писать парсер с нуля довольно утомительно.
> не сработало
-Wall скажи, и тебе компилятор объяснит, кто ты.
> что делают нормальные люди, если требуется распарсить
Берут flex или его отродья. Хотя такое и вручную несложно написать.
В общем, я понел. Пока потомок форкается - предок успевает уже все прокрутить, сам с собою поговорить, удалить семафоры и завершиться. Похоже, что способ снхронизации надо переделать.
https://pastebin.com/grPm2q6A
Гораздо проще это с помощью select делать.
Вообще, у тебя основная сложность из-за того, что ты долбишься с тем, что у тебя +-1+1-1+-+-1 везде. Абсолютные бы значения, а не смещения.
semctl умеет в SETVAL и GETVAL, ты можешь
помирить родителя и потомка на том, что если один записал, то значение P, если другой записал, то значение C, в противном случае ноль.
А от 0 до SETVMX можно организовать битовые масочки на "родитель может читать",
"родитель может писать", "потомок может читать", "потомок может писать".
Но это всё очень абстрактно, сам так не делал.
Спасибо.
что за конструкция по шагам:
1)BYTE b = (BYTE)&k;
2)if(++j==16&&i<398){
> BYTE b = (BYTE)&k;
Берется указатель на переменную, которая лежит в области данных.
> if(++j==16&&i<398){
Распечатывается хексдамп начиная с переменной выше. Зачем в условии вторая часть, я хуй знаю, а первая часть нужна, чтобы втыкать конец строки и (неправильно) печатать адрес после каждых 16 байтов.
int main()
{
char filename = "C:/Users/m08kaa3/Desktop/projects/Sheduling/simulation/10/gen_10.spc";
FILE config = fopen(filename, "r");
fseek(config, 0, SEEK_END);
long size = ftell(config);
fseek(config, 0, SEEK_SET);
char * conf_text = malloc(size);
memset(conf_text, '\0', size);
fread(conf_text, sizeof(char), size, config);
printf("%s\n", conf_text);
//Если это не выведет лишних символов значит в файле в конце есть мусор. Если мусор пропал то удали эту проверку и уповай на memset(), мусор бывает когда память неинициализирована, даже если она статическая.
fseek(config, 0, SEEK_SET);
fgets(conf_text, 1024, config);
puts(conf_text)
fclose(config);
free(conf_text);
}
На-до-е-ло.
> просрал символ
> просрал разделитель
> EOF появился неожиданно
> недозаполнил и мне норм
> исправил пункты 1-4, но функция парсинга использует 100500 флагов состояния и занимает треть программы
Имею в виду литературу, где это есть, статейки занятные, в которых предлагают перейти на perl
Обсуждали выше. Размер файла 10, выделили 10 байт памяти, записали 10 байт, но это не сделало эти 10 байт строкой, которую можно вывести через printf, потому что \0 никто не дописал. Выводим это говно, получаем все что угодно - от мусора до сегфолта. На самом деле, можно printf("%.*s\n", size, conf_text);
>>78500
Уже советовали flex.
Разделяй их на пробелах.
Кажется вы там замороченой хуйни насоветовали. Можно же вывести printf("%s\0", buf);
Строка -- это массив char@, заканчивающийся нулем.
printf("%s\0", buf) говорит: выведи мне строчку buf, потом добавь "\0".
Принтф начинает писать buf. Пишет, пишет, пишет, далее варианты:
1. Залезает в запрещенную область.
2. Упирается в случайно найденном в мусоре 0.
В первом случае шлет нахуй, во втором кроме сроки выводит всякое говно.
фиксить не буду, нутыпонел.
Отслеживается 9 true/false состояний для, соответственно, 9 значений ячейки. Приходится юзать uint16_t.
#define BIT_MASK(val) (1<<(val-1))
...
// Добавить val к маске
ban_vals|=BIT_MASK(curval);
if(!(ban_vals&BIT_MASK(curval))
write(0, "NIPANIMAT", strlen(<-von_to_govno);
Как после OR'а у меня НЕ-И выдаёт тру?
Было ...000000000
Я заполнил 2,3,5:
...000010110
Потом чекаю отсутствие, допустим, 2-го, т.е.
if(!(...000010110 & ...000000010)) - должен дать false, почему даёт true?
> uint16_t
Действительно
Я та мтроеточие ставил, что 7 оставшихся не писать.
Забейте, чуда не случилось, я обосрался в другом месте.
Да ты по всем фронтам обосрался. Тебе нужно работать с отдельными байтами по 8 бит, использовать можно тип short. Так то по теме проверки бит на чёткость уже кучи материала, но блядь, это же не строка чтоб сразу сравнивать все 9 из 128 бит.
Все должно работать. Разве что твоя нумерация битов с единицы сбивает с толку, но она у тебя консистентная, поэтому не приводит к проблемам.
Пардон, попутал.
Мне кажется что int16_t это нечто другое. Впрочем не вижу смысла использовать именно его. Почему бы не копнуть в сторону bit field?
> Впрочем не вижу смысла использовать именно его.
Например, есть ограничения по памяти. А так бы я тоже предложил unsigned int или хотя бы что-то типа uint_fast16_t.
> Почему бы не копнуть в сторону bit field
Внутри одной программы вполне норм, хотя и сводится к асболютно тому же коду, что и проверка побитовыми операциями. Плюс установка двух-трех флагов за раз вручную может оказаться дешевле битфилдов. Но битфилды непереносимы, т.е., если у >>79357 сетевые пакеты, то ему все равно придется доставать флаги из битфилдов и паковать в инты для передачи по сети.
Ненужно. Битфилды сформированные из инта будут интом и там и там, разница проявится если разная архитектура и внезапно инт не 32 бита а меньше или больше.
> Битфилды сформированные из инта будут интом
Вот только порядок и выравнивание будут отличаться от компилятора к компилятору.
Ну что ж ты тупишь? Ты написал свой Телеграм, Вася скомпилировал его вижуал студией под x86, а Петя - gcc под Байкал. У Васи первый флаг располагается в младших битах, а у Пети в старших, и вы не можете даже поговорить об этом, потому что из-за этих различий вы по сути пользуетесь разным протоколом.
Так это же нормально иметь под байкал отдельную версию ПО или не? Насколько я знаю архитектура почти гарантия совместимости и правильного межпроцессорного взаимподействия.
> отдельную версию ПО
Ну да, давай велосипеды по двадцать раз переписывать, вместо того чтобы просто сделать flags & SOME_BIT.
Нет, давай лезть на более низкий уровень имея те же операции в более высокоуровневом представлении.
> давай лезть на более низкий уровень
Давай. Мы пишем на языке, который именно для этого сделан.
Ебать ты пряник. Он сделан чтоб ассемблер упростить, а не наоборот.
Моца цопе!
> переносимость
Лол. Вырастешь большой - поймешь, что Си - один из самых плохо переносимых языков. В то время как код на каком-нибудь Python заработает на новой машинке без модификаций, в Си тебе придется обмазать его толстым слоем ифдефов, и он все равно где-нибудь упадет.
> Весь C пропитан унификацией
C пропитан неопределенным поведением, ты перепутал. Тту даже принюхиваться не нужно.
Именно. Запускаешь такой свой хелловорлд на DSP с CHAR_BIT=16, и видишь, как твои бананы медленно превращаются в желе.
>каком-нибудь Python заработает на новой машинке без модификаций
Сляжет от версии Питуна, истину глаголю.
А ты я смотрю умный. Скажи, вот я хотел вебкамеру подключить например к своему хловоролду, но не вкурю, что куда прописывать?
Это целый будапешт. Я видел как чувак трёхмерные движки пилит за пол часа, а сам как бы и простейшего не умею, гугл представляет собой лютый пиздец из мешанины hwnd, которые мало того что хуй знает как использовать, так ещё и не найти описания более подробного чем - "это int32, содержит номер окна", это же пиздец. Нет ли бибилиотеки реализующей всю это пвсеводнизкоуровневую хуету искаропки, чтоб вызвал функцию takeFrame(WRBCAM_0, buf, 32, 32); и получаешь заветный кадр в виде массива байт, или это утопия?
Это не на ютубе дебич, а настоящий человек.
> Нет ли бибилиотеки реализующей всю это пвсеводнизкоуровневую хуету искаропки
Вообще, сейчас модно брать OpenCV и не думать. А так, в винде с камерами вообще плохо, нужен COM, и дальше есть всякие-разные варианты ебли со всякими DirectShow или WIA. Но есть старый, "неподдерживаемый", но тем не менее рабочий и простой метод: https://msdn.microsoft.com/en-us/library/dd757677(v=vs.85).aspx Там буквально несколько строк:
создаешь окно capCreateCaptureWindow, шлешь ему WM_CAP_DRIVER_CONNECT, WM_CAP_FILE_SAVEDIB, WM_CAP_DRIVER_DISCONNECT и потом ебешь полученную .bmp как тебе угодно. Можно обойтись без .bmp, там можно установить колбеки на фрейм и т. д.
> "это int32, содержит номер окна"
Но это действительно номер окна, и это не обязательно int32, это struct HWND *, и тебя не должно ебать, что там внутри. Это вполне нормальный сишный интерфейс, когда либа работает с указателем на incomplete-структуру, и сама она может обращаться к ее полям, а юзер видит только непрозрачный указатель (хэндл).
ленивая жопа, бери йобареколер, который тебе фреймы будет кидать в папку и считывай от туда своим хелоувердом не забывая удалять
>>79619
Ты не понял моего бугурта. Вот есть структура - про неё много чего написали, но упомянуть что она мне нахуй не нужна, забыли.
А я блядь ебусь и 3 дня читаю гугл как эту структуру заполнять, где брать, куда объявить и т.д., чтобы узнать от онона, что эта хуйня может просто висеть где то там и напрягаться по её поводу моветон.
Вот надо тебе окно - получай ебалу с гибкими настройками вместо #include vsyaHuinya.h createwindow("заголовок",x,y,w,h);
И у винды это ещё по божески, GTK это вообще пиздец.
Чувство такое что проектировалось это умными, но наглухо отбитыми придурками и не для людей.
кокая структура? может это она тебе не нужна. но винапи говно, это да. вне контекста задачи, твой бугурт нищитовый.
> А я блядь ебусь и 3 дня читаю гугл
Зачем читать гугл, когда можно читать документацию? Цитата из MSDN:
> Window Handle
> After creating a window, the creation function returns a window handle that uniquely identifies the window.
> A window handle has the HWND data type; an application must use this type when declaring a variable that
> holds a window handle. An application uses this handle in other functions to direct their actions to the window.
Просто RTFM и все.
Не вижу ни слова про то что можно неиспользовать эту ебалу. Читал я msdn, затем метался в гугл из за таких же строк, что мол так и так используй это и это, а где взять - а хуй его знает, начинай с первой страницы msdn, вдруг встретишь.
Есть у меня одно тёплое воспоминание о GTK, это cairo. Вот уж API проще не встречал, всем бы на него равняться.
есть джва тома книжек про погромирование под вындовс 95 на винапи, читай, они актуальны, там все разжовано. настоящие погромисты на столько круты, что ответов на их вопросы в интернете нет.
https://pastebin.com/kp4EaUgc вот тебе минимальный пример. Он говно по многим причинам, но из этого уже можно что-то слепить и/или перейти на нормальный метод когда-нибудь позднее. Компиляция: gcc file.c -luser32 -lavicap32, в студии аналогично (user32.lib, avicap32.lib).
https://msdn.microsoft.com/en-us/library/dd757677(v=vs.85).aspx
Открываем первую страницу
https://msdn.microsoft.com/en-us/library/dd797847(v=vs.85).aspx
И сука таки ни единого слова про подключаемые заголовочные файлы, ни слова в примере вызова функции про то что из себя представляют fOK, hWndC, WM_CAP_DRIVER_CONNECT, где лежат и чего значат.
Теперь второй пример.
cairographics.org/manual/
Открываем документацию
https://www.cairographics.org/documentation/
Первая же страница начинается с лаконичного примера, в котором всё понятно без hWndCdolboёbоv
https://www.cairographics.org/FAQ/#getting_started
>И сука таки ни единого слова про подключаемые заголовочные файлы
https://msdn.microsoft.com/en-us/library/dd756879(v=vs.85).aspx
наркоман, уходи.
Вот пример минимальный, в котором хотяб понятно где int.
; Example of making 32-bit PE program as raw code and data
format PE GUI
entry start
section '.text' code readable executable
start:
push0
push_caption
push_message
push0
call[MessageBoxA]
push0
call[ExitProcess]
section '.data' data readable writeable
_caption db 'Win32 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dd RVA _ExitProcess
dd 0
user_table:
MessageBoxA dd RVA _MessageBoxA
dd 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
section '.reloc' fixups data readable discardable; needed for Win32s
Вот пример минимальный, в котором хотяб понятно где int.
; Example of making 32-bit PE program as raw code and data
format PE GUI
entry start
section '.text' code readable executable
start:
push0
push_caption
push_message
push0
call[MessageBoxA]
push0
call[ExitProcess]
section '.data' data readable writeable
_caption db 'Win32 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dd RVA _ExitProcess
dd 0
user_table:
MessageBoxA dd RVA _MessageBoxA
dd 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
section '.reloc' fixups data readable discardable; needed for Win32s
> И сука таки ни единого слова про подключаемые заголовочные файлы
В MSDN обычно есть about/using/reference. В about тебе рассказывают, что это такое, как оно работает, нахуй оно нужно, и что вообще существует, в using гайд с примерами, а в reference как раз все описания. Обычно оно все очень сильно перелинковано, но как я уже говорил, технология старая, еще из 95 винды, поэтому ссылок мало. Вот тебе референс про connect:
https://msdn.microsoft.com/en-us/library/dd743891(v=vs.85).aspx
>https://msdn.microsoft.com/en-us/library/dd743891(v=vs.85).aspx
Спасибо кончено. Но я наверное просто не создан для всей этой залупы. Мой уровень это purebasic, не более, всё что сложнее просто перегружает мозг.
Чому ни? Загугли nirsoft, я когда вижу эти охуенные утилиты весом пару десятков килобайт, но с UI и мощным функционалом, аж трясет от восхищения за того программиста, кто это все дело пилит.
Эх, щас бы в 2K19 дотнетоговно напрямую с ядром работало.
char*: создает указатель, который указывает на литерал, лежащий в секции данных. Ты можешь изменять сам указатель, но не можешь писать по указателю - строковые литералы ридонли.
char[] создает массив достаточного размера, чтобы скопировать в него литерал (и копирует его туда). Так как это массив, то ты, конечно же, можешь изменять содержащуюся там строку.
Си можно выучить на приемлемом уровне менее чем за 10 лет. При этом ты будешь знать, что происходит в коде, а не предполагать.
ОС, либы, embedded, прикладной софт тоже иногда.
Ты когда-нибудь программировал микроконтроллеры, где килобайты рам можно по пальцам пересчитать?
Конечно. Ты понимаешь, что g++ и gcc выдадут тебе идентичный код, если ты не будешь использовать в крестах многие крестовые фичи? При этом ты можешь, продолжать пользоваться теми фичами, которые на код напрямую не влияют, а жизнь проще делают.
Ну хз, у нас все на си ваяют. Возможно потому, что проще потом лицензировать (авионика), а не из-за возможностей языка.
Так я об этом как раз и сказал выше - стандарт в разы меньше, вариантов хитровыебанного поведения меньше, осилить проще и проверить проще.
Стоит дополнить, что в первом случае можно изменять сам указатель, а во втором имя массива является константой.
>имя массива является константой
Что ты хотел сказать этим набором слов?
Имя целочисленной переменной тоже является константой. Или ты можешь показать код, который переименовывает целочисленную переменную?
Он мне не нравится.
Cпасибо!
Он имел в виду, что можно ptr++, но нельзя array++, т.е., массив можно рассматривать как константный указатель на его первый элемент.
>>81369
> Где это написано?
Именно там и написано. Второе предложение логически вытекает из первого, и хотя в большинстве компиляторов в целях совместимости с говнокодом есть возможность "отключить" этот абзац, проще считать строковые литералы константами:
> It is unspecified whether these arrays are distinct provided their elements have the
> appropriate values. If the program attempts to modify such an array, the behavior is
> undefined.
>>81428
MSDN, можно старенький и оффлайновый мануал из Platform SDK для XP/2003 - им удобнее пользоваться, но там нет некоторых новых фич.
>>81443
Сохраняй исходник в UTF-8, собирай с -fexec-charset=866, потом когда-нибудь научишься делать правильно (возможно, в CRT и консоли винды к этому времени как раз появится полноценный UTF-8). Можешь собирать без -fexec-charset, но запускать в помершелле, он умеет в UTF-8 после chcp 65001. Можешь поставить себе ConEmu, он тоже в UTF-8 может.
int main(void) {
char b[] = "БB";
printf("%x\n", b[0]);
return 0;
}[/CODE]
Почему распечатывает ffffffd0? Почему бы не 000000d0?
chcp 1251 - кодировка Windows
chcp 65001 - кодировка UTF-8
Иногда требуется выбрать для консоли другой шрифт.
Потому что char у тебя signed, а char в выражениях, а так же в аргументах variadic-функций подвергается integer promotions: (signed char) 'Б' превращается в (signed int) 'Б', старший бит стоит, значит оно отрицательное, происходит sign-extension, т.е., знаковый бит дублируется влево на всю ширину переменной. Хочешь получить d0 - делай (unsigned char) b[0] (promotion никуда не денется, но будет zero-extension, т.к., unsigned char) или или b[0] & 0xff (promotion опять же никуда не денется, но будет сделано еще для оператора &, получится (0xffffffd0 & 0xff), в результатае посчитается красивый (int) (0xd0), который уже промоутить не нужно, он и так int).
>>81609
> chcp 65001 - кодировка UTF-8
И тут все виндусы кроме свежих билдов десяточки скажут "ой" при попытке вывести кириллицу.
Потому что char - это знаковый тип, где русские буквы это отрицательные числа.
Используй unsigned char b[] = "БB";
Или так: printf("%x\n", b[0] & 0x00FF);
>И тут все виндусы кроме свежих билдов десяточки скажут "ой" при попытке вывести кириллицу.
Проверил на Windows 7 с шрифтом Lucida Console:
#include <stdio.h>
char utf8text[] = {0xD0, 0x90, 0xD0, 0x91, 0xD0, 0x92};
int main(void) {
printf("%s\n", utf8text);
return 0;
}
С chcp 65001 выводит "АБВ".
Кури про wchar и wprintf, нехуй ебаться с кодировками (методы советуемые на форумах работают от раза к разу) правда setlocale все равно надо использовать зато без ебли с настройкой консоли. Либо, если лень писать L перед каждой строкой, то в венде можно пользоваться нестандартной библиотекой tchar.h ну это уже сам кури.
>L перед каждой строкой
Не советую, в одной проге из-за этого долго пришлось править несовместимость (GCC в Linux использовал 4-байтовые символы Unicode, Visual C++ в винде - 2-байтовые). Нужно применять UTF-8 везде.
А у меня выводит:
> АБВ
> В
А вместо "Привет, мир!" выводится, например, пикрелейтед. И это тоже 7 со шрифтом Lucida Console. А стабильно оно только с десяточки работает.
-fexec-charset работает совершенно таким же образом, только не вынуждает хранить исходники в древней кодировке, создавая проблемы с IDE и системами контроля версий.
Первый раз такое вижу. Обычно либо выводит русские буквы, либо квадратики.
И с chcp 1251 такое же?
У тебя какая-то сборка от васяна.
C chcp 1251 ок или крякозябры, в зависимости от кодировки выводимых байтиков. Винда - чистая тестовая виртуалка. Более того, с chcp 65001 и WriteFile, к которому сводится твой printf, и WriteConsoleA иногда (а на XP - всегда) фэйлятся и не выводят вообще ничего, поэтому приходится идти длинным (зато надежным) путем. Делается кастомный yoba_printf, который с помощью MultiByteToWideChar преобразует UTF-8 в UTF-16, который уже выводит с помощью WriteConsoleW, и вот с UTF-16 проблем никаких нет, вне зависимости от кодировки, выставленной chcp.
>Винда - чистая тестовая виртуалка.
А, тогда ясно. Нужно ставить Microsoft Visual C++ redistributable package.
На древней msvcrt.dll могут быть любые аномалии. Она родом с XP, где UTF-8 нормально не поддерживался.
В десятке видимо обновили.
А CRT-то каким местом? Тут же нет разбора строки - %s просто копирует символы в stdout пока не встретит \0, а stdout сводится к _write, а _write к WriteFile. Вот если бы я toupper делал или strtok какой-нибудь, или хотя бы %.2s, тогда да, CRT могла бы что-нибудь испортить.
Но ты меня заинтересовал, попробую отладить когда-нибудь и посмотреть, почему такое поведение. Ты чем собирал? Студией?
И да, msvcrt - дефолтный рантайм Visual C++ 98, оно же VS6.0. Ее, конечно, обновляли, но родом она еще из маздая.
> Он имел в виду, что можно ptr++, но нельзя array++, т.е., массив можно рассматривать как константный указатель на его первый элемент.
:facepalm:
>> Где это написано?
>Именно там и написано.
Да, чёт проглядел.
Почти.
Рыбья головёха?
Есть кто с мгу? Слейте лабы по с/с++ с меня как обычно
Рыбья голова)
Поржал всем офисом)
Некоторые люди не могут в побитовые операции, битовые поля проще, удобнее и иногда даже быстрее.
Пишу программу занимающуюся посимвольной обработкой строк. ОС Linux, компилятор GCC, кодировка UTF-8.
Если в строке есть многобайтовые символы, то перед обработкой перевожу строку в wchar_t. Столкнулся с проблемой при обратном переводе в char: не могу найти функцию из стандартных библиотек, которая принимает строку типа wchar_t и возвращает количество байт, которое нужно выделить для записи этой же строки в char. Статическая длина строки отпадает сразу, так как длина входной строки может быть совершенно любого размера.
Есть такая функция в стандартной библиотеке и как называется? А то может я и ищу то, чего нет.
вроде нет, поскольку я велосипедил подобное сам, но там легко и реализаций миллиард
https://github.com/JeffBezanson/cutef8/blob/master/utf8.c
Знаю, что легко, но хотел найти какой-то общий стандарт, чтобы не пилить велосипеды. Если нет, то напишу сам.
А чем переводишь? wctomb говорит, сколько символов нужно - просто просуммируй результаты. Но велосипед будет быстрее.
Алсо, я бы на твоем месте не выделывался. Длиннее 4 байтов один code-point не занимает. Если у тебя суррогатные пары уже лежат в одном 32-битном wchar_t, тогда два раза по 4 байта на символ максимум. Выделяй сразу столько, точно влезет, и не нужно будет заниматься бесполезными подсчетами.
math.h имеется
#include<math.h>
main(){
float b=4;
float a=sqrt(b);
printf("%.1f",a);
}
Обосрался
заебал скажи че сделать чтоб робило
бля отдуши чувак. объясни плиз нахуя это нужно было прост в винде такого я не добавлял
В винде вся математика в CRT, в той же либе, что и printf и т. д., и она прилинковывается автоматически, по умолчанию. В линуксах отдельно, у них принято делать жизнь максимально неудобной.
> В винде вся математика в CRT, в той же либе, что и printf и т. д.
И хуй чего выкинешь, все гвоздями намертво прибито.
> В линуксах отдельно, у них принято делать жизнь максимально неудобной.
Линкуешь только то что нужно. Принцип разделяй и властвуй на шицо, но спермачи кукарекают что-то про неудобство.
В сперме хелловорлд 50 метров? Лол. Ибо у меня в дебиане меньше 4Кб. Целый кластер потратил для теста, ёк макарёк.
Валю, я даже Qt статически линкую
Хелловорлд в винде 8к, если динамическая линковка. Или меньше 200к, если статическая.
>>83156
> Принцип разделяй и властвуй
Зачем разделять, если это стандартная библиотека Си? Давай вообще от либ откажемся, будем линковать printf.o и malloc.o каждый отдельно.
> Линукешь только то что нужно.
На самом деле для выбора "что нужно" придуманы линкеры.
> от либ откажемся, будем линковать printf.o и malloc.o каждый отдельно.
Уууууу чо удумал, это ты насаждай в мастдае дистрибьюцию в предкомпилированных файлах. Нам исходники голые подавай, а мы уж как нибудь сами скажем компилятору с чем собрать программу. Усёк, гаврюшенька?
>объясни плиз нахуя это нужно было прост в винде такого я не добавлял
"так сложилось исторически"
Нашёл чем гордиться. Шо то хуйня, шо это хуйня. Надо иметь статические бибилиотеки на каждую функцию и линковать автоматически, ато развели ебалу.
"кококо хочу подключаю хочу неподключаю" - Ты же и так знаешь что подключить придётся, по тому что ты функцию используешь в коде, а не по тому что у тебя гибкая система настроек и свобода действий.
В ньюфаг-тред шагом марш!
gcc c.c -lm
пейсать
gcc -O2 c.c
Тогда sqrt вместо вызова функции будет реализован инструкциями копро-цессора, на месте.
-O1, -Os и -O3 тоже подойдут.
Но это не гарантировано. Так что лучше -lm
Да я лучше в дворники пойду, чем в интерпрайзы на джавах.
Убунтодебил, уходи.
Я стал php-developer.
Борщеязычки говно без задач, а на сишке весь мир держится.
Двачую этого дZенствующего.
Окей, ставишь билдтулзы с говном на виртуалку, забираешь оттуда PSDK и компиляторы. Профит.
Почему данный код работает корректно, выдавая пользователю на экран нужные сообщения?
int num;
scanf("%d", &num);
char* errors[] = {"first", "second", "third"};
printf ("%s", errors[num]);
В приведенном выше куске кода, если я инициализирую num как 0, 1 и 2, то получаю сообщения "first", "second" и "third", соответственно. Почему? Как я понимаю, чтобы сообщения выдавались, необходимо в printf'е делать разыменование errors[num], то есть добавить звездочку.
Сейчас попробую объяснить, как я понимаю массив указателей:
В данном случае мы имеем массив указателей errors. В массиве errors хранятся 3 указателя на тип char, которые указывают на массивы из слов. Ниже представлен простенький рисунок. 14, 15 и 16 в ячейках errrors - это, грубо говоря, сами указатели. Соответственно, в приведенном коде выше, когда мы, допустим, printf'аем errors[0], должно выводится 14 (правда, формат в printf'е стоит "%s", но не так важно), однако, как уже сказал, на экран выводится first. Почему? Мб, я как-то неправильно понимаю?
Давай разберемся, что такое errors.
Errors - это массив указателей на char.
Принтф получает на вход УКАЗАТЕЛЬ НА char, и обрабатывает егоименно так (у тебя там %s же, это важно!). Поставь там %i какой-нибудь и получится число.
Ну есть в сишке указатели-хуятели и дальше чё? Как ебля с указателями и освобождением памяти прокачает мой скилл в программировании в общем?
Ну вот я джавист, прочитал недавно K&R и Прату чисто в академических целях. Никак я свой навык не улучшил. Углубился в старину, посмотрел как писали раньше проги и всё.
Ты просто студент без реального опыта работы, который потратил какое-то время на сишку, в отличие от своих друзей, которые дрочили питон какой-нибудь, и возомнил себя ебать гуру.
Решают структуры данных, алгоритмы, архитектура. Твоя сишка нахуй не нужна для навыков. Сишка в современном мире - крайне узкоспециализированный язык. Изучать её нужно либо для конкретной работы, либо полистать пару книжек для экскурса в историю. Всё, больше Си тебе ничего не даёт. Это просто изкоспециализированный инструмент.
Как же байтослесари триггерятся на джаву)))) Я всё понимаю, потратить на обучение в 3 раза больше времени, и получать в 2-3 раза меньше - конечно это обидно. Остаётся только писать на двачах, что Си - это ебать орудие Богов.
> чему? Как я понимаю, чтобы сообщения выдавались, необходимо в printf'е делать разыменование errors[num].
Упускаешь, что [ ] сам делает разыменовывание. Смотри: ∗errors - это адрес (указатель на) массива first, правильно? И далее ∗(∗errors) или ∗∗errors - это разыменованный массив first, т.е., символ 'f', но это к делу не относится. А errors[num] это сахарок, полный аналог которого ∗(errors + num), где арифметика - адресная, т.е., errors + 1 = адрес errors + размер одного указателя, а errors + n = адрес errors + размер указателя ∗ n. И потом ∗(...) этот адрес разыменовывает, и ты получаешь адрес строки.
> cоответственно, в приведенном коде выше, когда мы, допустим, printf'аем errors[0], должно выводится 14
> правда, формат в printf'е стоит "%s", но не так важно
Сделай %p и получишь свои 14, потому что %p просто берет аргумент arg и формирует текстовое представление указателя: можешь считать, что оно аналогично printf("%x", (unsigned long) arg).
А %s берет свой аргумент arg, считает его указателем, и разыменовывает его: делает ∗(arg), ∗(arg + 1), ∗(arg + m), пока не найдет символ \0. Ну и выводит полученные символы, конечно. Поэтому ты видишь текст, а не число.
>А %s берет свой аргумент arg, считает его указателем, и разыменовывает его...
Вот, теперь точно понял, что именно меня вводило в заблуждение. Я раньше не знал (или не задумывался), что %s разыменовывает указатель. Теперь все точно ясно. Вопрос закрыт. Чуть головой не поехал
https://pastebin.com/tMRF7673
ребят посмотрите код плиз , у меня вопрос , можно ли передать в функцию указатели , так что бы по такому выражению она выделила память ,просто если вставить этот кусок (array = (double@@)malloc(sizeof(double@)@ROW);)в функцию, он отработает , но выдаст ошибку сигментации
Не совсем понятно, чего ты хочешь. У тебя в текущем виде программа должна более-менее работать. Хочешь переместить выделение памяти в input_date? Тебе придется тогда как-то вернуть массив. Например, передавать double ∗∗∗array_ptr и после маллока делать ∗array_ptr = array. Или просто возвращать из функции double∗∗, делая return array, а аргумент убрать просто.
аааа, понял спасибо , а программа и так хорошо работает
У меня есть sizeof(smth).
Как надёжно попасть на i-ый элемент массива?
Я же не могу просто сделать так:
smth_tmp=∗((char ∗) ptr+sizeof(smth))
верно?
> Я же не могу просто сделать
Можешь, только левая звездочка там лишняя. Ты либо:
smth foo = ∗(smth ∗) ((char ∗) ptr + ...);
либо
smth ∗bar = (smth ∗) ((char ∗) ptr + ...);
Но лучше скастить к указателю на smth и прибавить i:
smth foo = ((smth ∗) ptr);
smth ∗bar = (smth ∗) ptr + i;
Я структуре присваивал, а не указателю, я просто типа не написал. Оттого и левая звздочка, спасибо.
Алсо, в моём случае функция не будет знать типа, т.е. ей передадут только size_t от sizeof(given_type). Так что способ один для меня применим, в отличие от второго.
void foo(...,float c[3]){...} ==>
foo(...,{1.0f,1.0f,1.0f}); - вроде раньше так делал, а сейчас забыл.
О точно! Благослови тебя Сибог
Любой. Они все говно. Я предпочитаю борланд, можно ватком, но ватком - это целый свой мирок со своими закидонами.
Я вообще не знал, что оно умеет в 16-битный код. Будет не совсем то - с 32-битными регистрами, вон даже какой-то MMX проскочил с -O3. Но запуститься - запустится, наверное. А что за задача у тебя? Тебе точно нужен современный компилятор для ее решения?
Пиши на асме: читай вторичный загрузчик, переключайся в 32-битный защищенный или нереальный режим и не страдай хуйней. Алсо, прошу прощения за скриншот, там дизасм 32-битный, а код 16-битный.
На Си ты охуевать будешь гораздо больше. А без знаний о стеке и сегментах как вообще загрузчик писать? Тебе ж этот самый стек настраивать, не говоря уже о дескрипторах сегментов защищенного режима.
В ассемблере у тебя больше контроля. А тут ты будешь ебаться с теми же сегментами, отличать far pointer от near pointer, и заодно ебаться с вызовами BIOS через жопу.
> Не понимаю даже чем сегменты
far pointer - это пара 16-битный сегмент, 16-битный офсет (записывается как сегмент:офсет), в реальном режиме все настроено так, что плоский указатель считается как (сегмент ∗ 16) + офсет. В защищенном чуть по-другому, но для защищенного ты выставишь базу всех сегментов в 0, и будешь вообще игнорировать наличие сегментов.
> стек
uintptr_t stack[4096];
uintptr_t ∗stackptr = stack + 4096; // stackptr - это пара ss:(e)sp.
// Это делает проц.
void push(uintptr_t value) { ∗--stackptr = value; }
uintptr_t pop(void) { return *stackptr++; }
Больше там ничего нет, в этом твоем стеке.
float
integ(float a, float b, float eps, float (f)()) {
float sum = 0.0;
while (a < b) {
sum += f(a) eps;
a += eps;
}
return sum;
}
И передаю.
float
square(float a) {
return aa;
}
res = integ(4.0, 7.0, 0.1, square);
Этот код, конечно же, не работает, в res записалось чёрт-те что.
Чтобы он правильно работал, надо указать float (f)(float).
А если я хочу передавать функцию с неизвестным заранее числом аргументов?
float
integ(float a, float b, float eps, float (∗f)()) {
float sum = 0.0;
while (a < b) {
sum += f(a) ∗ eps;
a += eps;
}
return sum;
}
И передаю.
float
square(float a) {
return a∗a;
}
res = integ(4.0, 7.0, 0.1, square);
Этот код, конечно же, не работает, в res записалось чёрт-те что.
Чтобы он правильно работал, надо указать float (∗f)(float).
А если я хочу передавать функцию с неизвестным заранее числом аргументов?
float
integ(float a, float b, float eps, float (∗f)()) {
float sum = 0.0;
while (a < b) {
sum += f(a) ∗ eps;
a += eps;
}
return sum;
}
И передаю.
float
square(float a) {
return a∗a;
}
res = integ(4.0, 7.0, 0.1, square);
Этот код, конечно же, не работает, в res записалось чёрт-те что.
Чтобы он правильно работал, надо указать float (∗f)(float).
А если я хочу передавать функцию с неизвестным заранее числом аргументов?
> Этот код, конечно же, не работает, в res записалось чёрт-те что.
Сравни с float square(double a), прочитай про default argument promotions. Алсо, своими пустыми скобками ты отключил контроль типов при вызове функции, готовься к сложно отлавливаемым багам.
> А если я хочу передавать функцию с неизвестным заранее числом аргументов?
Это крайне хуевая идея. Хотя бы потому что integ это количество аргументов знает (иначе не сможет вызвать f), f количество аргументов знает, а значит тебе никто не мешает правильно задекларировать свою f и не выделываться.
Если ты хочешь странного (а вы тут все хотите странного), посмотри в сторону функций с переменным количество аргументов, как printf, например. Сделай механизм детекта количества и типа аргументов в рантайме: stdarg.h, va_list, va_arg - вот это все.
>>86696
> Какие подводные?
Если собираешься переписать только graphics - поебешься с циклом обработки событий, наверняка придется городить еще дополнительные doevents() в самых неожиданных местах. В целом, это достаточно быстро все портируется. Если собрался переписывать саму прогу, то подводных никаких, но это дольше.
Работа есть? Смогу прогать мк на военном предприятии? А может быть даже смогу работать дома?
Работа есть, крупные города или не эта страна. Про удаленку и не мечтай. К околовоенным не суйся, у них на строчку кода десять страниц пояснений и согласований.
Работы вообщем-то дохуя и больше. Все серъёзные фреймворки так или иначе имеют высокопроизводительные части, работающие на C. В эпоху опенсорса все лежит на гитхабе. Увлекайся, разбирайся, форкь, улучшай и тебя рано или поздно позовут работать в буржундию или на удалёночку.
Друзья, вощем не могу придумать алгоритм решения задачи:
есть дерево с файлами и .txt, на вход функции дается корень, каждый .txt содержит символическую(ие) ссылку(и) на другие файлы того же дерева, или тупик, или приз.
Нужно найти путь к призу.
Сразу понятно, что нужно рекурсивно пройти дерево файлов, а вот как обрабатывать *.txt?
мб кто-нибудь встречался с подобной задачей?
Так оно инициализацию генерит, вот тебе не похуй, какой там код.
указатель на функция гугли. Берешь инициализируешь как переменную указатель int (*fun)(int , int);
при этом у тебе описана функция с такими же аргументами
int function(int a, int b){
return a+b;
}
теперь просто передаешь указателю функцию :
fun=function;
теперь можешь как аргумент пихать указатель.
> А если я хочу передавать функцию с неизвестным заранее числом аргументов?
если несколько аргументов то <stdarg.h> поможет
А мусорные переменные-то зачем создавать? Он вон напрямую передает, как человек, а ты какую-то бесполезную ебанину советуешь.
не заметил я просто, саня хуй саси
Описание аргументов требуется не потому, что нехороший Си запрещает указатели на функции с неизвестными аргументами. Просто при вызове функции эти аргументы нужно как-то передавать, а для этого нужно знать их типы, а каким-то другим путем (через астрал?) узнать в рантайме, что вот эта конкретная вызываемая тобой функция хотела первым параметром char вместо int - невозможно. Поэтому Си в таком случае делает лучшее, что он может: определены default argument promotions (например, вместо char будет положен int, а вместо float - double), передаваемые аргументы неявно кастятся к своему дефолтному типу. То же самое делается для необязательных аргументов variadic-функций типа printf - там информация о типах тоже недоступна. Если вызываемая тобой функция именно этого всего и хотела, то все заработает. Если хотела float, а прилетел double - ну ты видел, чем это заканчивается.
> А если указывать указатель на указатель на функцию?
А какая разница? Проблема не в адресе, а именно в том, как компилятор будет эту функцию вызывать. А так ты мог бы хоть указатель на void передавать, тебе никто не мешает. На самом деле так нельзя: по историческим и архитектурным причинам возможны ситуации, когда указатель на данные и указатель на функцию могут быть численно равны, но указывать на разные вещи. Поэтому кастить между указателями на функцию и указателями на void - это UB, хотя на практике на всех современных распространенных платформах все ок.
Очень подробный ответ, спасибо.
В общем, такими изворотами лучше заниматься в более приспособленных для этого языках.
> Просто при вызове функции эти аргументы нужно как-то передавать, а для этого нужно знать их типы, а каким-то другим путем (через астрал?) узнать в рантайме, что вот эта конкретная вызываемая тобой функция хотела первым параметром char вместо int - невозможно
А как в некоторых других языках дело обстоит, не знаешь? Как-то же они умеют и могут в это. Но засчёт чего?
>по историческим и архитектурным причинам возможны ситуации,
А можешь рассказать поподробней?
> А можешь рассказать поподробней?
Ну ты даже на x86 можешь написать ОС, которая выставить ненулевую базу сегменту CS или DS так, чтобы физический адрес CS:some_virtual_addr не был (или наоборот был) равен DS:some_virtual_addr. Или вон там кто-то выше про 16-битную сишечку спрашивал - в small-модели памяти near-адреса кода и данных могут совпадать, но фактически код и данные лежат в разных сегментах. Алсо, в некоторых особо упоротых DSP указатели на код хранятся, читаются и присваиваются как physical_addr >> 2.
> В общем, такими изворотами лучше заниматься в более приспособленных для этого языках.
Я так и не понял, чего ты хочешь добиться. Ты же функцию вызываешь? Значит, ты знаешь, сколько и каких параметров будет. Почему нельзя их в указателе на функцию указать?
>Как-то же они умеют и могут в это.
Там не явно предается информация о количестве параметров. В Си есть VA_ARG, е еще лучше съеби и не еби господам мозг.
>На самом деле так нельзя: по историческим и архитектурным причинам возможны ситуации, когда указатель на данные и указатель на функцию могут быть численно равны, но указывать на разные вещи. Поэтому кастить между указателями на функцию и указателями на void - это UB, хотя на практике на всех современных распространенных платформах все ок.
Ну то есть вся абстрактопараша, все питушыные платформы с JIT-компиляцией и GC существуют чисто случайно, потому что авторы компиляторов сишки и плюсов добрые? Охуеть же.
>который учил не Си, и не кресты, а некий "си с классами".
Сцук, это про меня. Просто практиковаться было интересно на winAPI, литературе часто были примеры с кодом вроде LPTCCONTROLDATA context = LPTCCONTROLDATA)malloc((size_t)sizeof(TCCONTROLDATA)); - что-то вроде, а может и нет, стал уже забывать С с классами - 12 лет не кодил, но зашел в ваш тред понастальгировать после богомерзкого JS-треда с их программированием фреймворков.
А ещё тогда полюбил их __try __except
>Ну то есть вся абстрактопараша, все питушыные платформы с JIT-компиляцией и GC существуют чисто случайно, потому что авторы компиляторов сишки и плюсов добрые?
Типа того, всякие эмуляторы с браузерами напару с операционными системами туда же.
По-нормальному запись байтами выполняемого кода в память и последующий вызов оного как функции можно делать онли через вынос этого добра в ассемблер.
Именно.
Вот такая параша на самом деле UB в сяшке:
https://gist.github.com/nickdesaulniers/5299272
И на этом UB, считай, построен весь мир. Все мир, карл, может быть в одночасье doomed, и они еще называют сяшку системным языком, хотя ты на сяшке ни одну операционную систему без UB или ассемблера не напишешь.
>А как в некоторых других языках дело обстоит, не знаешь? Как-то же они умеют и могут в это. Но засчёт чего?
За счет ненативности и рантайма. Рантайм может хранить код как он хочет, компилировать его на лету, хранить различные метаданные, связанные с типами и прочее. Достигается это за счет того что код ненативный и выполняется либо интерпретатором, либо компилируется JIT-компилятором по необходимости со всеми требуемыми проверками во время выполнения.
Алсо, тред пора перекатывать.
Слишком категорично. Но да, JIT предполагает знание о системе и выход за пределы стандарта Си.
Ничего. Пустые скобки в Си (но не в крестах) означают, что информация о типах и количестве недоступна. Мы там выше обсуждали.
Ничего себе метапрограммирование в крестах. А если у меня эта функция перегружена числом параметров, компилятор разберется и вызовет то что нужно?
Пишу условие if ((p++) == 7) { ... }
В таком случае p будет инкрементировано только в рамках условия if, т.е. p увеличится на 1 и сравнится с цифрой 7, а в глобальном значении останется 6, так? Или же будет инкрементировано на единицу, и уже глобально будет иметь значение 7 во всей программе после проверки условия?
> в глобальном значении останется 6, так
Не так. Нет никаких рамок условия, есть выражение, и оно вычисляется. Постинкремент меняет переменную, и ему абсолютно похуй, где он сам в это время находится.
> p увеличится на 1 и сравнится с цифрой 7
Неа. Сначала сравнится, а потом увеличится. Поэтому если p изначально был равен 6, то тело if не выполнится. Но инкремент, разумеется, произойдет в любом случае, поэтому после вычисления выражения в скобках p станет равным 7.
Алсо, у нас новый тредик уже >>1187521 (OP).
Это копия, сохраненная 13 июля 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.