Это копия, сохраненная 29 апреля 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ https://wandbox.org/ или https://pastebin.com/ для вставки кода, если он длиной больше нескольких строк или содержит [i] или ∗.
Что читать:
- Brian Kernighan, Dennis Ritchie "The C Programming Language": http://www.cypress.com/file/56651/download
- Stephen Prata "C Primer Plus, 6th Edition" (2014): относительно свежая, знает про C89/C99/C11, описывает различия, объемная (около тысячи страниц), годная, с вопросами, упражнениями и ответами. Читать после K&R или до.
- Zed A. Shaw "Learn C the Hard Way" (2015): годное пособие для гуманитариев для гуманитариев!
- Немного примеров хорошего стиля: http://www.oualline.com/books.free/style/index.html
- ООП, например: http://www.cs.rit.edu/~ats/books/ooc.pdf
- Стандарт ISO/IEC 9899:1999 (C99): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf (драфт)
- Стандарт ISO/IEC 9899:2011 (C11): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (драфт)
- Черновик стандарта ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf (февраль, с диффами)
- Последний черновик ISO/IEC 9899:202x (C2x): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2583.pdf (октябрь)
Чем компилировать:
- Очевидный 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 помогает читать сложные сишные декларации.
Прошлые треды:
- №63: https://arhivach.net/thread/623165/
- №64: https://arhivach.net/thread/623166/
- №65: https://arhivach.net/thread/637465/ >>1852710 (OP)
Так крякни его, и сразу сможешь использовать эту функцию нормально без деморежима.
Да, если архитектура это предусматривает.
main не фактическая точка входа в программу
argv это массив указателей, элементы будут все так же лежать где-то в памяти.
К примеру: беру я название программы которую нужно открыть, ввожу первые 3 буквы, нажимаю TAB и чтобы все файлы которые начинаются с этих букв показывались в консоли.
Это как то через какие то готовые утилиты делается и библиотеки да?
Если что я сейчас изучаю stdlib с fopen и т.д
Какой-то bash это и так сделает если твоя приложуха лежит в пути который в PATH.
А если ты хочешь ещё и аргументы дополнять - там уже надо читать как bash autocomplete настраивать и писать скрипт.
Powrshell кажись тоже там умеет.
>>874945
r+ тебе нужен.
Ну а вообще если файл большой, и надо активно мелкие моменты в нем менять - изволь делать через mmap, но если ты начинающий, то даже не связывайся с этим.
Спасибо. Тогда не буду. Буду учить дальше.
a=b++ b++ b++;
Вообще UB. Ты не знаешь точно когда компилятор может всунуть инкремент - после всего блока вычислений три раза, или после каждого взятия значения из b.
https://ideone.com/QrjJty
Откуда лезут с этим вопросом? Это троллинг или на собеседованиях такое спрашивают?
В пабликах, это мем уровня "любой пятиклассник решит эту задачку"
выбрось эту книгу. дважды изменение одного объекта в памяти, не разделённое секвенс поинтом - ub
Тут не бывает правильного вывода, как не бывает правильного значения у фразы "нельзя казнить помиловать"
long i = 5 + 3;
То сами 5 и 3 перед тем как быть посчитанными и стать i принимаются за int, если не хватает места то unsigned int - long - unsigned long - long long - unsigned long long. Так вот в чем смысл добавлять суффиксы к этим статическим числам типо ULL (unsigned long long), если язык сам это делает автоматически? Не понимаю зачем это нужно именно с интами, с числами с плавающей точкой понятно, там изначально все числа даблы и если хотим сэкономить память, то используем флоаты при вычислении. В итоге контролируем не только к какому типу приводить, но и с каким вычислять. Но насколько я понимаю с интами все наоборот и изначально отчет стартует с самого минимального типа инта, и сам приводится автоматически к нужному типу. Так зачем это нужно? Сэкономить не выходит очевидно.
Надеюсь данный скрин поможет тебе приблизиться к пониманию.
> Сап, программач, начал изучать С
Рекомендую дальше продолжать изучение и искать смысл для каждой возможности этого чудесного и максимально простого языка.
>Так вот в чем смысл добавлять суффиксы к этим статическим числам типо ULL (unsigned long long), если язык сам это делает автоматически?
Чтобы подсказать компилятору как лучше сделать, очевидно же. Если ты пока не столкнулся с проблемой, это не значит что ее нет.
Ну меня конкретные случаи применения интересовали.
>When you declare a decimal integral literal in C, the compiler treats it as the first integral type that can hold the value, checking in the following order: int, long int, long long int. But your number is so large that it can not fit the signed long long type. To get rid of the warning, define the literal explicitly as unsigned by adding U or u.
Как я понял есть два случая:
1. Когда проводим вычисления и мы перелетаем границы типа при этом используя два младших типа (int + int = int, по логике компилятора, но это может быть и лонг, поэтому хотя бы один литерал нужно обозначить как лонг, чтобы производилось приведение типов, если у нас такой случай.)
2. Когда литерал больше типа long long, то есть unsigned long long, тогда достаточно просто поставить U или u и компилятор поймет, что имеется ввиду unsigned long long.
Короче учебник неверную информацию предоставил о поведении компилятора, мол литералы приводятся прям до unsigned long long, хотя выше long long нужно уже вручную обозначать и особой разницы между ULL, UL, U нет, они только в выражениях играют роль, если приводить надо.
У операции "присваивание" приоритет выше, чем у постинкремента.
У постинкремента самый низкий приоритет.
Покажи мне компилятор, который посчитает это выражение как 6 и 4.
>Это какой-то феерический пиздец с ключами.
Что с ними не так?
>Где вы такие "компиляторы" находите?
Обычный онлайн компилятор. Написал в нем, потому что пк не под рукой.
>>877036
Чтобы явно показать, что следующий адрес на единицу больше в десятичной системе. В общем, для наглядности конкретного примера, не более.
>У постинкремента самый низкий приоритет.
Это неважно, потому что в данном случае важны точки следования (sequence points) а их тут нет
Это UB (Undefined behavior), неопределенно поведение. Оно не определено, хоть и не является ошибкой. Компилятору на вход дали мусор, компилятор может выдать мусор.
Более того, сегодня он тебе выдаст 1 и 4, а завтра ты допишешь какую то функцию, оптимизация поменяется, и выведет что то другое - why not?
>Покажи мне компилятор, который посчитает это выражение как 6 и 4.
Clang, GCC.
Вряд ли на хосте того веб-компилятора используется восьмибитный проц. Ниже результаты msvc и gcc. В обоих случаях компилировалось под x86 32-бит. Видно, что char всегда располагается по нечетному адресу, а int - по четному (возможно, кратному 4-м). Чем это обусловлено? Еще раз повторю вопрос: разве не должно применяться принудительное выравнивание памяти по 4 байта на 32-бит и по 8 байт на 64-бит, дабы соответствовать машинному слову? Ведь так процу на 32 бит придется бегать не по 4 294 967 296 адресам, а по 1 073 741 824 фрагментам по 4 байта. Я вообще раньше думал, что так и работает. Но факт того, что char'ы размещаются в нечетных адресах уже приводит к тому, что разметка наебется. Плюс, чел >>877041 говорит, что x86 может обращаться к любой ячейке. Если по умолчанию компиляторы для x86 не включают выравнивание в ОЗУ, то нахуя они это делают в структурах, например?
Я хз, что за компилятор там используется и с какими ключами он запускается по умолчанию. Вообще, такие вещи касательно выравнивания как-то описываются в стандарте языка? Или это уже приколы компиляторов и только?
Процессор всё равно будет выбирать с шины или из кэша целым словом. Ради теста сделай два char, а затем int
Наверняка в памяти каждое из них будет в границах 4-х байт.
А уже как внутри этих 4-х байт будет выровнен char это уже дело десятое.
Хотя... с другой стороны, если приведёшь неыровненный указатель к указателю на int, то получится чушь. Странно. Но проверять лениво.
>такие вещи касательно выравнивания как-то описываются в стандарте языка?
va_arg должен понимать выравнивание и он платформо и системо зависим. Но видя какое выравнивание тут постят троллят вестимо, лучше всегда смотреть что сгенерировал компилятор, когда выравнивание критично.
А какая разница? Язык это язык, компилятор это компилятор.
>Наверняка в памяти каждое из них будет в границах 4-х байт.
Да, так и вышло. Если добавить еще три чара, то адреса будут:
41 - char
40 - char
39 - char
38 - char
34 - int (с 34-го по 37-й байт -- 4 байта)
То есть фрагменты действительно по 4 байта, если объявлять char компилятор ставит его в самый последний байт фрагмента. Т.е., фрагмент в 4 байта заполняется от начала к концу.
>Хотя... с другой стороны, если приведёшь неыровненный указатель к указателю на int, то получится чушь. Странно. Но проверять лениво.
Почему чушь? Указатель же может в любой адрес указывать. Тип, на который он указывает, нужен лишь для адресной арифметики.
Выравнивают структуры.
Зачем одинокую переменную выравнивать? Нету смысла.
Более того, есть команды во всяких армах/riscv которые могут делать load/store для байтных значений. По твоей логике выходит если у процессора машинное слово это 4 байта, то он с другими типами не должен иметь возможности работать и нужно городить костыли?
На пикриле можешь увидеть как компилятор спокойно кладет по адресу SP + 31 значение char командой strb. И ничего плохого не случается.
4
180
Что надо выводится, но awk продолжает принимать на вход строки с клавиатуры и не спешит завершать работу. Почему так и как его заставить сдохнуть после вывода этих двух чисел?
if (fork() == 0)
{
dup2(desc[1], 1);
execl("/bin/du", "du", "myfile", ".", NULL);
}
else
{
wait(&s);
dup2(g[0], 0);
execl("/bin/awk", "awk", "{print $1;}", NULL);
}
}
Переформулируй вопрос. На пике все объекты выравнены (остаток от деления адреса на размер = 0)
И wait не нужен.
>The attached kernel patch (applied on top of 4.18.5) that I've tried, almost completely eliminates the disk thrashing(the constant reading of executable(and .so) files on every context switch) associated with freezing the OS and so, with this patch, the OOM-killer is triggered within a maxium of 1 second when it is needed, rather than, without this patch, freeze the OS for minutes
>, without this patch, freeze the OS for minutes
Linux kernel. 29 years gone.
Are you serious?
Патч посмотрел. Почему именно 250 Мб?
Отпишешь сюда что Торвальдс скажет. Или мэйнтенейр. Интересно же.
>Почему именно 250 Мб?
Патч не мой. В другой версии дефолт 64 и мождно настраивать.
Читай ридми внимательно - патч создал анон и исчез\. Я воссоздал его труды.
Потому что это реально хороший порог. В федора 33 демон uresourced резервирует 250м для DE.
Запомни, учишься ты сам. А пту/универ/остальная шарага нудны чтобы подтянуть слегка уровень в общем развитии и найти людей с такими же взглядами как ты.
Без разницы что дальше изучаешь.
Можешь вообще хоть забить, не ходить туда. Главное самостоятельно обучаться.
Я так и делаюмои бивисы некоторые еще до массивов не дошли, лол, но просто интересно, что ждет дальше? Какой язык программирования будет, или последующая зубрешка си'шки и js. Просто хочу знать и да, и смешно слушать про саморазвитие и т.п в си треде, лол.
план обучения ищи на сайте своей шараги
>Запомни, учишься ты сам.
Да.
>А пту/универ/остальная шарага нудны чтобы подтянуть слегка уровень в общем развитии и найти людей с такими же взглядами как ты.
Лолнет. Учебки не учат, а калечат. Это такой фильтр/экзамен на "взрослую жизнь", принуждающий делать всякое бессмысленное говно уровня копать от забора и до обеда "потому что важный начальник (здесь препод) скозал нада" молча повинуясь, и заодно вертеться в обществе, выкручиваясь с оценачками и прочей поебалой, чтобы не делать всё как честный дурак и не сдохнуть от стресса в результате. В итоге выходят годные члены общества - рабочие мураввьи, без мозга, но исполнительные и умеющие в коллектив, где можно - откосить, кому нужно - подсосать, и так далее. Вот что учат все эти учебки.
Высер душевно больного школьника который не осилил пту?
Все так, а это что, плохо?
Сап байтоебач. Дублирую пост с C++ треда. >>1879047 →
Есть функция на Си и ее интерпретация на асме, пик тотали рилейтед.
Казалось бы, компилятор должен выделить 16 байт под буфер и 4 байта под флаг, и тогда стек должен выглядеть как на рисунке 1, но нет, он выглядит как на рисунке 2. А именно -- флаг, 12 байт непонятной хуйни, 16 байт буфера, 8 байт указатель (типа в регистре он их оставлять не хотел) и еще 8 байт выделенных хуй знает зачем. Больше всего меня беспокоят 12 байт между флагом и буфером, т.к. от этого зависит, как будет работать эксплойт через переполнение буфера.
Через компилер эксплорер код прогнал, гцц и клэнг выдают примерно то же самое. Пока что нагуглить смог только canary value, но не уверен, что это оно.
>Казалось бы, компилятор должен выделить 16 байт под буфер и 4 байта под флаг,
размер слова в стеке равен разрядности процессора.
Ассемберный код не соответствует картинке с исходником.
int b = 1;
b = ++b;
Я так понимаю, значение b может быть 2, если пре-инкремент прибавит к b единицу и вернет полученное значение, которое затем будет присвоено b. Или же b может быть равно 3, если будет отдельно посчитано значение b+1 (без изменения значения b), и уже после того, как полученное значение будет присвоено b, выполнится инкремент. То есть, либо это сработает так
b = b+1;
b = b + 1;
либо так
b = b + 1;
b = b;
Вопрос в том, почему нельзя уточнить этот момент в стандарте? Например, обязать реализацию выполнять преинкремент сразу, и не считать b+1 отдельно. Неужели, эта проблема не решается?
>это паддинг
Понял, спасибо. Забыл сказать, что компилировалось скорее всего с флагом -fno-stack-protector. Нагуглил, что gcc выравнивает стек по 16 байт. Т.е. там получается как на картинке пикрилейтед слева? Почему он не может сделать как второй вариант? Гцц без флагов оптимизации просто в тупую выделяет переменные по одной и каждый раз делает алигнмент, вместо того, чтобы выделить сразу все и сделать алигнмент для всех? Второй вариант расценивается уже как оптимизация?
Олсо, попробовал флаг mpreferred-stack-boundary=3, я думал, что он выдаст третий вариант, но раздутый пэддинг никуда не пропал, как будто гцц вспомнил, что стэк баундари равно 3 только когда отнял из rsp 40 байт.
>>879104
>размер слова в стеке равен разрядности процессора.
Так тут все равно лишнее место получается, даже если выравнивалось по 8 байт.
>Ассемберный код не соответствует картинке с исходником.
Не понимаю, о чем ты, compiler explorer почти идентичную залупу выдает.
https://godbolt.org/z/nTqYen
На второй картинке ошибка в четвертом варианте, там последнего пэда нет, ну вы поняли в общем.
С -O3 вообще переменной flag нету, просто в аккумуляторе значение и сразу возврат.
Либо перестаешь пользоваться scanf и переходишь на какой нибудь fgets
Либо затыкаешь варнинг, задав #define _CRT_SECURE_NO_WARNINGS как там написано
А, ну что касается первого ворнинга, scanf возвращает количество распарсеннгого, то есть ты можешь обрабатывать ошибки
int read_x = 0;
do {
read_x = scanf("%f", &x);
if(read_x == 0) printf("ошибка ввода бла бла");
} while (readx == 0 && ready == 0);
scanf_s (если ругает ко всей хуйня добать _s) и будет робить
Поменяй компилятор или подкрути, чтобы были ПРЕДУПРЕЖДЕНИЯ, а не ШУМ.
что такое булевская библиотека?
>Не понимаю, о чем ты, compiler explorer почти идентичную залупу выдает.
var_4 откуда взялась?
Учи английский. Без него тебе только в 1С программировать придётся.
так нахуя тут проверка? Явно человек учиться и до циклов не дошел, а ты его грузишь лишней инфой. Да и проверка на дурака нахер тут не нужна в реалиях.
Он спросил что у него за ворнинг. Там прямым текстом написано что программист игнорирует возращаемое значение. Я написал зачем эта функция что-то возвращает.
Стандартный варнинг в vs19, если не написать _s в конце scanf. Держу в курсе. Эта хуита и так будет работать, без проверки
на дурака.
ЯННП. Объясните пж.
Вот у меня есть файл yoba.c. К нему я инклюжу yoba.h.
Так вот, в файле yoba.c у меня было несколько переменных и функций с идентефекатором static и все компилится/билдится. И я часть из них перенес в файл yoba.h и прога все равно компилтся без ошибок.
Но какого хуя? Ведь идентефикатор static делает видимость только в пределах одного файла, почему тогда функции и переменные, обозначенные в файле yoba.h видны в файле yoba.c????
Няшки подскажите, на сколько рекурсия отсасывает в производительности? У меня есть рекурсивная функция, четкая и красива, а вот переписать ее это получается ебаный нечитаемый ад.
Вот так норм?
Сравни количество слов, сохраняемых на стеке с тем, сколько будешь сохранять после переписывания. Есть разница в разы?
А глубина рекурсии какая?
>А глубина рекурсии какая?
Не более 5
>сколько будешь сохранять после переписывания
Я там сам стек заводил пихал туда состояния и я ебанулся за ним следить, код превратился в нечитаемое говно и мой мозг поломался
Лол, как это вообще возможно? Все итеративные алгоритмы в разы проще и понятней.
>на сколько рекурсия отсасывает в производительности?
С чего бы это? Если не гоняешь по стеку большое количество аргументов функции, то рекурсия вполне хороша.
Ну а так считай сам - на первом входе будут Page Faults при росте стека. Но дальше эта память твоя и просадки по скорости не будет.
>Все итеративные алгоритмы в разы проще и понятней.
Чигобля? Даже школьный фибоначчи легче в рекурсивном виде.
Точно, ещё и локальные переменные к аргументам добавляются.
Но всё равно стек "дрочится" только единожды. Дальше виртуальные страницы стека уже отображены процессу и всё быстро работает.
Виртуальную машину. Не полностью, а просто выполнение инструкций. Без прерываний, без видео и любой периферии - просто виртуальную машину, чтобы умела по шагам выполняться и показыват текущее значение регистров, верхушки стека и по желанию дамп памяти.
Поиск и извлечение всех webp-файлов из произвольного контейнера, используя небольшой буфер, 64 Кб, например.
Лолчто? Итеративный фибоначчи занимает пару строк
int sum = 1;
while (n > 1) {
sum *= n;
n--;
}
Иди стек прокручивай, неуч.
Ну конечно, у тебя сразу с двух, лол
ты агрессивный какой-то, родители в детстве много били?
Лабы нахуй, это стандарт борды.
Возможно тебе будет интересно, порешать простые задачки, поотвечать на нелепые вопросы начинающего в этом деле. Там не очень много
Нет, это не интересно
int i, j, size;
printf("Введите восемь целых чисел: ");
scanf("%d %d %d %d %d %d %d %d", nums);
//printf("%d\n", nums[0]);
size = sizeof(nums) / sizeof(int);
//printf("%d", size);
for(i = size - 1, j=0;i>=0;i--, j++)
{
reverseNums[j] = nums;
printf("%d", reverseNums[j]);
}
for(j = 0;j < size;j++)
{
printf("%d", reverseNums[j]);
}
Цель отобразить массив nums в обратном порядке.
Какого хуя ошибка сегментации вылетает?
Судя по отладке с помощью printf проблема где то ещё на чтении чисел. Хотя scanf допускает применение нескольких спецификаторов через пробел.
Но вот проблема, kbuild хочет .cmd файлы иметь для всех объектников. Якобы, чтоб как-то проверять что-то связанное с необходимостью пересборки.
И он их сам генерит, если сишники сам собирает.
Но для готовых объектников не генерит.
Я воткнул везде touch .object_file_name.o.cmd - помогло. Но это вроде как костыль. Знает кто?
Так-то необязательно проприетарного. Там асмовые исходники собираются отдельным ассемблером.
Тогда почему не добавить его нормально в систему сборки ядра? Вроде как модули на ассемблере в линуксах тоже есть.
(Про -> знаю, записал именно так для наглядности)
в строках из ошибки присваивание элементу s.data значения и распечатывание соответственно.
Потому что во втором случае создается копию структуру и инициализируется. Изначальный объект, который в main, при этом остаётся неинициализированным.
> Потому что во втором случае создается копию структуру и инициализируется. Изначальный объект, который в main, при этом остаётся неинициализированным.
Не понял. Как инициализация зависит от вызова функции где-то дальше по программе?
Ты вызываешь InitStack, где полям структуры присваивается значения, в том числе происходит аллокация памяти.
После выхода из функции копия структуры уничтожается (а память утекает).
struct stack s остаётся дефолтным, с не инициализированными полями, без аллоцированной памяти.
А лол, понял, спс большое.
#include <stdio.h>
int main(void)
{
int nums[8], reverse_nums[8];
size_t size;
printf("Введите восемь целых чисел: ");
scanf("%d %d %d %d %d %d %d %d",
&nums[0], &nums[1], &nums[2],
&nums[3], &nums[4], &nums[5],
&nums[6], &nums[7]);
size = sizeof(nums) / sizeof(int);
for(int i = size - 1, j = 0; i >= 0; i--, j++)
{
reverse_nums[j] = nums;
printf("%d ", nums[j]);
}
printf("\n");
for(int i = 0; i < size; i++)
{
printf("%d ", reverse_nums);
}
printf("\n");
}
Жду советов олдфагов как можно сделать лучше, потому что в С новичок.
#include <stdio.h>
int main(void)
{
int nums[8], reverse_nums[8];
size_t size;
printf("Введите восемь целых чисел: ");
scanf("%d %d %d %d %d %d %d %d",
&nums[0], &nums[1], &nums[2],
&nums[3], &nums[4], &nums[5],
&nums[6], &nums[7]);
size = sizeof(nums) / sizeof(int);
for(int i = size - 1, j = 0; i >= 0; i--, j++)
{
reverse_nums[j] = nums;
printf("%d ", nums[j]);
}
printf("\n");
for(int i = 0; i < size; i++)
{
printf("%d ", reverse_nums);
}
printf("\n");
}
Жду советов олдфагов как можно сделать лучше, потому что в С новичок.
Ой, блять
#include <stdio.h>
int main(void)
{
int nums[8], reverse_nums[8];
size_t size;
printf("Введите восемь целых чисел: ");
scanf("%d %d %d %d %d %d %d %d",
&nums[0], &nums[1], &nums[2],
&nums[3], &nums[4], &nums[5],
&nums[6], &nums[7]);
size = sizeof(nums) / sizeof(int);
for(int i = size - 1, j = 0; i >= 0; i--, j++)
{
reverse_nums[j] = nums;
printf("%d ", nums[j]);
}
printf("\n");
for(int i = 0; i < size; i++)
{
printf("%d ", reverse_nums);
}
printf("\n");
}
Пропустил
Ой, блять
#include <stdio.h>
int main(void)
{
int nums[8], reverse_nums[8];
size_t size;
printf("Введите восемь целых чисел: ");
scanf("%d %d %d %d %d %d %d %d",
&nums[0], &nums[1], &nums[2],
&nums[3], &nums[4], &nums[5],
&nums[6], &nums[7]);
size = sizeof(nums) / sizeof(int);
for(int i = size - 1, j = 0; i >= 0; i--, j++)
{
reverse_nums[j] = nums;
printf("%d ", nums[j]);
}
printf("\n");
for(int i = 0; i < size; i++)
{
printf("%d ", reverse_nums);
}
printf("\n");
}
Пропустил
Если ты о задаче из Праты то тебе надо просто распечатаь масив в обратном порядк, не нужно отдельный создавать.
В параметрах функций всегда передается не то, что ты в них пишешь, а делается его копия и уже эта копия отправляется в параметр. Таким образом, функция получает копии, а исходная сущность всегда остается неизменной.
То есть, если ты отправляешь константу, создается переменная (параметр) с этим значением. Если отправляешь переменную, создается копия этой переменной. И не важно какой тип. Если переменная int, создается новая переменна int, если указатель, создается новая переменная указатель, если структура, создается новая структура. Параметры функций (переменные-копии) существуют пока работает функция, когда функция завершается, они естественно уничтожаются.
Исключением являются массивы, которые вроде как не копируются, а передаются по указателю, вопреки тому, что передаешь именно сам массив, а не указатель. Но массивы это вообще особенный феномен, наговнокоженный вопреки логике языка. Массивы надо учить отдельно, как ебанутую хуйню, просто потому что есть в языке такаой бред и надо смириться.
И возвращаясь к началу, в крестах таки можно передавать в параметр саму сущность, а не копию, для этого там есть ссылки. Но в си ссылок нет, тут для изменения исходной сущности передают указатель на неё.
1 слово
2 слово
3 слово
Я так понял использовать нужно бинарный формат, я создал отдельный файл для этого в бинарной форме, через fwrite вставил туда переменную которая сохраняется каждый раз при закрытий программы, т. е задача решена.
Но я хотел бы поинтересоваться, могу ли я использовать один файл для сохранения этой переменной не создавая второй? И как это сделать?
Открыть этот же файл в текстовой форме и присвоить на один указатель на файл, а бинарную форму на второй указатель?
Реквестирую курс по с/с++, где объясняется оформление исполняемого файла и добавление встроенный или
директорных ресурсов (Иконки, вав-вайлы и т.д.). Желательно с пояснением синтаксиса и роли
библиотек. Можно в виде статьи.
Язык не специфицирует форматы экзешников. Смотри в доках на свою ОС
>И какой по твоему должен быть sizeof обычного указателя?
Такой же как у int
Почему тогда a не 4? Он жи есть указатель на первый элемент массива.
а объявлен как массив, ь как указатель.
Я не понимаю тебя. Причем тут ОС и доступ к файлам через язык программирования? Ты о чем вообще? Я учусь. Мне нужно через stdlib создать файл в который будут добавляться слова после ввода и печатать в каком порядке были добавлены слова.
Ниочем не говорит.
Значит ты пишешь на каком то другом языке, возможно на яваскрипте.
Ну ты скорее всего не понял задачу, спроси у учителя.
Очевидно что ты можешь просто прочитать файл по одной строке и сосчитать таким образом их количество.
Или ты можешь прочитать последнюю строку и распарсить число которое у нее в начале.
Ага, уже сообразил. Проще было посчитать количество строк. А вообще как это работает с fprintf, fwrite? Если юзаешь fprintf то пишешь в текстовый режим текст, а fwrite или fwrite то только в бинарном сохраняешь данные правильно? Т.е я не смогу достать переменную сохраненную в текстовом режиме?
#include<stdio.h>
#include <locale.h>
void main(){
setlocale(LC_ALL, "Rus");
int a[100];
int n, i, b;
puts("Указать размер массива:");
scanf_s("%d", &n);
puts("Эллементы массива:");
for (i = 0; i < n; i++){
scanf_s("%d", &a);
}
for (i = 0; i < n / 2; i++){
b = a;
a = a[n - i - 1];
a[n - i - 1] = b;
}
for (i = 0; i < n; i++)
printf("%d ", a);
}
Тоже новичек, но в пту так учили
#include<stdio.h>
#include <locale.h>
void main(){
setlocale(LC_ALL, "Rus");
int a[100];
int n, i, b;
puts("Указать размер массива:");
scanf_s("%d", &n);
puts("Эллементы массива:");
for (i = 0; i < n; i++){
scanf_s("%d", &a);
}
for (i = 0; i < n / 2; i++){
b = a;
a = a[n - i - 1];
a[n - i - 1] = b;
}
for (i = 0; i < n; i++)
printf("%d ", a);
}обосрався
.h это заголовочный файл, если ты включил заголовочный файл в .c файл то он исчезает при комплияций и становится единым целым с исходным файлом, по крайней мере так видит это компилятор. Если ты используешь static в заголовочном файле, то ты не напрямую получаешь инфу, а копируешь. Если бы ты использовал static в другом исходном файле и пытался получить доступ с другого, компилятор бы тебя не понял, потому что для него это слепая зона.
Не слушай пидоров с пту, развивайся сам а? Я смотрю на этот код и мне хочется блевать.
Ну так предложи свое решение, все такие умные, а как просишь показать так сразу по сьебам.
>>883998
>>883127
Нахуя создавать reverse массив, если вы пишите, что его нужно просто вывести в обратном порядке?
#include <stdio.h>
int main()
{
int i,n;
printf("Введите размер массива: ");
scanf("%d",&n);
int nums[n];
for (i=0;i<n;i++)
{
printf("Введите %d элемент массива: ",i);
scanf("%d",&nums);
}
printf("Заданный массив в обратном порядке: ");
for (i=n-1;i>=0;i--)
printf("%d ",nums);
return 0;
}
>>883998
>>883127
Нахуя создавать reverse массив, если вы пишите, что его нужно просто вывести в обратном порядке?
#include <stdio.h>
int main()
{
int i,n;
printf("Введите размер массива: ");
scanf("%d",&n);
int nums[n];
for (i=0;i<n;i++)
{
printf("Введите %d элемент массива: ",i);
scanf("%d",&nums);
}
printf("Заданный массив в обратном порядке: ");
for (i=n-1;i>=0;i--)
printf("%d ",nums);
return 0;
}
#include<stdio.h>
#include <locale.h>
void r_arr() {
int n;
if(scanf(" %d", &n) == -1) return;
r_arr();
printf("%d ", n);
}
void main() {
setlocale(LC_ALL, "Rus");
r_arr();
}
А ты умен сука. Жаль что рекурсия бесполезна.
Я изначально так решал когда то. Интересно если им дать написать алгоритм сортировки че будет?
Ну переменные в бинарном формате, т.е они сохраняются так как компьютер их видит. Есть текстовый формат, в котором сохраняется только текст, а есть бинарный в котором может сохраняться и текст и переменные но в бинарном виде.
Короче могу ли я сохранить переменные в текстовом файле, вот в чем вопрос. Можно же как то раз предполагается, пишут что в текстовом файле можно сохранять бинарные данные.
> Нет текстового и бинарного формата, все хранится в бинарном
Но есть флажок b для fopen. Ой...
Что тебе мешает сохранить переменную текстом?
Что по твоему случится с переменной в бинарном виде, если твой текстовый файл откроют блокнотом, поменяют пару строчек, а потом сохранят?
Спасибо. Я снова прочитал различия, в юниксе их нет для файла оказывается. Но вот почему когда я пытаюсь вытащить переменную из текстового файла, при этом сохраняя её через fwrite, выходит мусор при использований этой переменной типа -123123123123123123? Влияет ли на это использование fscanf и fprintf?
Ну смотри, мне нужно достать из файла эту переменную потом, нужно писать функцию которая будет искать внутри текста это число, потом конвертировать его через atoi? Аааа ничего не понимаю.
Кто нибудь подскажите я смогу посмотреть через дебагер что творится внутри программы в плане просмотра содержимого буфера итд?
В моём мейкфайле есть куча одинаковых команд, с разными таргет/пререквизтами
Application.o: Core/Application.cpp
$(CXX) $< -c $(INCLUDES) -o $@
Log.o: Logger/Log.cpp
$(CXX) $< -c $(INCLUDES) -o $@
Как записать это в одно правило? Везде пишут %.o: %.cpp, но мне не нужно для всех целей, а только для определённых, плюс непонятно, как dirname отбросить для таргета.
Есть, в хорошей книжке Кернигана и Ричи - первая глава. Книжка в шапке первым пунктом.
Рекурсия на стеке.
Представь себе колоду карточек
Ты пытаешься считать число и если получилось, то записываешь его на карточку в поле n
Когда числа закончились, ты начинаешь выводить записанное на верхней карточке n, а потом скидываешь эту карточку открывая ту что под ней.
Читай хороший код (ядро bsd очень чистенько выглядит).
Для начала определись что такое красивый код, когда выведешь формальные критерии - их и придерживайся.
Вообще C маловыразительный язык, поэтому красоты в нем мало.
>char гарантированно имеет длину 1 байта
Забыли упомянуть только, что C-байт может быть не 8 бит.
Есть же книжки на тему, так и называются, серия "Чистый код" Мартина, "Совершенный код" Маконнела.
*МакКоннела, конечно.
Вопрос в другом. Влияют ли они как то друг на друга? Может ли fwrite переписать данные fprintf и наоборот?
Там же есть всякие директивы компиляторам. Почему не ввести еще одну типа destructor, что когда ее объявляешь для какого-то типа (а у нас он будет один - это пользовательсая структура), то вызовется эта данная функция.
Т.е. будет что-то вида
destructor my_struct f() { // что-то делаем }
upd:
это же по сути никак не изменит язык, не переусложнит его. Он же и сейчас отслеживает, когда структура выходит из области видимости и выкидывает ее, а так просто при создании ассемблерного выхлопа перед этим освобождением бы всовывал имеющуюся деструктурную функцию.
Речь про C и его все новые стандарты 11/17/2x.. Почему все не вводят и не вводят такую мега удобную вещь. Это же не испортит старую кодовую базу никак, не добавит накладных расходов.
> в сторону Zig
да есть плюсы и раст тогда уж
Ну, наверное потому что в Си весь поток выполнения линеен и нет неявных прыжков?
Вот нашел расширение gcc
https://stackoverflow.com/questions/1828550/portable-equivalent-to-gccs-attribute-cleanup
Ну так и в чем изменится его нелинейность при создании на этапе компиляции ассемблерного выхлопа? Просто вместо освободить память у базового типа удет вставляться при необходимости вызов еще одной функции.
Ну вот как в это gcc, например. Почему не берут очевидную полезную и нужную вещь в стандарт. Это же избавило бы от кучи возможного забытия очищения памяти, не добавляя никаких накладых расходов.
плюсы с растом сейчас плюс-минус на одном уровне по скорости, и - да, в крупных сложных проектах, а не линейных алгоритмах, они обгоняют уже сишечку по скорости из-за того же отсутсвия расходов для некоторых действий в рантайме
Нелинейность будет не в ассемблерном коде, а в программе на Си.
Появляется неявный вызов не в той точке, где он написан. Ну это как... Исключения в c++.
Перетолстил.
Так кому не надо и не будут этим пользоваться, а вот кому из-за отсутствия деструкторов библиотеки приходится переусложнять и апи для них, что потом пользователям надо помнить не забывать делать free для кучи вещей, хотя это можно было бы от них скрыть - это сильно бы помогло.
Так это не переусложнение, когда у тебя есть явное _Free. Переусложнение будет когда будет разброд и шатание. У одних есть, у других нету.
в смысле, ну так это такая же функция. Вот ты вызвал из сторонней либы f() ты же тоже не знаешь, что она под капотом делает и что вызывает. Поэтому читаешь доки или смотришь код, где уже и видешь, что именно оно делает.
Если тебе в твоем коде это не нужно, то и не используешь никак.
Ну во всех компиляторах это есть в том или ином виде, просто нужно это стандартизовать.
Я знаю что я вызвал f() и вернусь в строчку ровно после f(), а не улечу куда-то по неявному обработчику, не?
Пользователь функции f() получит точно такие же два исхода: либо внутри функции все поломалось либо он вернулся к строчке после ее вызова.
Ты хочешь разменять протечку по памяти/ресурсам на потенциальную протечку по памяти при отсутствии деструктора и потенциальный UaF при его наличии. Спизди себе набор _cleanup_ макросов из systemd если очень надо.
> Спизди себе набор _cleanup_ макросов из systemd если очень надо.
Куда я его спизжу, если он не на всех компиляторах работает.
> на потенциальную протечку по памяти при отсутствии деструктора и потенциальный UaF при его наличии.
утечка будет только в том случае, если предоставляемый код был кривым, от этого ты и так не застрахуешься
снимается возможность забыть пользователем освободить ресурс
соответственно при его отсутствии мы имеем все как было, при его наличии всего лишь выполнется +1 функция, которую не пользователь вынуждено вызывает ручками, а она сама на этапе компиляции вставится
Нет, ты не понял. Тебе всё-равно ВСЕГДА нужно будет проверять не забыл ли ты конкретно для этой структуры определить деструктор. А заодно и для вложенных полей этой структуры (их нужно удалять в своём деструкторе или нет, как считаешь?).
Кстати, если так подумать, то нахуй тебе деструктор, если у тебя и конструктора нет? Если в структуре хранится что-то что надо чистить, то это что-то всегда было передано извне и сруктура этим не владеет и не может почистить сама.
И ты прелагаешь непонятный костыль, который приносит в код UB.
> Куда я его спизжу, если он не на всех компиляторах работает.
Ну сорян, сделай ifdef и крэшся если собирают не шлангом с gcc.
так UB появиться неоткуда, из минусов только чуть дольше происходит компиляция
ну конструктор еще можно пережить, в крайнем случае пользователь условную функцию init не забудет вызвать, т.к. делает это прямо здесь и сейчас, а вот потом где-то там освободить ресурс - постоянно
ну вот есть допустим структура, а в ней вектор есть динамический
функции есть для работы с этой структурой типа добавить элемент/удалить
а вот при выходе самой структуры из области видимости пользователи часто забывают вызвать условное free() для этой структуры
поэтому и говорю, что очень часто не хватает деструкторов (хотя напоминаю, что почти во всех компиляторах они есть, с разными названиями)
Двач, не гони меня тряпками, а лучше объясни. Без какого либо бэкграунда начал вкатываться. Пытаюсь осилить курс CS50, смотрю как украинскую так и ангельскую версии лекций. Собственно вопрос в PSETe 1, а именно mario. У меня получилось сделать задание, но я его всё написал через printf, понял, что получилась стена говна и пошёл в интернет. Нашёл пикрелейтед и нихуя не понимаю. Как работает этот алгоритм. Знакомых которые могли бы объяснить у меня нет. Если можно, то прям как бабуину на пальцах. Cпасибо.
> Исключением являются массивы, которые вроде как не копируются, а передаются по указателю, вопреки тому, что передаешь именно сам массив, а не указатель.
Но ведь "сам массив" и есть указатель на его первый элемент, вроде все логично, нет?
>так UB появиться неоткуда, из минусов только чуть дольше происходит компиляция
Если ты неправильно отследил кто владеет памятью и почистил её, то возникает UaF и что в программе произойдёт дальше тебе никто не гарантирует. Также пользователь либы может вытащить из твоей структуры указатель, которым не владеет, и сохранить у себя.
> ну вот есть допустим структура, а в ней вектор есть динамический
> функции есть для работы с этой структурой типа добавить элемент/удалить
Без внятной концепции владения деструктор только сделает хуже. Тебе не деструктор нужен, а умные указатели.
Я не пробовал - https://github.com/Snaipe/libcsptr
почитаю всю ветку, я вообще не о том спрашиваю как кому-то что-то сделать в конкретном случае, я про стандарт и его развитие и про причины торможения
Всё просто, на пикрелейтеде написана полная хуйня, которая скорее всего и не работает.
Держи - https://ideone.com/VxBsws
Тут всё просто, сам разберёшься.
>>885069
В программировании стараются избегать повторения кода, поэтому придумали циклы.
Цикл for выполняется от, до (пока условие соблюдается), и с шагом.
Внешний цикл выполняется size раз, рисуя строчки. В конце каждой строчки рисуется перевод на новую строку.
Внутренний цикл выполняется _для каждого шага внешнего цикла_, size раз
Внутри него рисуется по 1 символу (пока забьем на условие), таким образом у тебя будет нарисована таблица size на size.
Остается вопрос какой символ рисовать, закрашенный или пустую клеточку. Для этого грубо говоря складывают x и y координату. Можешь проверить в тетради в клетку. Примерно так: если строка 23, то нарисовать можно только в столбце 0; если строка 22, то логично что можно нарисовать в столбце 0 и 1; если 21, то в 0, 1 и 2; и так далее.
Ещё раз ты просишь деструкторы, не понимая зачем они появились в плюсах, для задач которые деструкторы нормально не решают впринципе.
Никто такую хуйню в стандарт тащить не будет.
Потому что в комитете Си консерваторы, которые не хотят тащить все подряд из плюсов, но тебе такой ответ вряд ли понрваится.
плюсы тут ни при чем, это ж просто концепция, а тут она более чем востребована и опять же всеми разрабами компилатор уже как-то да запилена, но каждый написал свой костыль и поэтому почти никто не пользуется
Помню читал такой срач и там чуваку просто скинули ссылку где вступить в WorkGroup чтобы официально давать предложения в стандарт :3 Погугли, запплайся, напиши, вдруг добавят.
Мне больше интересно почему никто не форкнет компилер (или напишет свой, там же немного писать) и не сделает диалект C без UB.
>компилер - это дохуя сложно
В случае с Си - легко. И воспроизводилось кучей людей.
>rust
Гавно без задач и нинужно.
когда напишешь еще один компилятор, то ты просто увеличишь их количество, а польза будет отрицательной, нужно сам язык улучшать
Компилятор же детектит UB, надо просто пропатчить чтобы это была хард ошибка.
в интерпретируемых - да, в работающих уровнем пониже - пока не получится избавится, т.к. железо разное и его поведение разное, порой принципиально
Железо тут не причем. Речь про Undefined, а не про Implementation defined. Алсо толсто, C# компилируется AOT либо JIT
Ты эту концепцию сначала опиши нормально.
>>885096
> UB
Есть один нюанс. UB в стандарте появился не от балды, а потому что C - кроссплатформенный ассемблер под абсолютно разную хуйню с абсолютно разной реакцией на граничные ситуации которые потом и назвали UB. И когда ты решаешь UB ты по сути отрезаешь платформы.
> почему никто не сделает диалект C без UB.
Сделали кучу раз. Последняя попытка называется golang, можешь попробовать.
> Ты эту концепцию сначала опиши нормально
описал выше уже подробно: возможность описать функцию, которая вызывается перед выходом объекта этого типа из области видимости.
С примерами описал где она многим требуется и жалуются, что не хватает. И как разрабы, так и пользователи.
Описал, что это ничего никому не испортит, а только добавит полезный функционал языку (видимо поэтому все почти разрабы компиляторов это уже сто лет реализовали)
#include <stdint.h>
int main(void)
{
long long result = INT64_MIN / -1;
printf("The result: %lld", result);
}
Твоя концепция не решает твои проблемы вообще никак, а примеры твои работают только у тебя в голове.
Давай псевдокодом прям вот тут:
```
void _Free(array• a){
if(a->data) { free(a->data); a->data=NULL}
}
int foo(void)
{
array a = { .data=malloc(10 • sizeof(int)) };
fill(&a); // <= заполняем
check(a); // <= проверяем что заполнили
printf("%d", a.data[0]); // <= UaF :(
}
```
Вот абсолютно нормальный код, который с появлением деструктора стал крешится. Потому что в check передаётся копия структура, для которой при выходе из check вызывается деструктор и сносится data.
Чувак, серъёзно, что тебе мешает взять С++98 пожить с деструкторами и понять что в C они будут бесполезны, более того опасны? Я как будто с первокуром общаюсь.
пиздец.. ты вообще пишешь какую-то хуйню про другое. Ты или перечитай внимательно, что обсуждаем или уж не лезь тогда. А то повылезают из серии дишь бы что-то сказать, даже не пытаясь понять о чем речь. Ты еще как умник выше скажи про реализацию на языке умных указателей.
Я пишу именно то что надо. То что ты путаешь defer и деструктор и выдаёшь одно за другое - чисто твоя проблема.
Если нужен defer в си - юзай
#define DEFER(f) __attribute__((cleanup(f)))
Ну и
DEFER(string_destroy) char ×huy = string_new();
А вот для умных деструкторов надо думать о передаче владения, а там уже растом тянет и std::move
>А вот для умных деструкторов
Чем умнее язык, тем тупее программист. А си не для дебилов. Поэтому умного говна и деструкторов в частности не будет.
Так и туалетная бумага для дебилов. Иначе зачем тебе голова и руки, с такими высказываниями-то?
Проблема современной цивилизации в толерастии. Тупому быдлу внушают, что все люди одинаковые, равны. В результате, дебилы лезут в треды умных считая себя такими же и кукарекают "то не так, это не так", не понимая, что это только от их тупости. Но указать некому, толерастия же.
Два чаю. Вот пример, когда человек просто хотел сделать сигнатуру чуть более правильной, добавив const на указатель, который и так не должен быть изменён: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2526.htm
Оказалось, что это breaking, потому что компиляторы начали бы генерить предупреждения, а вендоры считают новые варнинги (даже семантически верные, даже не ошибка компиляции) ломающим изменением: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2565.pdf
Правильно это или нет: хз, тут это философский вопрос
Все сводится к байтовым массивам. Все байты можно переписать.
>Правильно это или нет: хз, тут это философский вопрос
Правильно. Библиотека существует для пользователей, это не игрушка её разработчиков, которой можно вертеть как захочешь. Разработчик должен думать не о себе, а о пользователях. Если его изменения будут поводом высирания кучи варнингов где их раньше не было, это головная боль пользователям, поэтому так делать не надо. А свои "ну такжы лучшы!" можешь в анус себе засунуть, это типичный лепет тупых эгоцентричных малолеток.
Винда сосёт, переходи на линупс или бздю. Привычная для винды кодировка - их собственная, все одно используют, а винда как всегда.
Пробовал гуглировать, но либо нахожу таки код на крестах, либо какие-то демки 1989 года под ДОС, либо нихуя, так как попробуй нагуглить что-то с просто символом «C». Хотелось бы чего-то современного, с ECS, дата ориентед дизайном, Vulcan/Metal хотя сейчас подумал что там наверное апи уже под плюсы/обжективные плюсы минимум. Выручай анон.
Russian_Russia.1251
берешь SDL2 и гуглишь
Так это ты в коносли chcp должен менять
Их несколько там разный набор
https://www.onlinegdb.com/edit/S1gOeSa6hv
Тут могут быть объёбы?
Чего я хотел этим добиться: по состоянию флага нужна подмена символа, входящего в массив строк, для поиска по новому - подменному значению в строке.
Реализовал как мог.
Беда вот какая: как только отработает этот код, следующая за ним функция (работающая с джи-сон) виснет, вешая весь цикл.
Ещё есть либа cJSON, которая используется для пакинга \ парсинга джи-сон строки: https://github.com/DaveGamble/cJSON
Но там вобще мрак и я не знаю как её проверить.
Короче на Гите в awesome C есть ссылки на ресурсы. Но я знаю один ресурс в котором объясняют на пряниках всё про векторы и так далее. Но там очень тяжело. Позже скину.
Как я рад что был прав на счёт CS50, такой раковый вброс. Они даже код писать не могут, более того учат своих студентиков писать некачественный код с умершими конструкциями которые никто не использует. Кому нужен do while в 2021? Ну если только для макросов каких нибудь и то не знаю, не использовал.
Ты не тролишь случайно?
Вот что я напилил
https://www.ideone.com/m00C2E
Язык Си требует много дисциплины, фокусировки, ответственный подход и абсолютную волю.
Недурно.
https://www.ideone.com/Q2gKlk
Ну короче там есть ячейки памяти, каждый спецификатор выделяет определенную память согласно размеру типа. Если int 4 байта, если вставишь вместо int - long размером 8, то выведется половина, те 4 байта вместо 8. Если тип меньше спецификатора (поменяем long и int местами) то одна половина памяти будет просто нулями, а вторая значением которое тебе нужно вывести. Но есть проблема, незанятое пространство из первого спец. перенесется на второй соседний спец. если ты его туда поставишь. Либо он просто останется в памяти и тут UB.
Если совсем педантичный ответ дать, то смотри соглашения о вызове функций и то, как там реализован vararg. Например, вот выдержка из SystemV x64 ABI (стандартный линуксовый):
>The prologue of a function taking a variable argument list and known to call the macro va_start is expected to save the argument registers to the register save area
То есть у тебя копируются в память регистры и va_arg просто шагает по памяти. Указал va_arg(args, int)? Шагнули на столько-то байт в памяти. va_arg(args, double)? Шагнули на столько-то.
Если выводим signed char = 1 как %hd, то будет
|00000000| + |00000001|
Просто продление до нужного спецификатора.
Если signed short = 1 как %hhd и потом еще один %hhd
То значение в памяти разделится на два?
|00000000| |00000001| и будет выведено 0 и 1? А до второй переменной дело даже не дойдет. Ведь будет шагать от начала числа по заданному кол-ву байт. Что-то в онлайн компиляторе проверил, все равно все верно выводит.
Правильно понял?
Тогда почему, когда все так понятно в теории на практике:
int main(void)
{
signed short i = 1;
signed char j = 2;
printf("%hhd %hhd\n", i, j);
return 0;
}
Дает 1, 2 на выходе?
Судя по стандарту va_args промоутит все до инта
То есть реально в твоем примере ты вызываешь как бы
printf(const char*, (int)i, (int)j)
Да, точно меньше инта ради скорости промоутится, это понял. Но тогда с лонгом и интом пример должен сработать.
int main(void)
{
int n1 = 1;
long n2 = 2;
printf("%zd %zd %d %d\n", sizeof(int), sizeof(long), n2, n1);
return 0;
}
Вывод: 4 8 2 1, инт в два раза короче лонга, но когда подсовываем лонг и говорим читать как инт и затем еще инт он похоже читает с конца, а не с начала и нигде не спотыкается. Читал просто в учебнике как все это происходит, но даются две версии разные, в одной читается с конца применяя modulus или просто отбрасывая лишнюю часть, если в двоичной системе смотреть, а в другой (там где объясняется UB) наоборот говорится, что все стартует с начала по кол-ву байту соответствующему спецификатору. Не понимаю, в итоге компилятор то понимает, что от него хотят, то не понимает.
>инт он похоже читает с конца
Ну так ты запускаешь скорее всего на x64 архитектуре с Little-endian.
Попробуй с большими числами, не 1 а какое нибудь 0x13579246
>Не понимаю, в итоге компилятор то понимает, что от него хотят, то не понимает.
А это в принципе неважно, потому что раз у тебя спецификаторы не соответствуют переданным аргументам, у тебя UB, а при UB компилятор не обязан ничего понимать.
Так что то что ты исследуешь, это не какое то истинное свойство языка, а просто стечение обстоятельств, как это работает на каком то одном компьютере с каким то одним компилятором с каким то набором флагов компиляции.
Понял, спасибо. Как я понял, операция modulus точно происходит при конвертировании типов, но необязательно при спецификаторах форматов в printf, тут уже зависит от архитекторы и может быть по-разному. Лучше UB не делать играясь со спецификаторами и все делать вне printf с помощью арифметики. Я думал это как-то можно понять как пресловутый integer overflow, который вроде как ошибка, но в рамках логики.
Интеловский крестокомпилятор вроде оптимизирует. Правда, если у тебя амуда, то соснул, но есть кое какие оптимизации и для неинтелов.
Параметры уже Инта расширяются до Инта при вызове: integer promotion.
Для %d long ты должен был получить предупреждение.
https://en.cppreference.com/w/cpp/compiler_support
Вообще ничего не дает в этом плане. Ну будет у тебя [esp+1], [esp+3] вместо [esp+4], [esp+8]
А в куче как?
Дядям в комитете нужно менеджить главный язык программирования этого чёртового шарика, который должен транслироваться в опкоды для всего: начиная от суперкомпьютера и заканчивая твоим вибратором. С такой ответсвтвенностью люди становятся оочень консервативными и действуют по принципу: "работает - не трогай".
Ууу, прям херои. А как же тогда с++ справился, а кода ведь на нем в разы больше.
>с++ справился, а кода ведь на нем в разы больше
Бля, школьник, пиздуй тралить в другом месте.
>открой сорцы хрома и посчитай
Всё, в цирк можно не ходить целый год. Твоего представления достаточно.
Лол, долбоеб, дяди из комитета еще 31 год назад всех хардварщиков нахуй послали. Они нихуя не делают, только иногда собираются на свои сходочки и отклоняют предложения людей не входящих в СОВЕТ.
ллвм
Погоди разве хром не перешел на Го?
Прослезился, это легендарный пост.
Именно поэтому сишка еще не растеклась в то бесформенное говно, в которое превратился соседний язык. Вон давеча в комитет притаскивали замыкания с маллоком внутри, это ж где я им маллок возьму, когда у меня на МК памяти два килобайта?
Никто и нигде последние лет 15 не использует сишку на мк, сдохнут легаси станки сдохнет и сишка. Вместе со своим профнепригодным комитетом. Ну а если ты на полном серьезе отрицаешь что комитет хуево справляется со своей работой то ты долбоеб
> Никто и нигде последние лет 15 не использует сишку на мк, сдохнут легаси станки сдохнет и сишка.
Сам работаешь? А что тогда по-твоему используют? Трансо раст?
Толсто.
в юнет-фактори 18+ проста((((
Я твоим потоком сознания чуть не подавился, но выстрелю на удачу. Я подобное высирал, когда не знал про little/big endian
Нет, sizeof тебе не вернет размер адресного регистра целевой архиктуры. Просто в любых операциях компилятор подставляет константу либо вычисление по стеку адреса нулевого элемента.
или устроиться по сабжу ага, правда все равно творчества будет не хватать
А кто-то сомневается?
strcmp
Конечно есть нюансы, такие как в разных локалях может быть другой порядок букв в каких нибудь европейских языках
Или например если ты хочешь не лексикографический, а натуральный порядок, как в папках, чтобы file15 шел после file2.
Спасибо
Привет, аноны. Так вышло, что мне нужно так скажем распарсить строку. Вот пример
на вход дается строка CD , мне нужно чтобы что-то запустилось, если на вход будет дана CD и еще что-то. Например так
if ( strcmp(line, "CD") == 0 )){
printf("odin")
if (strcmp(line, "CD + пробел иные символы") == 0)){
printf("dwa");
как мне это сделать? вот пример пишу CD - просто переходит в домашний каталог и все
пишу CD Desktop/Folder/ перейдет в соотв. место
Помогите, пожалуйста, уж силы иссякли ебаться с этим.
Если на вход идёт строка, то оно разве разбивает по пробелу ? То бишь если на вход CD, то это 2 символа, а если test, то это уже 4, но если cd test , то как выцепить инфу после пробела ?
Я просто к тому спрашиваю, что мне надо обрабатывать текст после предполагаемой команды, например чтобы разные настройки доступа менять и тд(пишу терминал)
argv изкоропки разбивает все аргументы, расспличенные одним и более пробелом
Нулевой индекс включает в себя вызов программы e.g. ./a.out
Зачем тебе сырые строки ковырять?
Говорю же, терминал надо написать, а в нем очевидно что ввод строки, на вход аргументами программы это не сделать, ведь он сделает 1 команду и все, а надо обрабатывать динамически. Если я сделаю функцию, которая принимает строку с стандартного входа как char *list[] , то обращаясь к скажем индексу 1 , разве я получу символы до первого пробела , ведь он отдаст первый символ и все? Понимаю, что это ебля ещё та, но надо.
Здарова, байтоебы, бля ну си конечно заебись язык ничего лишнего, да и ничего нужного, аля сам ебись придумывая связные списки под каждый пук. Короче си - говно без задач в современном мире, если только вы не пилите ядро линукс или драйвера, хотя и драйвера уже на с++ пишутся.
удаляйте тред.
Лол, я на си в свое время много писал и много чего использовал, но ты сам то видел эти "готовые" либы? Это хуйня полная и неудобная.
Да и вообще какой смысл писать на си сейчас? Быстрее чем с++ это точно не будет, при разумном использовании последнего. А вот скорость написания, читабельность и емкость кода будет намного намного выше.
Приведение типов это насколько затратная операция? Если я впишу условное (short int) x - y это скажется?
>Потому что типа int на конкретно моей платформе самый быстрый и он соптимизировал
Да, размер инта зависит от платформы, но это всегда самый оптимальный тип.
А почему, что есть приведение типов, что его нет - код один и тот же?
компилер знает что делать и сука делает это
ctype.h используй
Если я правильно понимаю то у тебя идентичный код. Ведь результат все равно скастится к типу возврата.
Не пробовал готовые либы искать? Curses там
Может быть тебе подключить питон и вызывать его...
>Говорю же, терминал надо написать,
В смысле?
Получил строку и пользуешь функцию strchr(mystr, " ");
Вернёт указатель на первый пробел или NULL, если пробела нет.
Или создай массив указателей и разбивай строку на токены в цикле.
Пиздец вопросы. Пиздец ответы. Убить вас всех нахуй. Или отправить на лесоповал озеленять вырубленные площади.
main() {..}
Законно ли писать поверх buf + max в таком случае? Я думал, что что-то вроде сигсегв будет, там же за границу .bss пишется.
+ sizeof(int), разумеется
Почему для того чтобы из буфера не читался \n в условиях проверки стоит
while(getchar() != '\n')
continue;
Почему НЕ равно? Потому что оно в любом случае перейдёт в тру, т.к ты ввод нажимаешь, и вместо continue пойдёт проверка следущего символа буфера, т.е \n
*в false. То есть в любом случае contine не происходит, а происходит итерация внешнего цикла с проверкой оставшегося \n
Мне нужно скомпилить вот это дело, желательно без установки и настройки тонн софта и докачки библиотек.
https://github.com/pmaillot/X32-Behringer/blob/master/XAir_Command.c
GCC уже посоветовали, но я нихуя не понимаю как он настраивается и обязательно ли качать всю хуйню по нему или есть просто компиллер.
Помоги анон.
в цикле проверяешь разницу текущего времени с временем отрисовки предыдущего кадра и если больше нужного значения рисуешь кадр
Такое прокатывало в DOS, но сейчас операционки многозадачные. Загрузка проца 100% без причины это говнокод.
это самый простой рабочий вариант а он студент
сейчас процессоры по 6 ядер имеют так что никто не заметит
Надо получить RPM_A.
Если можно, то в двух вариантах: 1) кратко пошагово; 2) в одно действие.
Спасибо анон, но нихрена в итоге не получилось все равно. Для компиляции еще надо собрать библиотеку, этого я не осилил.
Написал разработчику с просьбой скомпилять и он скомпилил.
Написал для интереса. Говнокод или все хорошо?
Патч с реализацией мягкой защиты Active(file), с тремя крутилками. В настройках по умолчанию побочек не выявлено, в отличие от всех других вариантов. По умолчанию жесткая защита отключена, а мягкая соответственно действует весьма мягко, но ощутимо положительно при своппинге.
https://github.com/hakavlad/le9-patch/blob/main/le9aa1-5.10.patch
Пишу протокол обмена с железякой ARM. Объявляю enum cmd_type_t наподобие CMD_0001 = 0x0001U и т.п. несколько кодов команд. Компилятор для железки (GCC) успешно делает поле кода команд двухбайтовым, а такой же точно код на Винде (Qt) делает его четырехбайтовым. Запись CMD_0001 = (uint16_t)0x0001 не помогает. Упаковывание структуры pragma pack(push,1) тоже не дает эффекта.
Как заставить компилятор под комп сделать правильную разрядность cmd_type_t - два байта?
Спасибо
enum достаточно большой, чтобы вместить используемые в нём числа, плюс компилятор можно попросить упаковать его поплотнее какими-нибудь __attribute__ ((__packed__)) или -fshort-enums если загуглишь `sizeof enum`, первая же ссылка ведёт на stack overflow, где это всё написано
>>889658
Твой буффер будет расположен в сегменте данных.
Поэтому сигнал может быть сгенерирован если выйдешь за границу виртуальной страницы. Но пока не перешагнёшь границу страницы, исключения не будет.
БОЛЕЕ ТОГО! В сегмент данных попадают переменные из разных исходников. Т.ч. граница сегмента данных может далеко - при выходе за границы массивы ты просто прочитаешь или перезапишешь глобальные или статические переменные, обхявленные в других файлах.
RPM_R = ( ((n - 1) x f x m x 60) / (COUNT x poles) );
y = ( (n - 1) / (2 x poles) );
RPM_A = RPM_R x y;
Надо с помощью операций с битами вывести следующие значения: 0x00 => 3, 0x08 => 5, 0x10 => 7, 0x18 => 9.
Т.е. если в байте третий и четвёртый биты равны 0x08, то надо вывести 5 и т.д.
Понятно, что какой-нибудь switch-case и маска 0x18 решили бы проблему.
Но надо вычленить это именно битовыми операциями.
Хелпуйте, парни.
Начни с функции, которая реализует сложение через битовые операции.
Тебе всякой чуши поотвечали. В языке никаких сигналов нет. А писать за пределы все равно незаконно.
Ты видишь последовательные комбинации битов, и у тебя не загорелась идея как превратить их в последовательность индексов от 0?
>А писать за пределы все равно незаконно.
Наоборот. Си - свободный язык, позволяет очень много всего делать, и так и надо. Можно всё, а делать или не далеть решать только тебе. Язык не запрещает, не сковывает руки, а наоборот помогает делать что угодно. И из за этого он прозрачен, что ты пишешь, то и получаешь. Ты видишь что ты пишешь, в отличие от других параш, где язык является черным ящиком, хуй знает что там под капотом реально происходит.
Странная рекомендация.
UB - все что не описано в стандарте языка.
Ты же рекомендуешь почитать об UB в стандарте. Как-то странно.
Продолжаю искать: DO-178C.PDF (A и В тоже подойдут), DO-254.PDF, DO-385.PDF (всё ещё некритично), ARINC-653.PDF.
Без смс и регистрации!
read.pudn.com/downloads133/doc/565041/ANSI_ISO%2B9899-1990%2B[1].pdf
Ну открой ты стандарт чтобы чушь не пороть. Ситуации при которых возникает UB описаны именно в стандарте.
> Ситуации при которых возникает UB описаны именно в стандарте.
Ты даун? Ты хоть раз читал стандарт? Тебе пояснили, что ситуации при которых UB происходит наоборот в стандарте не описаны.
Ты наркоман? Зашел потроллить тупостью? Ты хоть раз открывал стандарт? Там описаны ВСЕ ситуации при которых происходит UB.
Спасибо, пока что робит.
И что? Следуя твоим дебильным мемасам, свобода это и есть UB. Когда можно делать всё, значит предскащзать действия невозможно. И тут нет проблемы. Поедсказать невозможно только со стороны, например дебил как ты или компилятор, который вообще машина, не сможет предсказать, но это и не нужно. Главное, что умный человек, либо не будет так делать, либо будет когда ему это нужно. Главное есть возможность, это всегда плюс. Важно что язык предсказуем, ты пишешь код заранее зная что он делает, буквально.
А вот всякая пидарасня из других говноязыков программирует наоборот. Сначала "предполагает" от балды, что "наверное" код будет делать надо, но не факт, ибо неизвестно. Так что сначала надо запустить и посмотреть что выйдет. Посмотрел, если "сработало", ну окей, если "не сработало", продолжает гадать на кофейной гуще пока наконец не "сработает".
Программирование на си это техника - выдача устройству четких команд на исполнение. Ты сначала должен знать работу устройства и поддерживаемые команда, а потом просто перечисляешь что делать и всё четко исполняется.
"Программирование" же на другом говне - как бюрокрания: "Господин язык, мне тут надо сделать это, я вроде составил прошение по форме (но неуверен), пожалуйста рассмотрите, если у вас будет время и желание, а я холоп, человек маленький, дальше не моего ума дело, подожду решения господина, если что не так, перепишу и подам прошение снова и снова, пока вас не устроит. С низким поклоном, макака Чухан Объебосов".
И вот таких чуханов объебосов, из говна залетевших в си-тред видно сразу. Си - четкий язык, поэтому программист на си всегда знает что делает, ведь есть доки. А залетные чуханы делают наоборот, пишут на авось от балды примерно так:
>char a[NN], b[NN]
>"введите 1 строку:", a
>"введите 2 строку:", b
>if (a == b) "строки одинаковые"
Потом запускают, не понимают результата, и бегут в тред с вопросами "а пачиму ниработаит?". Потому что привыкли писать хуету, сами не зная какую, чисто интуитивно, на авось "может прокатит". И вот этот вот пиздец эти ебланы считают протраммированием.
В си-то всё четко, прежде чем писать, читаешь доку, и заранее знаешь что получишь. Вообще не вопрос, проблемы не существует. А у хуесосов, в говне вместо языков, никакой ясности нет, язык - черный ящик, делает хуй знает что, вот и "программисты" тоже пишут хуй знает что, на удачу.
И что? Следуя твоим дебильным мемасам, свобода это и есть UB. Когда можно делать всё, значит предскащзать действия невозможно. И тут нет проблемы. Поедсказать невозможно только со стороны, например дебил как ты или компилятор, который вообще машина, не сможет предсказать, но это и не нужно. Главное, что умный человек, либо не будет так делать, либо будет когда ему это нужно. Главное есть возможность, это всегда плюс. Важно что язык предсказуем, ты пишешь код заранее зная что он делает, буквально.
А вот всякая пидарасня из других говноязыков программирует наоборот. Сначала "предполагает" от балды, что "наверное" код будет делать надо, но не факт, ибо неизвестно. Так что сначала надо запустить и посмотреть что выйдет. Посмотрел, если "сработало", ну окей, если "не сработало", продолжает гадать на кофейной гуще пока наконец не "сработает".
Программирование на си это техника - выдача устройству четких команд на исполнение. Ты сначала должен знать работу устройства и поддерживаемые команда, а потом просто перечисляешь что делать и всё четко исполняется.
"Программирование" же на другом говне - как бюрокрания: "Господин язык, мне тут надо сделать это, я вроде составил прошение по форме (но неуверен), пожалуйста рассмотрите, если у вас будет время и желание, а я холоп, человек маленький, дальше не моего ума дело, подожду решения господина, если что не так, перепишу и подам прошение снова и снова, пока вас не устроит. С низким поклоном, макака Чухан Объебосов".
И вот таких чуханов объебосов, из говна залетевших в си-тред видно сразу. Си - четкий язык, поэтому программист на си всегда знает что делает, ведь есть доки. А залетные чуханы делают наоборот, пишут на авось от балды примерно так:
>char a[NN], b[NN]
>"введите 1 строку:", a
>"введите 2 строку:", b
>if (a == b) "строки одинаковые"
Потом запускают, не понимают результата, и бегут в тред с вопросами "а пачиму ниработаит?". Потому что привыкли писать хуету, сами не зная какую, чисто интуитивно, на авось "может прокатит". И вот этот вот пиздец эти ебланы считают протраммированием.
В си-то всё четко, прежде чем писать, читаешь доку, и заранее знаешь что получишь. Вообще не вопрос, проблемы не существует. А у хуесосов, в говне вместо языков, никакой ясности нет, язык - черный ящик, делает хуй знает что, вот и "программисты" тоже пишут хуй знает что, на удачу.
>пук
Дальше не читал. Ты не достоит программировать на Си. Все изящество программиста на Си в том, чтобы читать раздел J2 в стандарте языка, и избегать всяческого UB по коду. Ты не имеешь права с такими мыслями писать код на Си. Ты меня слышишь? Не имеешь права!!
>Дальше не читал.
Я и говорю. Быдло макаки залетевшие из своей параши в си - читать не приучены, не читают они, а значит не знают что пишут, тогда как программист на си - наоборот, сначала читает и уже знает, а только потом пишет. Или, еще яснее: если не знает, не пишет ничего, пока не разберется в том, что собственно собирвается напечатать в редактор кода. В си нельзя ебашить непонятный код, в надежде на авось или на "потом докрутить по результату". Это и есть тот самый, настоящий UB, UB головного мозга дебиломакаки, которой в си делать нечего.
Пчел, решил дать шанс твоему шизовысеру.
Так вот, язык Си не имеет никакого отношения ни к устройству, ни к его командам. Язык - это лингвистический конструкт. В языке Си нет никаких .bss секций, page faults и прочего. Зато в языке четко сказано что запись за пределами массива - UB, то есть лажа.
Нету, уфы
>Си не имеет никакого отношения ни к устройству, ни к его командам. Язык - это лингвистический конструкт
Как в воду глядел. Как раз об этом размышлял, но писать было лень, а тут ты такой. Поражаюсь себе. То ли я такой умный, то ли глупцы такие предсказуемые. Хоть и отрицаешь голословно, но, по крайней мере, это говорит, что более-менее понял написанное. Уже хорошо. А то я уже привык к ответам уровня пеньков.
Для ясности, начну с терминологии. Будет так: си – «язык (программирования)», соответственно: «программирование», «программисты». Другие языки – «говно», соответственно: «говношлепство», «говношлепы / макаки».
Итак, рассмотрим следующий код:
int a=1;
Говношлепов учат так: «переменная – это ячейка памяти, в которой хранится значение». Определение – гуманитарное, в соответствии с обычным житейским здравым смыслом – философия. Ячейка является сущностью, объектом. Ничего учить не надо, любой человек по дефолту – понимает простую философию на интуитивном уровне. И хорошо, правильно учат, оно так и работает, но только в говне.
А вот в си это не работает, от слова совсем, потому что си – это программирование машины, техника, а вовсе не пиздоблядская гуманитарная философия.
Начнем с того, что переменная в си это не объект, а значит никакая не ячейка. Ячейка имеет защиту, она изолирована стенками. Нельзя из одной ячейки попасть в другую. Если попытаться засунуть в ячейку слишком много, ничего страшного не произойдет, просто часть не влезет и всё. Именно так работает говно, но не си.
Си это машинный интерфейс. Прежде чем написать эту простейшую строчку кода, ты должен понимать как работает железо (процессор+память) и выучить, что переменная это просто место в памяти, никакими «стенками» не защищенное и не ограниченное. Это технические спецификации машины и языка си как её интерфейса. Этому нельзя догадаться философской интуицией – только выучить, заранее читая документацию. Иначе, без этих технических знаний, ты уже крупно обосрался одной этой строчкой.
Ты полном дерьме, по уши, по одной простой причине – гуманитарное говноблядство безопасно. Ты можешь на дваче пиздеть любую хуйню, не зная, заливать в уши лапшу, и максимум тебя просто пошлют и всё. Именно так происходит в говне, Тебе просто либо выдается ошибка, либо получаешь не тот результат. Ничего страшного, просто крутишься как уж на сковородке пока не получишь желаемое. Обычная повседневная жизнь любого быдлана, бытовая философия – суть говношлепства.
А техника, машина – наоборот, очень уязвима. Машина – не автомобиль для быдла, а большой сложный механизм на заводе (компьютер) и пульт управления на всю стену с кучей лампочек, кнопок и рычажков, её интерфейс (язык си). Ты не можешь просто подойти, не изучив, что это за машина, как устроена и работает, как на неё воздействует каждая кнопка, и просто наугад тыкать гуманитарнным способом: «та кнопочка зелененькая, значит можно жать, будет только лучше, а вот та красная, значит лучше не трогать» и так далее. С машиной, любое неверное движение и она просто ломается нахуй. Поэтому говношлепов к машинам не подпускают, сначала требуют выучить всё и сдать экзамен. Иначе еблан первым же действием всё ломает нахуй. Тут не прокатит метод научного тыка как у говношлепов гуманитарных, вторых шансов нет, машина слишком сложная. Даже повторяя косяки, ты ничему не научишься. Только читать документацию заранее, до полного понимания куда ты лезешь.
>Си не имеет никакого отношения ни к устройству, ни к его командам. Язык - это лингвистический конструкт
Как в воду глядел. Как раз об этом размышлял, но писать было лень, а тут ты такой. Поражаюсь себе. То ли я такой умный, то ли глупцы такие предсказуемые. Хоть и отрицаешь голословно, но, по крайней мере, это говорит, что более-менее понял написанное. Уже хорошо. А то я уже привык к ответам уровня пеньков.
Для ясности, начну с терминологии. Будет так: си – «язык (программирования)», соответственно: «программирование», «программисты». Другие языки – «говно», соответственно: «говношлепство», «говношлепы / макаки».
Итак, рассмотрим следующий код:
int a=1;
Говношлепов учат так: «переменная – это ячейка памяти, в которой хранится значение». Определение – гуманитарное, в соответствии с обычным житейским здравым смыслом – философия. Ячейка является сущностью, объектом. Ничего учить не надо, любой человек по дефолту – понимает простую философию на интуитивном уровне. И хорошо, правильно учат, оно так и работает, но только в говне.
А вот в си это не работает, от слова совсем, потому что си – это программирование машины, техника, а вовсе не пиздоблядская гуманитарная философия.
Начнем с того, что переменная в си это не объект, а значит никакая не ячейка. Ячейка имеет защиту, она изолирована стенками. Нельзя из одной ячейки попасть в другую. Если попытаться засунуть в ячейку слишком много, ничего страшного не произойдет, просто часть не влезет и всё. Именно так работает говно, но не си.
Си это машинный интерфейс. Прежде чем написать эту простейшую строчку кода, ты должен понимать как работает железо (процессор+память) и выучить, что переменная это просто место в памяти, никакими «стенками» не защищенное и не ограниченное. Это технические спецификации машины и языка си как её интерфейса. Этому нельзя догадаться философской интуицией – только выучить, заранее читая документацию. Иначе, без этих технических знаний, ты уже крупно обосрался одной этой строчкой.
Ты полном дерьме, по уши, по одной простой причине – гуманитарное говноблядство безопасно. Ты можешь на дваче пиздеть любую хуйню, не зная, заливать в уши лапшу, и максимум тебя просто пошлют и всё. Именно так происходит в говне, Тебе просто либо выдается ошибка, либо получаешь не тот результат. Ничего страшного, просто крутишься как уж на сковородке пока не получишь желаемое. Обычная повседневная жизнь любого быдлана, бытовая философия – суть говношлепства.
А техника, машина – наоборот, очень уязвима. Машина – не автомобиль для быдла, а большой сложный механизм на заводе (компьютер) и пульт управления на всю стену с кучей лампочек, кнопок и рычажков, её интерфейс (язык си). Ты не можешь просто подойти, не изучив, что это за машина, как устроена и работает, как на неё воздействует каждая кнопка, и просто наугад тыкать гуманитарнным способом: «та кнопочка зелененькая, значит можно жать, будет только лучше, а вот та красная, значит лучше не трогать» и так далее. С машиной, любое неверное движение и она просто ломается нахуй. Поэтому говношлепов к машинам не подпускают, сначала требуют выучить всё и сдать экзамен. Иначе еблан первым же действием всё ломает нахуй. Тут не прокатит метод научного тыка как у говношлепов гуманитарных, вторых шансов нет, машина слишком сложная. Даже повторяя косяки, ты ничему не научишься. Только читать документацию заранее, до полного понимания куда ты лезешь.
Пиздец шиза. Не пиши мне больше.
Интересно что будет когда этот шиз научится включать оптимизацию в компиляторе
Потому что поняли что писать сложную логику, в которой друг с другом взаимодействуют десятки пользовательских сущностей, на процедуропараше — пустая трата времени.
Пока что не знаю ООП, просто не понимаю почему вьебали это если в Си есть всё. Чем обосновано хуй знает.
Школьнексон, плиз. ООП — это не о языке. Это концепция. И эта концепция старше чем езык погромирования це. Ты можешь на каком угодно языке писать в ООП стиле. И ты скорее всего и пишешь, просто не знаешь об этом.
А что тебе интересно?
Пиши все что относится к системщине и твоей душе угодно. Это самый простой вариант.
Например?
Я в этом вашем "системном" не шарю от слова совсем. На пайтоне я пишу боты, парсеры, и веб на джанго/фласке. Приведи примеы, пожалуйста
Python, Nginx, Linux.
Спасибо. А вот ещё назрел вопрос: что тогда делает sys_brk(addr)? В гуглах несколько противоречивая информация, в мануале же написано, что по успешному выполнению конец ДС становится равным addr, т.е. простая аллокация/деаллокация для сегмента. Типа еще линкер рожает символ _end, указывающий на конец сегмента; он виден в отладчике, но в рантайме простой программы _end всегда равен 0x00.
Одним словом, что определяет начало и размер сегмента?
Вообще я так понял, что brk() просто проверяет лежит ли addr в пределах сегмента данных, если - нет, то ENOMEM
Сегмент данных начинается в _end, а заканчивается там, где скажет brk.
> _end всегда равен 0x00.
extern _end[];
ебать ты меня затролил, float* конечно
По указателю лежат только байты. "Какие там данные" это абстракции у тебя в воображении. Язык лишь имеет сахарок прочитать столько байт, сколько ты укажешь (типом), так что сам должен знать сколько тебе надо.
Смотрят кто и куда обращается и на основании своего опыта подобных явлений делают предположения, которые потом проверяют. Так же смотрят на сами данные. Опытные кулхацкеры просто глядя на хекс-дамп могут сказать что это такое, лишь по внешнему виду чисел. Изучаешь все аспекты программ и с обытом набиваешь глаз.
Любым дебагером. Из них самая навороченная йоба это IDA.
Привет, аноны, извиняюсь за совсем уж даунский вопрос. Но
Как грубо говоря распаковать указатель на чар?
Имеется
char c[128];
char test
нужно содержимое test положить в c , strcpy(c, *test) так или иначе не сработало.
memcpy(с, &test, sizeof test)
#define InitArr(dst, src) memcpy(dst, src, sizeof(dst))
Почему segmentation fault?
Тестирую, что быстрее, копировать сначала по первому адресу двумерного массива, или по второму?
copyij будет копировать аргументы или передовать память из рук в руки?
Сколь большой массив можно объявить?
Ты копируешь аргументы через stack, два массива по 2048 * 2048 байт(~8 миллионов байт), вполне вероятно ты вываливаешься из-за этого в SIGSEGV.
А вот если бы ты имел операционную систему с дефрагментацией стэка, то думаю бы с бы такой бы проблемой бы ты бы не бы столкнулся бы.
>>899976
Яхуйзнает, может так:
>int8_t ××array = (int8_t ××)malloc(sizeof(int8_t ×) × LEN);
>for (size_t i = 0; i < LEN; ++i) {
> array = (int8_t ×)malloc(sizeof(int8_t) × LEN);
>}
Хотя я не уверен до самого конечного конца...
Я вспомнил что надо именно так на плюсах маллокать
Это тупой рофл одного шизика, который мечтает дефрагментировать стэк.
Пости код в моноширинном шрифте
Нет, но у популярных пакетов обычно есть возможность писать расширения на Си.
Тип + add, - sub, ^ pow и тд.
Алгорит действий вроде понимаю, но понять не могу, какие функции использовать, чтоб разделить слова и цифры на входе
strtol/strtod распарсит столько символов, сколько сможет, и отдаст тебе указатель туда, где число закончилось. Подумай об этом.
а зачем мне заглавная?
Мне надо, чтоб оно считывало к примеру так:
1 2 add =
или так
7 0.5 add 2.2 0.2 sub mul
Да и не особо понимаю, как я потом числа анси, могу использовать в расчетах.
Ты говоришь о распознавании текстового синтаксиса. Либо пишешь парсер сам, либо используй готовые интерпретаторы скриптов. К языку программирования это не относится и быть в нём не может. Это относится к написанию компилятора/интерпретатора языка.
#include <stdio.h>
void main(void)
{
char, name[50];
FILE *in;
printf("Enter file name:");
scanf("%s", name);
if((in=fopen(name, "r"))==NULL)
printf("Error open %s", name);
else
while(!feof(in))
{
ch=getc(in);
putchar(ch);
}
}
char res;
char word[SIZE];
успешная запись в массив...
res = spaces(word, SIZE);
...
char spaces(char st, int n)
{
printf("Выполнен вход в space()");
char ch;
int i;
printf("%c", *st);
for(i = 0;i < n || st == '\0';i++)
{
if(st == ' ')
{
ch = st;
}
}
return ch;
}
Разметка слетела, звёздочки на res, char st, char ch
*strchr в первоначальной версии не использовалась
Это копия, сохраненная 29 апреля 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.