Это копия, сохраненная 16 июля 2019 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ или 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 (драфт)
- 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 помогает читать сложные сишные декларации.
Прошлые треды:
- №42: https://arhivach.ng/thread/438066/
- №43: https://arhivach.ng/thread/441686/
- №44: https://arhivach.ng/thread/444396/ >>1383604 (OP)
В случае с файлом на диске буферизация нужна, чтоб диск не дергался за каждым putchar. Вывод копится в оперативке и большими кусками сливается на диск. А вот когда это консоль, то молчать, пока не накопится 4 килобайта текста, неприемлемо, т.к. на твои глаза инфа должна поступать сразу для нормальной интерактивной работы. Можно было бы немедленно выводить каждую букву, но это, хоть и не диск, тоже тормозит работу, поскольку системный вызов для вывода данных куда-либо за пределы оперативки процесса (в твой терминал, который есть другой процесс) - более сложная процедура, чем просто отложить в буфер. Компромиссное решение - выводить каждую строчку, то есть делать fflush по каждом \n. Но иногда программа хочет вывести строчку, не "нажимая ENTER" в конце, например, чтоб оставить мигающий курсор за двоеточием, и ты красиво впечатал свое имя. Логично, что "Type your name: _" должно отобразиться сразу, и для такого распространенного случая предусмотрен дополнительный вызов fflush при входе в scanf.
>>1393388
хз, что кроме K&R посоветовать... Вкатывался после Паскаля на уровне мегамейнов (дополнительные процедуры не использовал почти).
все правила языка и функции маленькой стандартной библиотеки - нехуй делать. Кодить на уровне разработчика операционных систем, создавая макросами абстракции помудренее C++ - искусство, которому можно посвятить десятилетия.
Было бы учить чего, вполне реально. Вот насчет С++ можно подумать.
Пытаюсь отправить имя файла по сокету.
>char *filename = malloc(header.nSize+1);
>recv(sock, filename, sizeof(filename), 0);
>printf("Filename:%s", filename);
Отправляю: hello.exe\x00
Выводит: hello.exPо
char ★string;
char ★★tokens;
Обем память выделяется динамически.
tokens[0] указывает на начало string. Если я делаю free(tokens), то не освободится ли случаем память, занятая под string? Возникло подозрение, что именно так и происходит, поскольку на освобождении string после освобождения tokens программа падает.
> то не освободится ли случаем память, занятая под string
Нет, освобождается только то, и только столько, сколько было выделено соответствующим malloc(). Т.е., если ты сделал string = malloc(strlen("dupa") + 1), то free() освободит только те пять байтов, которые выделены, и только тогда, когда аргумент указывает на начало блока (т.е., free(string + 1) нельзя).
Другое дело, если бы у тебя было tokens = malloc(num_tokens ★ sizeof(★tokens) + string_table_length); и string = (char ★) &tokens[num_tokens] (т.е., после массива токенов начинается таблица строк). Тут ты выделил память под обе сущности одним блоком, одним же free() и должен освобождать, а free(string) будет багом.
> sizeof(filename)
sizeof(char *) это константа, в 64-битной системе оно равно 8. Ты получаешь 8 валидных байтов и мусор. Как думаешь, может быть, здесь есть какая-то связь?
Хм, спасибо. Ладно, пусть пока память подтекает, не критично.
sizeof исправил, указал просто 9.
вывел: hello.exe
Причем если я не использую malloc,
>char filename[header.nSize];
все выводится нормально.
Попробовал в malloc тоже передать просто 9, результат тот же самый - выводит мусор.
Охуеть, правда? Размер массива равен размеру массива, а размер указателя - размеру указателя!
Ладно я разобрался, вот еще вопрос.
После загрузки я должен выполнить файл (CreateProcess()) передав ему 1 аргумент: GetModuleFileName()
Как я узнал из документации, передать аргументы можно так
>CreateProcess(filename, args)
По документации, тип 1-й переменной должен быть LPCSTR, то есть, как я понимаю, обычный char (тип буфера с именем файла) проканает.
Тип 2-й переменной - LPSTR.
Как раз этот тип возвращает GetModuleFileName согласно документации.
То есть по моим расчётам проканает запустить процесс с типом имени char и аргументом типа LPSTR ?
> CreateProcess(filename, args)
Кто тебе такую хуйню сказал? Там в три раза больше аргументов. И там два способа. Ты можешь сделать либо:
CreateProcess("foo.exe", NULL, остальные аргументы);
либо:
CreateProcess(NULL, "foo.exe arg1 arg2 итд", остальные аргументы);
> LPCSTR
> LPSTR
На самом деле там LPCTSTR и LPTSTR соответственно. Если у тебя не выставлен дефайн UNICODE, то первое const char ∗, второе просто char ∗, но передавать char ∗ (а также всякие массивы char) можно в оба. Если выставлен UNICODE, то это const WCHAR ∗ и WCHAR ∗ соответственно, а для преобразования из char ∗ понадобится временный буфер и MultiByteToWideChar().
> этот тип возвращает GetModuleFileName согласно документации
Он DWORD возвращает, а вот массив из char/WCHAR, который ты ему передаешь, а он заполняет, ты можешь передать и в CreateProcess тоже, да.
>Кто тебе такую хуйню сказал
docs.microsoft.com
Аргументов больше, я знаю, я сократил, зачем мне в примере писать все NULL/0/FALSE ?
>CreateProcess(NULL, "foo.exe arg1")
То есть мне надо будет конкатенацию filename и буфера GetModuleFileName делать ?
А если там будет символ на русском языке, то есть UNICODE, а у меня он не поддерживается, потому что у меня все на обычных char.
В общем надо имя файла из char конвертировать в wchar ?
Ты вообще учил С? Вон в шапке полно книг, за неделю все прочитаешь и глупые вопросы сами собой отпадут.
Есть ли простое правило/формула по представлению/разиминование указателей? Для начала частный случай многомерных массивов.
Спасибо.
>многомерных массивов
Допустим, есть массив a[m][n]. Чтоб нормально использовать указатель за пределами контекста, а не писать a[m*i+j], в функции, например, которая этот массив принимает, надо объявить локальный указатель на последовательность массивов соответствующих размерностей (указать все, кроме старшей, компилятор должен знать ширину шага, а насколько далеко заходить - твоя забота):
void f(int ∗a, int n, int m)
{
int (∗a_)[m] = a;
// вуаля, арифметика индексации автоматизирована, можно обращаться к элементу ij, как a_[j], передавать куда-то указатель на начало i-строки массива, как a, и т.д.
}
>>394023
бля, борда [ i ] схавала, ща пофиксю
>многомерных массивов
Допустим, есть массив a[m][n]. Чтоб нормально использовать указатель за пределами контекста, а не писать a[m*i+j], в функции, например, которая этот массив принимает, надо объявить локальный указатель на последовательность массивов соответствующих размерностей (указать все, кроме старшей, компилятор должен знать ширину шага, а насколько далеко заходить - твоя забота):
void f(int ∗a, int n, int m)
{
int (∗a_)[m] = a;
// вуаля, арифметика индексации автоматизирована, можно обращаться к элементу i j, как a_[ i ][ j ], передавать куда-то указатель на начало i-й строки массива, как a[ i ], и т.д.
}
Не помню точно, о чем шла речь в прошлом треде, но у меня как-то тоже текла память, и я просто дописал вызов malloc_trim(0) после всей содомии с тысячекратными malloc()/free(), и гигабайтов мусора как не бывало. Процесс культурно продолжил жить, уложившись обратно в свои пару мегабайт.
Он не запрашивает, а просто переводит курсор на новую строку и не воспринимает то что я там ввожу??
> То есть мне надо будет конкатенацию filename и буфера GetModuleFileName делать ?
А зачем тебе вообще GetModuleFilename()? Ты себя запускать собрался? Если нужны аргументы командной строки - да, конкатенация, и про кавычки вокруг пути с пробелами не забудь. Если аргументов не передаешь, то просто положи имя исполняемого файла в первый параметр, а командную строку система сама дорисует.
> В общем надо имя файла из char конвертировать в wchar ?
Если нужен русский, а локаль в системе не русская - да, надо конвертировать. Вообще, в 2019 давно надо полностью юникодные программы писать.
Не себя, а передать путь до себя в кач-ве аргумента.
>давно надо
Я бы рад, но вот не очень понимаю даже самые простые вещи.
Где бы почитать о win32api и юникоде.
И там программки скомпилены в .с и .h, я правильно понимаю что .h это хедер и это сделано чтобы удобнее было работать с большим проектом?
Это конечно безусловно полезно и интересно, только вот мне надо всего 1 функцию использовать, как я предполагаю MultiByteToWideChar.
И вот ради нее убиться в чтение и понимание глубинных особенностей работы С с winapi ниахота
Слабовато.
Может просто Hello world.
Пример 1: https://ideone.com/XpUR9T
Отрабатывает идеально, никаких [warning], аргументы передает правильно, файл запускает.
Пример 2: https://ideone.com/2leU66
Все тоже самое за исключением того, что имя я получаю через сокет, отправляю сервером на питоне, кодирую в UTF-16 перед отправкой, что соответствует типу wchar_t.
Error code:2
Что означает файл не найден.
К слову, выводить полученное имя он тоже не выводит, однако вот если имя передать в функцию CreateFileW, файл создает с правильным именем.
> код с ошибкой можно на футболку
void main(void), но можешь вот у анона взять:
>>394821
> Пример 1
> wcsncat
Инстант фэйл. У тебя в буфере мусор, к чему оно там сделает cat, зависит от погоды на Марсе. Алсо, кавычки нужны вокруг имени программы: CreateProcess(NULL, "C:\\Program Files\\1.exe arg1", ...) будет пытаться запустить C:\Program.
> Пример 2
> recv(sock, name, 14, 0);
Инстант фэйл. name указывает в небеса.
Короче, вон там в шапке есть Прата, есть K&R. Прочитай любую, чтобы хотя бы слегка понимать язык, на котором пишешь. Заебал уже.
char *helloworld = "Hello, World!";
fwrite(helloworld, sizeof(helloworld), 1, stdout);
$ ./laba1
Hello, W$
/∗ C sucks! ∗/
Я имел ввиду то, что в современных реалиях С - никчемное говно, требующее дохуя, а дающее нихуя.
C не подлежит оценке.
Понял. И ты тоже понял. Используй либы, будет как на других языках, вплоть до: int main(void) { return tic_tac_toe_from_library(); }. Си в этом плане ничем не отличается от какого-нибудь жаваскрипта, ты можешь писать сам, а можешь скатиться до npm install isOdd ой, у нас же нет npm... к счастью.
Нихуя питонодети ахуели, 250 строк кода и уже мозг закипает. У меня на хеллоуворлды по 2-5к строк уходит. Короче уебывай из треда.
250 это немного особенно если там алгоритм нормальный который не выиграть. я на джс (на жиквери лол) писал в 350+ строк не считая штмл и ксс
в смысле у которого не выиграть, ничья или ты проигрываешь
Кармак смог написать свой чудесный идтек1, а ты обычный вкатчик-неосилятор. Возвращайся на завод с которого ты вылез.
Ну ты сравнил, конечно. Кармака (у которого до идтека за спиной тонны опыта) и обычного Васяна.
Мимо
Именно. Обычным васянам в программировании делать нечего, их там никогда не было, пока не появился быдлоскриптинг, куда они и набежали, по ошибке названный тоже "программированием". Но си это не быдлоскрипт, поэтому отсеивает таких залетушек на ура.
Ну ты крутой.
Когда компьютеры были большие, а программы маленькие...
Ты нереально крут, завидую тебе. Ты их по главам делал, много времени ушло?
Только тупое быдло вместо того, чтобы делать самому слушает чужие саксесс-стори. Да, именно от слова "сак", ты.
Да я только начал, можешь посоветовать для совсем нюфагов К&P нормально или с чего то попроще можно начать?
Ты что дурак конечно нет! Нужно начинать с ассемблера, электроники и устройства компьютера. Пока не понимаешь как работает 086, даже не притрагивайся к си, ну а потом эээ ну короче на кодварс найдешь все отьебись понял
Вот этот дебил всё правильно сказал. Начинать нужно с ассемблера, но не современного под винду, а старого под какой-нибудь спектрум или просто виртуальный процессор, я кажется читал подобную книжку. Тогда и железо и код были просты и понятны, а не засраны хуетой как сейчас, поэтому понять принцип работы компьютера легко и удобно. И это понимание необходимо, без него сразу нахуй в питон с жаюлскриптом можешь следовать
>и железо и код были просты и понятны
Вообще-то чистый х86 реального режима очень простой - достаточно не лезть в ссе и прочее.
Сегменты можно просто игнорировать.
Это была просто жирнота, дебилоид. На самом деле для си нихуя из этого не надо, т.к. это такая же высокоуровневая абстрактная параша, как и любой современный язык для домохозяек. И не надо отправлять людей куда-то, когда ты сам не понимаешь чем отличается скрипт от компилируемой сишки.
Ты разговариваешь с жиром, олигофрен.
Вот ещё такую
Дейтел П.Дж., Дейтел Х.М.
Как программировать на С
вроде в начале общие сведения о компьютерах идут.
Не слишком сложно, для начинающих пойдет?
if(a = 0) ...
Объясните пожалуйста что это за собачья хуйня ?
На C/winsock написана простейшая конструкция называемая клиентом, которая ожидает получения wchar_t массива.
>wchar_t chlen[14];
>recv(sock, (char*)chlen, 14, 0);
На питоне написан сервер который отправляет по сокету массив символов закодированных кодировкой UTF-16, что соответствует wchar_tПруфы: https://docs.microsoft.com/ru-ru/cpp/cpp/char-wchar-t-char16-t-char32-t?view=vs-2019
>s.send(string.encode("UTF-16")
Стандартной функцией prnitf с форматной строкой %ws принятый массив не выводится.
Однако если попытаться создать файл с массивом в качестве имени - файл создается без каких-либо проблем, вообще без проблем, даже если точно такой же файл уже есть, он создает два файла с одинаковыми именами.
При пристальном наблюдении, становится видно что разницу между UTF-16 и UTF-8 в питоне составляет так называемый символ BOM с кодом 65279.
Именно этот символ идет перед всеми остальными в массиве, но никак не отображается, а потому позволяет создать почти полностью похожий по имени файл.
В общем, кто может внести хоть какие-то здравые мысли по этой хуете - прошу помочь.
>BOM
Это для птдоров древний высер микромофта, нормальные люди его не используют, естемтвенго и принтв о нем не знает, чекай первые 2 байта и выводи с стретьего если твой питухоновский сервер зашкварен.
Нет, скажем так проблема вывода далеко не самая главная, что делать с ебучим BOM ?
Мне два одинаковых файла как бы не очень нужны, это конечно прикольно, можно клона какого-нибудь cmd.exe создать, но как вообще можно создать какое-то надежное сообщение между по сокетам между путоном и Си если приключаются вот такие истории ?
И нагуглить нихуя толком по wchar_t в питоне не могу, идея закодировать сама пришла в голову, но судя по работоспособности - идея была плохая.
>можно создать какое-то надежное сообщение между по сокетам между путоном и Си
Потому, что питухон для пидоров и смузихлебов, по дефолту кодировка должна быть указана в протоколе, некоторые текстовые редакторы бом вставляют, смузихлебы даже могут об этом не знать.
>для пидоров и смузихлебов
Месяц назад я бы поспорил.
В протоколе должна быть указана кодировка.
Как енто ?
Вот типа в питоне я делаю .encode(“UTF-16”) это есть указание кодировки, а в Си как ?
А функции виндовс которые заканчиваются на W (для них все и делается) в какой кодировке данные ждут ?
UTF-8/16 ? cp-1251 ? Тысячи их блять.
От чего такая анальная боль
Может ну его нахуй этот питон, смысла нет пытаться выдавить из него что-то годное ?
>UTF-16
Все юзают утф8
>смысла нет пытаться выдавить из него что-то годное
Почему, пусть сервер шлет все в одной кодировке.
То есть если с зашкварного питона я пошлю UTF-8 строку, мне ее на Си помещать так-же в wchar_t ?
А если мне нужно будет конкатенацию сделать с другой строкой типа wchar_t L" ", это возможно будет сделать ?
Функции виндовс кончающиеся на W поймут UTF-8 ?
>будет конкатенацию
Пох, это просто байты, можешь их хоть memcp копировать, проблемы только при выводе на консоль ну и подсчет количества символов.
Пробовал делать сетмоде типа для того чтобы вывести UTF-16 текст.
Не помогло, наверное потому что выводил не wprintf.
То есть если я сделаю сетмод для utf-8, программа и функции winapi запонимают эту кодировку ?
И строки конкатить можно будет ?
>чтобы вывести UTF-16 текст
Ну во первых под виндой ты соснешь, потому что там вывод не юникодовский, нужно сменить кодовою страницу
cmd.exe /k chcp 65001
Это вот по утф8, под утф16 гугли.
>конкатить
Они все ожидают строку заканчивающуюся 0, так что похуй, даже strcat сработает
Речь была о том что нехай пинать на инструмент если руки из жопы. Кармак конечно имел опыт, это не вкатывальщик с завода, при этом кармак и писал на си он так что его код и сейчас выглядит шикарно. А васян вечно будет жаловаться что сложно, непонятно, неочевидно и тд потому что васян создан для завода, ну или жс или питона в лучшем случае. Надо понимать что кресты и си для илиты, для ноулайферов, для тех странных задротов которые непонятно говорят, не ебут тяночек и не мечтают о ящике крепкого пиваса.
> Вообще-то чистый х86 реального режима очень простой
И нахуй никому не нужный. Весь современный софт, включая всякий эмбеддед пишется под плоскую модель памяти, так что ебаться в сегменты нет абсолютно никакого смысла.
>>395353
Во-первых, можно было не думая сделать 'тест'.encode('UTF-16')[2:] , а во-вторых, utf-16le.
>>395365
> Функции виндовс кончающиеся на W поймут UTF-8 ?
Я тебе еще в прошлом треде рассказывал, что ты можешь сделать MultiByteToWideChar(CP_UTF8, ...).
>>395371
> chcp 65001
Нормально работает начиная с десяточки. В старших версиях работает с оговорками, иногда проглатывает текст, иногда WriteConsole просто возвращает ошибку. Лучше так не делать.
Что у тебя не работает? Оно меняет кодировку вводимого и выводимого текста, аналогично SetConsoleCP()/SetConsoleOutputCP(), больше ни на что не влияет. Но консоль винды работает (работала) с UTF-8 плохо, поэтому были проблемы. Решалось нестандартной консолью типа ConEmu.
Насчет конката, я немного не так выразился.
Что совместить получится это понятно.
Приведу пример чтоб ты понял.
Стоит сетмод на UTF-8.
Eсть у меня некая строка
>wchar_r s[2] = L"aA";
Есть полученная из питона сокетом UTF-8 строка.
Мне нужно их совместить и передать допустим в CreateFileW.
Какие могут возникнуть проблемы ?
Как же ты заебал.
#define countof(x) (sizeof(x) / sizeof((x)[0]))
char buffer[1024]
char received_string[сколько-то];
recv(... received_string ... );
const char *arg1 = "yoba";
snprintf(buffer, countof(buffer), "\"%s\" %s", received_string, arg1);
WCHAR wide_buffer[1024];
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1, wide_buffer, countof(wide_buffer));
wide_buffer передаешь в CreateFileW. Не забываешь обработать ошибки snprintf (например, когда оно в буфер не влезло) и MultiByteToWideChar (много причин: не влезло, кривой UTF-8 и т. д.).
Какие нахуй сетмоды, вы ебанулись?
> передаешь в CreateFileW
Ну с тем принтфом в CreateProcess, но суть не меняется и для strcpy/strcat.
Чтобы загрузить последнюю игру -_-
Что ж поделать, у каждого своё предназначение в жизни. Кому-то приходится создавать автопилот для теслы, а кто-то должен вычищать блевотину бомжа с асфальта по утрам или шлёпать сайты на модном фреймворке.
> шлёпать сайты на модном фреймворке.
Так это сложнее. Я пытался освоить верстку или там пых, но у меня мозг переклинило на Си. Да и то, на нем ничего сложнее zakaz_laba_12_4_kurs.c не выходит.
Не в сложности дело. Современное программирование это аналог секретаря-машинистки, делание текстовых документов, а си это программирование компьютера - техника. Между технарем и секретаршей/бухгалтером как бы большая разница, хотя они оба могут делать сложные вещи.
>Современное программирование это аналог секретаря-машинистки, делание текстовых документов, а си это программирование компьютера - техника. Между технарем и секретаршей/бухгалтером как бы большая разница, хотя они оба могут делать сложные вещи.
Полную ерунду говоришь. Питон, пхп сранивать с бухгалтерией, а си с техникой это нонсенс. В си нет ничего такого, что нельзя написать на любом Тьюринг полном языке. Ну есть работа с памяться на низком уровне, но это не нужно для реализации алгоритмов.
Современное программирование ничем не отличается от несовременного. Нужно писать код, который решает задачи.
>работа с памятью на низком уровне
Чё это ваще значит?
>работа с памятью в си))))
Орнул.
Мне кажется что эту мантру повторяют из треда в тред только чудики вкатывальщики, вы откуда это берете? Компиляторы сижки на x86 даже к куче полного доступа не дают. Просто указатели на объекты складывают в лист. Вот это да, низкоуровнево пиздец. Си это сука не низкоуровневый язык, долбоеб. Это такая же каша из абстракций как питончик, который ты ненавидишь лишь потому что в соседнем треде так сказали. Все съеби.
в качестве результата выдаст остаток от деления полученной суммы на размер массива
указателей. Это не самая лучшая функция хэширования, но достаточно лаконичная и
эффективная.
#define HASHSIZE 101
static struct nlist (зв)hashtab[HASHSIZE]; / таблица указателей /
/ hash: получает хэш-код для строки s /
unsigned hash(char (зв)s)
{
unsigned hashval;
for (hashval = 0; (зв)s != '\0'; s++)
hashval =(зв)s + 31 (зв) hashval;
return hashval % HASHSIZE;
}
Что то не могу понять как это работает. Почему умножаем на 31, почему делим на hashsize?
Не делим, а берем остаток. Чтобы результат был в диапазоне от 0 до HASHSIZE-1.
31 особого смысла нести не должно. Функция хэширования по своей природе должна выдавать рандомный ответ, поэтому там часто используют странные магические цифры для дополнительной рандомности
> Что то не могу понять как это работает
Внутри цикла ты "сдвигаешь" умножением текущие биты хэша влево так, чтобы "добавить" биты очередного байта, но не слишком далеко, чтобы не потерять слишком много текущего состояния из-за переполнения. После цикла с помощью % ты приводишь результат к диапазону хэш таблицы.
>>396814
> Почему умножаем на 31, почему делим на hashsize?
> 31 особого смысла нести не должно
HASHSIZE - простое число, чтобы как можно больше битов hashval влияли на вычисляемый индекс (например, если размер таблицы 128, мы бы фактически просто выбросили старшие биты hashval). 31 - простое (или хотя бы взаимно простое с 2sizeof(int) ∗ 8) число, чтобы при переполнении после вычисления 31 ∗ hashval, которое компьютер вычисляет как (31 ∗ hashval) % 2sizeof(int) ∗ 8 отброшенные биты влияли на результат. Поэтому хэш-функция со сдвигом (hashval = (hashval << x) ^ ∗s) хуже.
Спасибо за развёрнутый ответ, но все же не понятно, при взятии остатка ведь может получиться, что у двух разных слов хэш будет одинаков, разве нет?
> у двух разных слов хэш будет одинаков
Конечно. Будет коллизия. Ведь количество возможных слов бесконечно, а количество элементов конечно, и поэтому у тебя там не массив указателей на строки, а массив связанных списков, элементы котрых указывают на строки. Слова с совпадающим хэшем попадают в один и тот же связанный список. Например, у тебя хэш-таблица на 5 элементов, а засунул ты в нее 10 слов, очевидно, что у некоторых слов хэш совпадет, и при их поиске ты будешь гулять по связанному списку, теряя в скорости. И это еще в лучшем случае. С плохой хэш-функцией может случиться так, что все 10 слов попадут в один и тот же элемент таблицы. Именно для уменьшения вероятности такой хуйни в твоей хэш функции используются простые числа. И поэтому самих хэш функций существует дохуя, с разным качеством, пытающихся как можно равномернее распределить хэши в разных ситуациях.
Но если тебе заранее известны все возможные элементы (например, у тебя список вкомпилированных встроенных функций, которые нужно вызывать по имени), ты можешь сделать https://en.wikipedia.org/wiki/Perfect_hash
Элементы... Как, блин, по русски buckets сказать?
http://web.karabuk.edu.tr/hakankutucu/CME222/MIT[1].Press.Introduction.to.Algorithms.2nd.Edition.eBook-TLFeBOOK.pdf
11.3.3 (со звездочкой) - страница 255 по навигации, 232 по печати. Пусть лежит.
Тебя про хэши на джуна будут спрашивать.
Самая простая и годная хеш-функция от Dan J. Bernstein
// Dan J. Bernstein string hash
static inline uint64_t hash(const char str) {
uint64_t h = 5381;
while (str) {
h = (h << 5) + h + *str++;
}
return h;
}
> Открытая адресация в разы лучше.
Да, никто не спорит, но цена открытой адресации - перехэширование, т.е., если со списками у тебя все просто понемногу ухудшается с ростом количества элементов, то когда у тебя хэш-таблица с открытой адресацией заполняется, на тебя разом падает вся "сэкономленная" работа. А просто ресайзнуть таблицу и не делать рехэш тоже хуево.
Даже с ресайзом и рехэшем быстрее работает, главное не давать таблице заполнятся больше чем на 80%
Пишу может не совсем по теме, но все-же.
Мне нужно разработать простую и легковесную систему администрирования чисто под Win32.
Изначально пришла идея и сейчас мной активно раздумывается о том, чтобы весь функционал системы был на управляющем сервере.
Если упрощено, на сервер будут храниться бинарники, и по мере надобности, клиент будет загружать их оттуда и выполнять, а затем либо удалять, либо оставлять, как уже пожелает пользователь.
Таким образом главный файл будет весить очень очень мало, при этом он почти не будет ограничен в возможностях.
Пока что из прогрессивных идей, эта первая.
Что скажете ?
Каким функционалом такие системы должны обладать кроме RDP/FTP/SSH ?
Вот я создал два массива
char★ A[]={"One", "Two, "Three"};
char★ B[]={"One", "Two, "Three", "Four", "Five"};
Дальше я создаю еще один массив с указателем на первые два
char★★ AB[]={A, B};
И как мне теперь добраться, например, до значения A[1] через AB[]?
Блин, так просто. А такого наворотил. Спасибо.
А такой вопрос. Почему, когда я попытаюсь получить данные из ячейки, которая выходит за пределы массива, то данные берутся из соседней ячейки?
Например, если я попытаюсь получить значение AB[0][3], то мне выдаст значение AB[1][1] т.е. "One" из массива B. А еще у меня из-за этой херни половина памяти ардуинки сожралось — пытался определить величину массива, но это уже другой вопрос (а может и тот же).
> данные из ячейки, которая выходит за пределы массива
Доктор, мне больно, когда я делаю так. Ну, не делайте так.
Данные-то в памяти где-то должны лежать? Вот тебе компилятор и сложил элементы обоих массивов последовательно, в том порядке, в каком ты их описал. Но никаких гарантий насчет этого нет, а выход за пределы массива так и вообще UB, не делай так.
> пытался определить величину массива
Для массивов массивов с переменным количеством элементов во втором измерении можно NULL последним элементом воткнуть: { "One", "Two", "Three", NULL }, и по нему детектить (это если ты все равно циклом по элементам бегаешь). А если размер нужен для проверки при произвольном досутпе, можешь посчитать sizeof-ом и захардкодить заранее: https://ideone.com/cTvEPz (типы в тайпдефы запихать можно, чтобы не писать эту мешанину звездочек каждый раз).
Спасибо, получилось. Я думал, что раз я определил массив, то у него есть начало и конец.
А еще такой вопрос. Еще я думал, что на стадии объявления массива, данные уже записываются в память, но у меня пожирание памяти начинается на стадии использования этих массивов. Может быть такое?
Т.е. на стадии объявления мой мк забит на 14%, а как только я начинаю использовать цикл вывода данных на экран из массива, то динамическая память занимает уже 50%
Объявление вообще не соответствует никакому действию в маш.коде, это лишь указание компилятору, на какую часть личного адресного пространства рассчитывает то или иное имя с начала использования. Раздувать сегмент стека компилятор скорее всего станет непосредственно перед использованием, как если бы ты объявил его в этом месте. Но ты имеешь право объявить раньше для красоты.
Я понял, спасибо за ответ.
wsl
https://pastebin.com/FCQ8ELNp
-_-
getopt
В целом реализация ахуенная, но абсолютно не читаемо. Выбери себе один стиль в котором будешь писать. Например чтобы смотря на члены выражения можно было понять, сравниваешь ты переменную, функцию или структуру, или член структуры. Аргументы функций тоже желательно выделять как-то. Попробуй какой-нибудь классический ООП стиль из сипп или джавы
Да не бейте лучше обоссыте линупс из под виртуалки я нормальный вон видишь даже вижак на панели задач ежже
Так а мейк мне нахуя тогда нужен, если я чё то еще руками буду делать? И почему не находятся? Я же ему русским языком говорю -L{путь к либе для линкования} и -Wl,-rpath={путь к либе} чтобы загрузчик эльфа знал, где ее искать. Тем временем я уже попробовал в /usr/lib и /usr/local/lib пихать printhello.so и делать чмод 755 всё в том же мейкфайле - не помогло.
И само чо интересное, компайлер моросит именно на extern-переменные, а на функцию, которая в том же хэдере - нет. Чому так то блять?
inb4 далбаёб переменные в шейрд библиотеках хранят только быки и пидарасы а рогов я у тебя что то не вижу --- это чисто в образовательных целях.
Я так и думал. Ты в своем .h объявил nameptr и
ucnameptr, а определить забыл. А так как оно у тебя явно extern, то самостоятельно компилятор тебе ниего не объявит. Создай в printhello.c переменные, и все заработает.
Да, как раз об этом читаю сейчас статью https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/. Спасибо, сейчас попробую.
Вроде и да, а вроде и нет. Функция в адресном пространстве либы, а переменные - в пространстве основного модуля. Так и должно быть? Или раз один инстанс шейрд либы может разными процессами дергаться, переменные либ всегда дублируются в памяти модулей из соображений безопасности?
> Ананасы, а какие основные навыки сейчас требуют у эмбеддед синьеров-помидоров с 4к+ зарплатой?
бамп вопросу. Неужели итт нет относительно успешных сишкоблядей?
Вкратце: система динамических библиотек в линуксе говно, она состоит из одних лишь костылей (в винде такой хуйни нет и близко, там все работает так, как ты предполагаешь). Скажи Source.c, что он тоже fpic, и настанет счастье.
изи лол....
>>anon122131231324ь
Здаров наСИльники посоветуйте что актуального почитать о CTP/IP (и сокетах) с примерами на сишке
> Посоветуйте учебник по С11 на русском
Советуем: https://www.ozon.ru/context/detail/id/147927650/
С вас две тысячи триста пятьдесят семь рублей.
Давай не вкратце лучше, или где почитать
А как перевод, что то в отзывах пишут перевод кривоват и напечатано как на ксероксе.
Там под каждой локализацией так пишут
Последний вопрос не актуален - только что увидел, что в K&R A6.3 детально описано, как должно выполняться преобразование.
> это всегда IEEE 754
Нет, к сожалению (#ifndef __STDC_IEC_559__). Но на распространенных платформах всегда.
У меня твердое ощущение, что мне нужно прокачать скилл комбинаторики.
В школе понятно этому не учили, да и не учился я особо.
В вузике тоже мельком проходили.
Но везде от алгоритмов до практического программирования чувствую что где-то меня наебывают.
Учусь по KR и Прата.
Порекомендуйте пожалуйста курс, можно платный по этой теме. Английский вполне на уровне.
Спасибо.
http://web.karabuk.edu.tr/hakankutucu/CME222/MIT[1].Press.Introduction.to.Algorithms.2nd.Edition.eBook-TLFeBOOK.pdf
Тут тебе и анализ алгоритмов с аналитическим доказательством ассимптотной сложности, и дополненения со всем необходимым математическим аппаратом (теория чисел, теория вероятности и т.д.), и много много всего, а главное - с упражнениями и задачами. Пусть объем не пугает, просто все изложено по-максимуму, да и никто не заставляет за раз все "выпивать". 3-е издание можно найти, лично я в Торе брал.
>в Торе брал
>когда есть кошерный libgen.io, на котором есть все технические книги
Палю годноту
У тебя контактные линзы выпали
На чистом си сейчас пишут всерьез только в embedded юниках и bare metal, и имеет смысл вьезжать только в это. И деньги, судя по вакансиях, есть только тут. Разве я не прав?
Ну, лично я, например, смог хоть как-то освоить только Си. Всякие кресты, шарпы, питоны и прочие джавы слишком сложные.
Все. Вопрос в трудозатратности и целесообразности.
Всё что угодно.
srav=SortDataset(s,i);
fwrite(&srav,sizeof(int),2, table);
Но в файле записывается нечто невразумительное
T в F ‹ \f
3 ]D џ EQ
Почему?
Конвертируй в ascii символы то говно, которое ты записываешь в файл, и будет у тебя в нем тогда нечто более вразумительное
То есть
fwrite(&srav,sizeof(int),2, table); >> fprintf(table, "%d", srav) // я правда не понял, зачем ты "2" передаешь в fwrite, но логиту, я думаю, ты поймешь.
Работает, спасибо, но все равно, почему мне такое говно выдавало?
Программа отсюда http://www.c-cpp.ru/content/fwrite тоже залупу печатает, хотя у автора видимо все работает.
Но ведь она действительно работает. Работает так, как того захотел автор - записывает значение переменной в бинарном виде, то бишь без конвертации в читабельную кодировку. Открой файл в каком-то hex-вьювере, и можешь сам сконвертировать бинарное значение в что-то более понятное для себя.
Но почему при записи строк таким способом они вполне себе нормально читаются в блокноте?
Ну так вот.
Каким способом нормально читаются? С помощью fprintf? fprtintf() конвертирует значение переменной в ascii коды и пишет эти коды в файл, а fwrite() просто записывает значение переменной в голом виде в файл без какой-либо конвертации.
Блокнот же парсит файл в ascii кодировке.
Если ты все же не понимаешь написаного мною выше, то почитай что такое ascii и зачем вообще эти кодировки символов.
> Каким способом нормально читаются?
С помощью fwrite записывая массив строк они прекрасно читаются в блокноте, а вот с инт и флоат такое не прокатывает.
А блять. Ну потому что строки в Си как раз представлены в ascii кодах.
char *s = "1234"; // здесь объявлена строка размером 5 байт. В памяти ее значение будет выглядеть вот так: {49, 50, 51, 52, 0 }
int num = 1234; // здесь объявлена переменная размером 4 байта (или 8 или какой там у тебя процессор). В памяти она будет выглядеть скорее всего вот так: {123, 4, 0, 0}
Теперь подумай как записанные данные будут выглядеть в блокноте в первом и втором случае.
Лалка))
Задали в шараге написать реверс шелл для виндовс.
Погуглил немного и нашел вот этот https://github.com/infoskirmish/Window-Tools/blob/master/Simple Reverse Shell/shell.c пример.
Скомпилировался нормально, без ошибок, только не работает так как нужно.
Неткат подключается и сразу отключается, будто бы cmd.exe либо не создается вообще, либо ничего не отправляет в stdout.
Процесс вроде бы создает, в GetLastError() ошибок нет.
Почему не работает ?
Скину вот еще https://www.youtube.com/watch?v=4r93_6wZYTk в пример видео, код почти такой же, работает на 10-ке нормально.
Ну, я вот тоже с ИБ. Самое такое, что писали - POSIX "изучали". Форки, екзеклы, потоки, семафоры и прочее.
Сам шелл как стартуешь? Он порт и айпишник из аргументов тянет. Файрволл еще может возбудиться и резать трафик.
Любопытненько.
Я просто скопипастил весь код изменив только адрес и порт и он заработал.
До этого я писал свой код который делает тоже самое, просто он был несколько поменьше и он не работал.
Ты хорошо разбираешься в Си ?
В гугле набери, додик
Можно, я разрешаю
Лудшая книга по алгоритмам на C
Все подробно разбирается и главное есть нормальные примеры, а в книге с твоего пика примеры очень хуевые.
Написал GUI-программу на WinAPI, прописав в APIENTRY вызов FreeConsole();, однако при запуске программы окно консоли всё равно появляется на микросекунду и сразу же после этого закрывается. Жутко бесит, помогите исправить.
В чем отличие кода использующего только функции winapi от кода использующего функции языка Си ?
> Что такое универсальная среда выполнения
UCRT что ли? Кривое говно.
> В чем отличие кода использующего только функции winapi от кода использующего функции языка Си ?
Функции языка Си (ты ведь имеешь в виду стандартную библиотеку, да?) - обертки для системного апи. Но так как они стандартизированы, то если твоя программа пользуется только ими, то в теории она скомпилируется и заработает на любой системе, где есть стандартная библиотека Си (а так как она стандартная, то если там есть Си, то и библиотека должна быть). С другой стороны Windows API работает только в Windows, ну и в wine худо-бедно.
>>401237
> А если tcc и используется WinMain ?
Да быть такого не может, он в таком случае, как и любой другой виндовый компилятор, автоматически выставляет -subsystem=windows. Показывай код.
> Что собственно значит это сохранение упорядоченности?
Значит список отсортирован (упорядочен), и нужно воткнуть элемент в подходящее для него место, а не просто в начало или конец списка.
>>401318
Когда тебе понадобятся указатели на указатели, ты первым об этом узнаешь argv видел?.
> работа этой штуки в железе
Ничем не отличается от указателя на объект: когда ты ставишь звездочку перед именем указателя (или квадратные скобки с индексом после него), по указанному адресу происходят какие-то манипуляции со значением указанного типа (например, чтение или присваивание). Этим значением может быть, например, int, double, целая структура или другой указатель. Что ты с этим значением будешь делать дальше - целиком и полностью твое дело.
применение - когда тебе надо вернуть из функции указатель, тогда и используешь указатель на указатель
например, ф-я поиска в списке будет возвращать указатель на ноду, которая содержит искомое значение, а для этого нужен указатель на указатель уже
в общем, когда понадобится, ты начнешь быстро это использовать, об этом выше уже написали
>
>
не парься: у вирта в "структурах и алроритмах" где обсуждаются односвязные списки, там и эта вставка описана как ее делать
если не хочешь думать, просто посмотри там
эк ты загнул
подозреваю что ответ будет таким: в си нет string interpolating, а composite formatting обеспечивается семейством функций printf ..
>здесь объявлена строка размером 5 байт
формально у тебя: определен указатель на char, инициализованный указателем на начало строкового литерала
>Подскажите, что писать-то на вашем си
laba1, laba2, .. на курсе по алгоритмам и структурам на втором году обучения в вузике
> так много виндузятников, которые пытаются что-то ковырять в винапи
вымирающий вид, прямо как белый амурский тигр, кхе-кхе
>теория чисел, теория вероятности и т.д.
эх, а нам ведь на отдельном курсе в вузике это целые полгода мозгу ебали
щас нихуя не помню уже оттуда
ОП пишет:
>>393395 (OP)
>Тред, посвященный прародителю всех С-подобных языков
Слышь, ты, позорище.
C (1972)
B (1969) — Би — интерпретируемый язык программирования, разработанный в AT&T Bell Telephone Laboratories. Является потомком языка BCPL и непосредственным предшественником Си.
BCPL (1966) - стал ответом на сложности своего предшественника, языка CPL, разработанного в начале 1960-х. Ричардс создал BCPL, «удалив из полного языка те функции, которые усложняли компиляцию».
CPL (1963) - Combined Programming Language (CPL) — язык программирования, совместная разработка кембриджского и лондонского университетов. До подключения к проекту лондонцев «С» было первой буквой от «Cambridge», а потом официально расшифровывалось как «Combined». Неофициально же «С» означало «Christopher», поскольку именно Кристофер Стрейчи[en] вдохновлял работы по CPL. Сейчас этот язык не используется, но его наследником стал язык BCPL — один из предшественников языка Си.
На него сильно повлиял ALGOL 60.
ALGOL 60 (1960) <= ALGOL 58 (1958) <= [FORTRAN (1957); Plankalkül (1948)] <= [Speedcoding (1953); Begriffsschrift (1879)] <= (ASM (1949) и Машинный Код)
>Чмох, соси хуй. Именно из-за хуевого синтаксиса В, никто его юзать и не стал
дебил, речь идёт о предках языка, откуда он есмь пошёл, сука, ты совсем тп, пидораска опущенестая?
K&R есть на русском. И не бойся инглиша, ты же не даун с 4 классами образования, хоть что-то знаешь. Просто бери нужную книгу и начинай читать, в браузере открой вкладку с переводчиком. Увидел непонятное слово - перевёл и пошёл дальше. Через месяц такой практики станешь сверхчеловеком.
Ну я просто вообще из С# вырос, там есть сахарок типа string s = $"this is {s1} interpolated string {s2}"; где s1 и s2 - другие строки. Вот искал что то похожее в С.
в линуксах и вообще unix-мирке до сих пор большинство user-space кода по итогу на сишке написано
это ничем, в принципе не оправданно, просто дань традиции
gnome, к примеру, у них сотри проектов на сишке, даже не на плюсах
если хочешь просто писать для развлечения и общественной пользы - велком, им постоянно нужны рабы
другое дело, в кернелее (что в виндах, что в юниксах) до сих пор надо писать на си, тут нету выбора особого
>с переводчиком
вредный совет. Лучше чисто английский словарь. Такой, что ввел "penis" и выбило "male organ of copulation". Так лучше вкатываться в инглиш.
Угомонись, дегенерат.
Ну да, так и надо осваивать. Не миллион частных случаев, а см. что откуда берется. Индукция сосет, дедукция рулит. K&R же не состоит на 80% из примеров. Это книжка на языке о языке, и к обоим языкам надо относиться с уважением. Серьезно, с переводчиком себе дороже.
Мамку ебал.
Связка clang + lldb вроде как работает под виндой.
>Косплей MinGW как-то не вдохновляет.
А зря. Разработка под линуксом, mingw и wine - самое удобное.
А так студия типа 2008 с visualassistx пиратским.
> Тред, посвященный прародителю всех С-подобных языков
Я вообще не знаю, что это должно значить. Текст остался от ОП-а самого первого треда.
Это тот, который выпилился?
Посмотри исходники какого-нибудь NIX и убедись в том, что шаблоны, стандартная библиотека плюсов, неявные вызовы в ядре на 100% неприменимы.
>Невозможно запустить это приложение на вашем ПК
хм.. неплохая идея. Отпидорить саму либу. Ведь отпидорятся и точки входа, и вызовы, если ее функции юзают друг друга. Шото я не подумал об этом.
> Как мне научить свой компилятор
> nm
Возьми компилятор и линкер у майкрософта, и все сразу станет хорошо.
Сделал программу для чтения строк из файла и записи их в список. Но при выводе после последней строки выводится (null) и программа выдает ошибку. Почему?
Ясно, я случайно поставил точку с запятой после ифа. Час искал ошибку, пиздос.
Мешать код от разных компиляторов - не очень хорошая идея в принципе. А на линуксе у тебя есть вайн, а в вайн ты можешь притащить билдтулзы какие-нибудь от 2005 студии, они весят 150 метров, считая Platform SDK.
шото у меня не гугляцца эти билдтулзы
Короче, на сайте Майкрософта нашел только от 2019 студии. Просит .NET Framework 4.6. Нахуй мне вся ультрасовременщина. Надеюсь, в один прекрасный день заскучавшему террористу приглянутся дети кого-нибудь покрупнее из этой ебучей корпорейшн.
Не хочу создавать отдельный тред, спрошу тут. Зачем нужен Си, если есть С++ и другие языки? Зачем эта какуля мамонта? Объективно, что можно на Си, но нельзя на С++? Вот на Си дохера что нельзя.
Чисто из рантаймовых соображений:
Си: Минимальный рантайм, малюсенькая стандартная библиотека, почти нет скрытых от глаза операций, реализуется за пару дней на любой железке/проце.
Плюсы: толстый рантайм (отвечает за инициализацию статиков, их thread-safety), большая стандартная библиотека которая ещё и сама оченб часто лезет к маллоку за памятью, много "магических" вещей (типа конструкторов, исключений, RTTI, виртуальные таблицы, захватывающие лямбды и тд и тп - это всё добавляет невидимый код), темплейты насилуют линкер и заставляют всё собираться в 50 (или больше) раз медленнее, сама имплементация реализуется очень долго и муторно.
Про семантику вообще молчу, в C++ она на три порядка сложнее. Вот расскажи, не читая cppreference, что такое deferred dynamic initialization или Koenig lookup. Кстати, ты знал, что есть такая вещь как Function try block? Я только в том году прочитал. Я сам пишу на C++ на работе, и мне нравится. Но я также знаю и людей, которые аргументировано терпеть их не могут.
Мне не нравится си плюс плюс, потому что фич много и много их может не стать с новым стандартом.
А нравится мне в нем то, что он генерирует код лучше, чем Си, если использовать те же классы и темплейты.
>Я сам пишу на C++ на работе, и мне нравится. Но я также знаю и людей, которые аргументировано терпеть их не могут.
Это не аргумент.
>Си: Минимальный рантайм, малюсенькая стандартная библиотека
Тебя никто не заставляет использовать весь функционал, но он у тебя есть и реализован без костылей. Твое высказывание равносильно " в луже тепло плескаться, а в море холодно"
>>402740
~
Си аналогично кряхтит на стадии компиляции, а сказки про быстродействие программы остаются лишь сказками.
> реализован без костылей
Только человек, никогда не писавший код с шаблонами, может употреблять это выражение рядом с C++.
>Тебя никто не заставляет использовать весь функционал
Тот факт, что другой функционал есть и занимает очень значительную долю фронт-энда (а с некоторыми фичами, которые касаются линкера и рантайма, ещё и бэк-энда) компилятора означает, что на подмножеством, которым пользуешься конкретно ты, выделено было не так много времени, как тебе хотелось. Да и C++ такой язык, что ты можешь наступить на грабли случайно, даже не сам этого не увидев. В обычных Сях все грабли лежат на полочке, чтобы ты их сам положил в нужное место и наступил.
>Зачем нужен Си, если есть С++ и другие языки?
Си не нужен, ведь С++ делает то же и намного больше и лучше.
Но Си-тред нужен, для обсуждения процедурного программирования, т.к. С++-тред засран ООП, функциональщиной и прочим ненужным говном.
fgets(mass, 6, filename), где 6 судя по описанию это количество символов +1.
Так вот, считал первую строку, она вывеласьхотя почему то вместе с 5 буквами был символ перехода на новую строку, отлично, снова запускаю fgets, и она уже нихуя не выдаёт. Почему?
А зачем код?
Ну вот например
char word[6]
fgets(word, 6,filename);
printf("%s", word) :
fgets(word, 6,filename);
printf("%s", word) :
Короче вопрос в чем, объясните мне пожалуйста таинства TCC.
Читал где-то (тут или нет, не помню), что как таковой оптимизации в TCC нет, вернее она есть, но не в том виде в каком она есть в GCC например.
И тем не менее мне непонятна магия размера бинарного файла.
У TCC это 2-4Кб, у GCC 100-200Кб.
Как TCC собирает такой маленький файл ?
Почему в DevCpp(GCC) такой собрать не получается ни с какими опциями для оптимизации ?
Ну и самый важный вопрос, почему мой бинарный файл собранный TCC не запустился на другой машине ?
На это как-то влияет 32/64 битовость системы ?
У меня если что 64 бита.
> А зачем код?
Ну ты ведь хочешь знать, где ты не прав?
> fgets(word, 6,filename);
> filename
И как, работает? Настоящий код неси.
> хотя почему то вместе с 5 буквами был символ перехода на новую строку
Где-то ты пиздишь, потому что если у тебя в файле строки по 5 символов, а в fgets ты передаешь 6, то шестым будет \0, и символ новой строки просто некуда воткнуть. Но в целом суть именно в этом. Ты либо читаешь "строка" + \r первым fgets и \n вторым, либо читаешь "строка" первым и \r\n вторым.
>>402867
> как таковой оптимизации в TCC нет
Да. Максимум они вроде constant folding они завозили, но инструкции побыстрее или покороче оно не выбирает.
> Как TCC собирает такой маленький файл ?
Это не про компилятор, это больше про линкер. TCC линкуется к старому сишному рантайму MSVCRT.DLL, плюс статически линкуется минимальный стартап и больше ничего. MinGW тоже к MSVCRT линкуется, но в дополнение к этому у него есть патчи для поддержки C99 (сравни printf("%zu\n", sizeof(int)) в TCC и MinGW GCC), есть некоторое количество лишнего говна, которое всегда линкуется, даже если не используется (вот я смотрю, в 8.2 уже какие-то opendir притащили, какие-то glob - зачем?). Поэтому минимальный размер у GCC в районе десятка-двух килобайт. Если у тебя 100К, то ты просто -s забыл, и у тебя кроме кода куча отладочных символов в бинарнике.
> почему мой бинарный файл собранный TCC не запустился на другой машине
Ну нам-то откуда знать? Ты ведь файл так и не принес.
>как работает fgets
Как написано в документации. Ты русекодебил, неспособный читать? Тогда справедливо соси хуй.
Так-то и на русеке описания хоть жопой жуй.
Тут же чередуются команды прочитать букву / вывести букву.
Значит каждая буква должна по два раза подряд повторяться. А получается, что в один int целая строка запоминается.
Зависит от настроек терминала. Терминал может отправлять инфу в программу построчно (по умолчанию) или посимвольно. У тебя отправляется построчно. Тоесть ты сначала вводишь строку, потом она сразу вся уходит в программу и начинает отрабатавать твой цикл. В линуксе если тебе надо посимволная обработка то нужно перейти в "noncanonical mode" с помощью вызова tcsetattr, может еще что поравить. Если у тебя операционная система виндоуз то не знаю, возможно ты соснул. Там должно быть что-то свое, _getch какой-то или еще какая хуйня.
>С чего повторяться то должна?
Потомучто в программе нет перевода строки.
>Читает букву
Фактически за один шаг цикла читается вся строка
> Фактически за один шаг цикла читается вся строка
Каждый шаг цикла читается один символ. Просто символы появляются в stdin сразу целой срокой. Пока ты вводишь строку цикл не работает (stdin пустой). Как только ввел цикл считывает по одному символу и выводит. Можешь добавить какой-то счетчик итераций в цикл.
Понел, спасибо.
Что именно не работает? https://ideone.com/ScXKqq
>>403310
> наших с тобой постов нет
И не только наших.В любом случае, с описанием "ничего не работает" я не могу тебе помочь. Нужен или файл (а ссылку, если она была, я увидеть не успел), или больше инфы.
И всё-таки.
А есть в этом смысл? Память экономится, или еще что то? Потому что на читаемости подобные конструкции сказываются не лучшим образом.
борда отступы хавает
А если там проверок больше? Но вообще основной поинт был в том что бы не писать это логгирование с else {} каждый раз и вынести их в отдельный макрос.
Мне нужно возвращать значение из родительской функции в случае неудачи, простая функция так не может.
Я всегда что-то вроде первого варианта использовал. Не люблю пользоваться макросами для control flow (максимум - что-то наподобие кернельных интрузивных списков). Если возможно, проверяю на ошибки в начале и делаю early return, как на пике.
Мне нравится в этом плане Zig со своими defer/errdefer (первый из которых взят из Go). Вроде как вполне сокращает лишнюю писанину. Посмотрим, как этот язык в конце концов себя покажет.
Просто вызубрить С11?
Иди пиши портянки if-ов, как люди. Никто твои макросы разгребать не будет.
>безопасный
Соблюдать правила
>хороший
Прочитать книги ХАКЕРСКИЕ
Писать читабельный код и чекать его на godbolt.
Пишешь код, получаешь опыт с такими же задротами, через 10 лет просыпаешься кармаком.
Методом проб и ошибок. У С столько нюансов, что просто вызубрив все равно будешь натыкаться на подводные камни. Короче говоря, нужно много практики.
> _protseduraname@8, что не соответствует моему _protseduraname
Первое - __stdcall, второе __cdecl. Объяви функцию как __stdcall, и оно слинкуется.
есичо, у меня инструментарий 2005 года
> мамой клянусь
Покажи сообщения линкера. Смотри, вот у меня оно все правильно декорируется на пике (последние две строки). Тоже какой-то старый cl примерно тех же лет.
> /Link
С маленькой буквы: /link, но не знаю, имеет ли значение регистр. Да и вообще, можно без /link тут, просто имя либы, оно само разберется.
Дык эта. У тебя тут кресты. А кресты имена манглят, а не декорируют. Сделай вокруг объявлений extern "C", как у меня на пике.
ох бля, как я забыл про extern "C". В случае с либой у меня header инклудиться как раз в блоке extern "C"
Ну блин, оно должно работать. Вот с MinGW была проблема, известная, а тут никаких проблем я не помню. Если уж либа такая секретная, смотри сам, что там у либы в экспортах, смотри, что тебе dumpbin показывает в символах, сравнивай, думай. Поищи, может там кто-нибудь сделал #define __stdcall на ничего. Или может, у тебя объвяления функций из либы правильные, и они линкуются, у тебя на твои колбеки ругается?
>что там у либы в экспортах
Я под шиндой только компилирую, а копаюсь в коде под линуксом. Там же посмотрел
nm zalupaSDK.lib | grep protseduraname
И увидел кучу всего, в т.ч.
_protseduraname@8
>#define __stdcall на ничего
Во всем хедере __stdcall фигурирует только дважды в одном месте
#define CALLBACK __stdcall
#define CALL_METHOD __stdcall
И дальше в объявлениях функций используются только эти CALLBACK и CALL_METHOD.
>у тебя на твои колбеки ругается
да. unresolved external symbol _protseduraname in function mygavnokod
ЧЗХ?!?!
cl /E | findstr protseduraname
extern "C" int protseduraname(...)
Там вообще такая хуерга идет:
#if (defined(WIN32) || defined(WIN64))
...
#define CALLBACK __stdcall
#define CALL_METHOD __stdcall
...
#else
...
#define CALLBACK
#define CALL_METHOD
...
Таке враження, ніби воно не знає, що в мене операційна система Windows.
> defined(WIN32)
Потому что _WIN32. Ну видимо от тебя хотели cl /c whatever.cpp -DWIN32 yobaSDK.lib
Все приложения на Си должны использовать msvcrt ?
Может ли приложение работать без msvcrt ?
> Все приложения на Си должны использовать msvcrt ?
Нет. Приложениям под линукс разрешили использовать glibc.
> Может ли приложение работать без msvcrt ?
Да. Ты можешь слинковаться статически, или ты можешь не использовать стандартную библиотеку, обращаясь напрямую к Windows API.
https://yadi.sk/d/c9RgWu-5GGAH1g
Вот ссылка на собранный TCC бинарный файл, который отказался запускаться на другой машине.
Ну не удивительно, что у тебя сообщения удаляли с такими-то файлами. Я ожидал от тебя собранный хелловорлд, а не эту пародию на бэкдор. Возможно, тебя просто антивирус блочит. Возможно (хоть и маловероятно), виноват TCC - директория исключений выглядит как-то подозрительно, возможно она сломана. И вообще, почему ты решил, что файл не запускается? Винда как-то ругается? Возьми x64dbg и поотлаживай - даже если на самом деле не запустится, ты хотя бы узнаешь NTSTATUS. Вангую, что все у тебя запускается, работает, просто не коннектится и выходит, завершаясь exit()-ом.
Что такое директория исключений ?
Почему антивирус на моей машине ничего не блочит, и за что блочить-то собсна ?
Запуск процесса и перенаправление ввода/вывода это что-то противозаконное ?
>Винда как-то ругается?
пикрелейтед
> Что такое директория исключений ?
https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
> за что блочить-то
Поведение. Сокет, cmd.
> пикрелейтед
Может она 32-битная просто? Под отладчиком запусти. Или в event-log-ах посмотри, может там напишут. Под этим окном может скрываться что угодно.
У меня нет возможности что-то там отдебажить на той машине где не запускается.
У тебя запустилось ?
В конце концов выбрал введение в дискретку на Udemy. 15$ всего.
Там теория множеств, логика, комбинаторика.
И шо вам сказать, таки ДИЧАЙШЕ ЗАШЛО, особенно теория множеств. Это практически основа всего. Я даже думаю немного глубже зайти в тм, уж оче достовляе.
А потом на алгоритмы перейду.
у вирта оче концентированный учебник, каждая страничка - полезная, для новичков, само собой
имхо, не устарел ни разу
struct
{
double time_;
double fps_;
} glob;
#define time glob->time_
#define fps glob->fps_
> Можно ли добиться для глобальных переменных, определённого расположения в памяти
Нет. Можно, линкером, но это костыль. Можно явно городить указатели, но это пиздец. Кто тебе мешает обращаться к своим переменным, как к нормальным членам структуры, зачем тебе эти дефайны, у тебя пальцы писать устают? Алсо, там у тебя должна быть точка, а не стрелка.
Ясн. Ну да хотелось покороче писать.
int i;
stack = (struct tree )realloc(stack,sizeof(struct tree)+1);
for(i=0;stack!=NULL;i++)
;
stack=a->left;
}
В теории функция должна расширять массив указателей на один и в конец добавлять указатель на структуру. Но на деле это не работает, и вообще такое чувство что я говно какое то написал.
А разве gcc массивы создавая двусвязку делает? Не думаю, что это будет работать на 99 или 89
При чем тут двусвязка? Stack массив указателей на структуру, который мне собственно нужен для обхода дерева в ширину.
Ну во первых у тебя проебанный реалок. Во вторых непонятно зачем тебе вообще перемещать элементы, если после реаллока и так в конце должен пустой элемент остаться. Ещё у тебя с пост-декрементом нулевой элемент смещается влево. Ещё у тебя нету, собственно, самого присваивания значений полям последнего элемента.
я думал ты говоришь про обычный char массив, есть в некоторых компиляторах фишка по проходу по элементам без арифметики
По моему должно быть ка-то так, но я не проверял.
void add(struct tree ЗВ a, struct tree ЗВ ЗВ ЗВ stack, int carrent_size)
{
ЗВ stack= realloc(ЗВ stack, carrent_size + sizeof(struct tree));
//предполагая что ты отставил последний указатель NULL
int i=0; while((ЗВ stack)) i++;
(ЗВ stack)= a->left;
//или всё таки так???
(ЗВ stack)= a;
}
1) Там struct tree ∗stack? Если нет, то не ок.
2) realloc() всегда выделяет размер элемента + 1 байт, ты хотел явно не этого. Таскай с собой еще указатель на текущий размер.
3) Тебе никто не обещал, что кусок, который добавится в конец realloc()-нутого массива, будет забит нулями. Еще один повод передавать указатель на размер. Ну если у тебя stack терминирован NULL-ом, тогда можешь просто цикл перед realloc() сделать, а не после.
4) А еще принято притворяться, что ты умеешь обрабатывать ошибки выделения памяти, поэтому void add - не самая лучшая идея.
Ты какую-то дичь городишь. Сделай связанный список из него уже стек делай.
printf("%d\n",stck->next);
free(stck);
printf("%d\n",stck->next);
stck=stck->next;
printf("%d",stck);
return stck;
}
Я видимо не до конца понимаю как работают списки и указатели. Почему первый printf выдает нуль, а второй и третий нет?
Понял, я долбаеб
Нет, я просто не так много гениальных кодеров знаю.
https://pastebin.com/TpCUJq5z
да, это псевдокод, исполняюемую версию с гитхаба не кидаю, ибо нехуй диванонеров кормить. Собсно, никого ебать не должно, у меня все работает. Но хотелось бы с соблюдением всех красивостей переделать. В курсе про static __thread, но градус гавнокодности отнюдь не падает.
ой бля, там разыменовать надо возврат tsearch
Численное интегрирование, чисметы, ваш кеп.
Но зачем рекурсия?
Самый прямолинейный способ интегрирования это сделать разбиение Ox на кусочки определённой ширины, и запись для них суммы произведений значений функции в середине отрезочков на ширину этих отрезочков.
Здесь промежуточек малый, можешь даже ln(1+t) расписать в ряд Маклорена, там в знаменателе t посокращается со степенями t в числителе, часть членов выбрось, полином второй степени по Симпсону интегрируется.
Ну вот ты мне энивэй расскажи, зачем рекурсия нужна.
Никогда не понимал эту книгу, а тут такое вижу. Про что там вообще рассказывается? Все рецензии какие-то водянистые, а в самой книге сорцы Лиспа, мне страшно.
Через graphics.h не могу, потому что 1)Где взять эти ебучии borland-утилиты из 90-х, чтобы скомпилировать, 2)Костыль с WinBGIm не пашет, ДА БЛЯТЬ И НЕ СМОЖЕТ, потому что он под кресты, с пространствами имен, дефолтными значениями параметров в функциях и прочим.
Юзай gnuplot или если шаришь в питоне то попробуй pyplot
если тебе чисто графики рисовать для курсачей и лаб - то юзай гнуплот и матплотлиб, как советует тебе господин выше.
если же ты хочешь дрочить это в сишечке то смотри на дерьмо типа такого
https://github.com/grz0zrg/fbg
https://github.com/simple2d/simple2d
[code]
struct Point {
int x;
int y;
int z;
};
int main(void) {
void r;
r = malloc(10sizeof(Point));
free(r);
exit;
}
[/code]
Почему не компилируется
struct sockaddr_in peer;
rc = connect(s, (struct sockaddr *)&peer, sizeof(peer));
Почему нельзя просто передать &peer, разве ф-ия коннект не знает, что за указатель она принимает.
потому return val; - встроенная конструкция C, по которой генерируется код типа
movq %rax, $val
popq %rbp
ret
и ты компилятор достаточно умен, чтоб ты мог опустить val.
exit же - это функция обертка для системного вызова exit, код для которого по умолчанию лежит в _start, куда возвращается main. Так что если хочешь завершить процесс на месте, пиши exit(0); и будет тебе счастье.
> ф-ия коннект не знает, что за указатель она принимает
Знает. Она принимает struct sockaddr, ты передаешь struct sockaddr_in. С точки зрения компилятора - это разные структуры. Это и есть разные структуры, просто они подогнаны так, чтобы у них было совпадающее начало. Вообще, так делать нельзя, там должен быть void * или union, но по историческим причинам тянется это говно.
>>409827
> Warning - не Error.
Нахуй иди.
Забавно, что у меня, возможно, больше профессионального опыта в си, чем у тебя, а ты такое мне говоришь, а может и не больше, кто знает.
Как в C, если это возможно, заставить набор команд/функцию выполняться атомарно? Я использую либу с многопоточностью, но сам потоков не заводил; мне нужно, чтобы функция из либы, выполнялась до конца, единым блоком и не расхуячивала мои данные.
То есть ты вызываешь функции из либы, и она возвращается прежде, чем кончает свою работу, потому что наплодила detached потоков? И ты хочешь, чтоб твоя программа заблокировалась, пока они не самовыпилятся? Просто не смог представить себе другой ситуации, когда взятие и высвобождение мьютекса нужны на разных уровнях.
> у меня, возможно, больше профессионального опыта
Так говорят только нубы, которые ничего не знают, есть такой сорт чсв-дебилов.
В линуксовых shared object'ах extern переменные и функции в двух разных процессах будут иметь один и тот же виртуальный адрес, или могут (и должны) иметь одинаковые значения в младших битах адреса, но разные в старших из за какого нибудь ASLR? При этом для обоих процессов они имеют одинаковый физический адрес до первой записи?
какая-то подзалупная библиотека...
>Репост из реверсача, вдруг тут кто нибудь знает
>В линуксовых shared object'ах extern переменные и функции в двух разных процессах будут иметь один и тот же виртуальный адрес
Этим ld распоряжается, виртуальные адреса будут разными. При этом у сегментов без прав на запись физ. адреса всегда будут одинаковыми. В не-pic elf файлах .so можно подменить в runtime, так что все еще хуже.
>или могут (и должны) иметь одинаковые значения в младших битах адреса
Да, память же страничная, все выравнивается (обычно) на 4к, выравнивание указывают в phdr у PT_LOAD. В man есть страничка про elf.
>При этом для обоих процессов они имеют одинаковый физический адрес до первой записи?
Да, а виртуальные останутся прежними. Это называется Copy On Write. Он и при clone сработает для всех отображений.
ASLR можно отключить.
оки, спасибо
Как лучше всего читать файл целиком в память ?
Размер знаю (fseek, ftell), а вот как прочитать способов нарыл много.
Нестрогое подмножество. Стараются поддерживать языки более-менее совместимыми. Но, например, в designated initializers есть только в C++20, а сишный _Complex вроде так и не завезли. Ну и там есть всякие мелочи типа sizeof('x').
int f (void• o);
и я в нее передаю указатель на структуру mystruct msInstance. есть ли смысл явно кастовать
f( (void•) msInstance);
?
и наоборот, если функция принимает mystruct•, есть ли смысл при передаче в функцию void• кастовать его к mystruct?
inb4 влияет при дереференсинге - а если я, например, передаю в функции f принятый указатель в какую нибудь системную функцию или вообще в инлайн асм операцию типа вызываю clflush или еще чего, где типы не имеют значения
fread если через стандартную библиотеку C.
Если unix-like, то fstat и read, но лучше будет отобразить файл в память целиком через mmap.
Про mmap двачую.
Бинарник из-за этих приведений никак не меняется, как и само значение указателя. Явно приводить к void★ не нужно. В обратном случае написать явное приведение к типу структуры вполне обоснованно.
Я уже сделал, fseek/ftell/fread в выделенный буфер char
А вы тут шарите за альтернативные потоки данных в NTFS ?
Прочитал тут книгу по питону, и там наткнулся на главу о сокрытии файлов.
Сколько всего там можно хранить, от баз данных, до исполняемых файлов.
Интересно, если такая функция используется некоторым программным обеспечением, то антивирус получается ровно на это дышит ?
Кому доводилось что-нибудь программировать связанное с этими потоками ?
>но по историческим причинам тянется это говно.
У винды половина апи с таким багором. Даже где-то читал, что они говорили, мол это фича. Классика короче.
>мол это фича
Backwards Compatibility довольно важная вещь. В линупсах юзерленд апи тоже десятки лет не изменяется. Им тоже приходится поддерживать такие былинные фейлы как aio. Говорят, что uring получше, но я не пользовался пока.
asm volatile("clflush 0(%0)\n"
:
: "c"(addr)
: "rax");
не могу найти описание именно для "с"
> https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints
> c The c register.
Т.е., ecx/rcx.
спасибо
Также в Си существует четыре класса хранения:
auto — по умолчанию для всех переменных.
register — подсказка компилятору хранить переменные в регистрах процессора. Для таких переменных отсутствует операция взятия адреса
static — статические переменные. Имеют область видимости файла.
extern — переменные объявленные вне файла
Не думаю, что в C11 что-то кардинально поменяли.
Ага, он самый, кстати починил, а все было из за одного пропущеного пробела. Ну как так то
А что необычного? Как по мне анон неплохой придумал ну или подглядел где то, не нужно хедеры указывать, все само находится и в отдельный каталог собирается. Осталось ещё сделать что бы объектные файлы подтирались и вообще хорошо будет.
мимоанон
Как можно что-то подобное на Си получить ?
Передаю аргумент sosi
//Цикл for
if(argv == "sosi")
{ /.../}
Не выполняется условие.
По адресу аргв всегда однобайтовый чар будет, т.е. argv[1+n]['s', 'o', 's', 'i']
Да, делаешь пустой массив и два индекса, на индексе, где находится пужный элемент увеличиваешь только индекс изначального массива, тащемта, я совсем не понял что тебе надо
Не очень понял 1+n, да и в принципе нихуя я не понял.
Почему printf() выводит по индексу, а условие не работает с тем же индексом, и как сделать чтобы работало ?
> функция pop() удаляющая элемент из массива, создает новый массив
Ничего она не создает, просто удаляет элемент.
> Как можно что-то подобное на Си получить ?
memmove(&array[index], &array[index + 1], (array_size - index - 1) * sizeof(array[0])) удалит из массива элемент index. Это полностью идентично тому, что делает pop() в питоне (ну за исключением того, что оно подсунет в index индекс последнего элемента, если ты функцию без аргументов вызовешь).
>>412318
Строки сравнивают с помощью strcmp(). Твое == сравнивает указатель на массив символов в argv с указателем на строковый литерал. Очевидно, что они всегда различны.
Например есть у меня массив [test, xyest].
На питоне у класса массивов есть функция pop, которая по индексу удаляет элемент из массива.
То есть после pop(0), в массиве останется только xyest.
Собственно это мне и надо.
Нормально объяснил, все по делу.
А то я на питоне скриптик написал, и захотел в образовательно-развивающих целях написать тоже самое на Си.
И вот с парсингом аргументов вопросы и возникли.
Дома буду, попробую, пасиба.
Забыл как это называется по умному, но в си любое имя это по дефолту указатель, и когда ты берешь в операцию сравнения какое-то имя, например *sosi, перед самой операцией разворачивается адрес, на который это имя указывает, и оттуда читается количество битов, определяющееся типом указателя/имени, т.е. если ты закастовал sosi к например флоат, то при взятии адреса будет читаться 4 байта, и они будут сравниваться с байтами с другой стороны сравнения. Если ты только изучаешь, то не юзай бестпрактисес, а пытайся все делать пошагово
Он добавляет в конец массива элемент который надо удалить.
Допустим я передаю аргументы:
a.exe -f test
Программа должна удалить из массива -f если найдет его.
А вывод такой:
a.exe
test
test
Может так происходит потому что for работает с массивом по одному адресу, а memmove переносит массив в другой адрес ?
Писал еще в прикреплённый, но тут по моему больше к месту.
С min max я уже нашёл ошибку.
> А вывод такой:
А ты argc исправил? Элементов-то меньше стало. Вот тебе рабочий пример: https://ideone.com/vNS9an
Точно, забыл про argc.
Теперь все хорошо.
А вот вопрос, если argv ответит указателем, то как мне получить значение этого указателя, чтобы его занести в другую переменную ?
char name = argv не работает
char name = &argv[1+n]
Выше ты говорил про разные адреса, в си этого нет, в рантайме сравниваются байты даты, т.е. == с одинаковыми байтами даты в разных адресах вернёт true, сравнения адресов, а так же арифметику и юзать их как параметры можно если компилить файл как .cpp
Проблема решилась избавлением от модулей
char ∗name = argv[i + 1];
>char name = &argv[1+n]
>main.c:12: warning: assignment makes integer from pointer without a cast
>main.c:12: warning: nonportable conversion from pointer to char/short
>char ∗name = argv[i + 1];
Сработало.
Еще вопрос по парсингу аргументов.
Допустим есть у меня определенные аргументы которые передавать обязательно, а есть которые не обязательно.
Без обязательных аргументов должен выводить help, а необязательные программа заменит своими значениями.
Собственно идея реализации пока одна, написать функцию булевую, которой передавать массив и строку, если строка в массиве есть - вернет True, если нет - False.
В питоне для этого есть in, в Си если что-то подобное и есть, то скорее для поиска подстроки в строке, или нет ?
А как ты передаешь аргументы? В виде массива, или как члены структуры?
В случае массива, тебе нужна функция, которая будет посимвольно искать то что тебе нужно, в стандартной либе есть strstr(), но стандартная либа под реальные проекты абсолютно не приспособлена, поэтому под свою нужду напиши свою, благо куда двигаться понятно. Кстати, bool в сишке не используют, он ничем не отличается от int 1 int 0/int -1 int 0/whatever int whatever int, при этом тратится время на линковку ненужной либы, лишние задачи в препроцессоре, лишние касты и етц.
Написал функцию, про bool прочел уже, возвращаю 1 если есть, 0 если нет.
https://ideone.com/Y8feXF вот как-то так получилось.
Че еще придумал, возвращать не 1, а индекс элемента, чтобы его запихать в memmove для удаления собственно.
Абсолютно не понятно что ты вообще хочешь сделать, поэтому советы тяжело давать.
>strcmp
На наебись.
И вообще советую не использовать функции str из стандарта, ибо возвращают они хуй знает что, имплементации там далеко не самые рациональные по скорости/памяти, на каждый пук реалок, который сам по себе один большой сишный костыль, нужный только для создания иллюзии низкоуровневости. Пиши сам, так и научишься намного быстрее.
Сделать программу, сейчас я пока пыхчу над парсингом аргументов.
Идея такая, есть 2 необязательных аргумента, их при отсутствии можно заменить дефолтными значениями, и есть 1 обязательный, это -f за которым следует список файлов.
Список как по мне обработать трудно, память-хуямять выделять, определять это все еще список файлов или нет, трудно это в общем, и я придумал удалять по элементу из массива, пока в конце концов в массиве argv не останется один лишь список файлов.
Вот это я и хочу сделать.
strcmp написать я могу и сам, не очень мне только понятно как вытащить из argv именно ЗНАЧЕНИЕ, чтобы уже по нему циклом пройти и сравнивать каждый символ.
https://ideone.com/Jqqy1L
чет такое получилось
Беспокойно насчет chrlen правда, все ли строки нулем заканчиваются ?
бееее
портированый еще
я уш лучше повелосипедю, вот мне не понятно если честно, почему в интернетах так мало этому внимания уделено, чет ниче внятного найти не могу
Ну какие стандартные либы-то ?
getopt равно как и argp либы линукса, а не виндовс
Запустить их можно вроде как, но это не костыльнее самописного парсера ?
Я, блять, не знаю, в чем у вас проблема, но MinGW под шиндовс вполне себе собирает программу с getopt, все работает как надо.
Мимо
mingw портирует glib, которая не входит в iso
Вот допустим мне надо положить строки в массив, чтобы получилось что-то такое ["stroka1", "stroka2"]
Делаю так
>char massiv[4][10];
>massiv[0][0] = *"stroka1";
>printf("%s", massiv[0][0]);
Пробовал strcpy, чтобы скопировать в [0][0] строку, выхлопнул warning'и, ничего не вывел.
Разобрался, индекс второй лишний указал.
И что, ее научили в векторную графику?
Хз что ты там делал, но просто пишешь инклюд ето говно и все работает!
Локально можешь виртуалку навернуть.
Потому шо так написано потому и нет.
Не работает.
Сбилженая либа находится в /usr/local/lib, если просто инклюдить, то кидает ошибки. Компилируется только с вышеуказанным флагом.
Хуй знает, я эту говно 3 годжа назад делал, либу в папку с проектом кидал, инклюдил и все работало.
> Как это фиксится?
Это требуемое поведение
> Почему в их онлайн-иде такого нет?
Там автоматом линкуется. Ты в своей тоже наверное можешь настроить. Или навернуть какой-то скрипт/makefile.
Спасибо за пояснения. По мейкфайлу на каждую небольшую лабу пилить как-то излишне, как мне кажется. Разве что сделать универсальный и передавать ему аргументом название си-файла.
> Хотя это ж illegal shit
typeof это такой же иллегал шит. Да еще и ненужный в твоем случае.
> я не хочу кастовать (char ∗)
Кастуй к указателю на uint8_t, но это слегка не по стандарту. А еще лучше заверни в макрос, чтобы не видеть. Что-нибудь типа OFFSET_PTR_BY(ptr, some_value).
> (void ∗)suka + sizeof(typeof(∗suka))
Ты не поверишь, но вместо всего этого говна ты мог написать (suka + 1).
>suka + 1
Это да, я просто для демонстрации, чтоб в одной строчке было видно, что эта часть выражения берется как void.
>макрос
уже на этом остановился, но с большим заточем под задачу. Макросы - это охуенно!
const data;
Сгенерированые судоку;
const data;
}
В Гугле по инфе находятся одни пиндосы из 95-ого и долбоебы с СО
> есть ли в си средства для работы с ПДФ
Своего в Си нет ничего, кроме стандартной библиотеки. Но ты можешь найти в гугле либы или писать PDF вручную, это несложно, можно обойтись одними printf, если не использовать сжатие, встроенные шрифты или картинки. Вон, можешь спиздить минимальную реализацию, например, отсюда: https://forum.pellesc.de/index.php?topic=471.15
вот, бля буду, спроси меня, нахуй я это высрал, хуй я те че внятное отвечу, анон
Как насчёт добавить в шапку? Намного лучше всякие Code Complete читать
Скиньте хоть примеры, как макросами жизнь облегчать, а то может я у себя таким образом могу что-то упростить.
Примеры ограничиваются define zalupa penis ? her : davalka;
return zalupa и хуйней типа define unexpected_error
Вот динамически расширяемый массив.
https://pastebin.com/Xw7su98i
Складываешь в него указатели хоть до Берлина, потом free и дело с концом.
#define swap(a,b) {typeof(a) _t = a; a = b; b = _t;}
Можно всякие километровые касты заворачивать в дефайны. Все в фантазию упирается.
А вот зделол бы счетчики по отрицательным индексам, и можно было бы без вот этих вот ужасных Ls_itm индексироваться.
Тогда надо еще Ls_free делать свой, и указатель придется явно носить как void∗∗, а не просто void∗. Короче, черный ящик ломается. Вообще, это под задачу делалось. У меня возврат указателя в контекст, где не существует чудо-макросов, и там же может понадобиться free. Хавнокод, согласен, не стал для двачей перечесывать.
> In recent versiions of GCC, the inline keyword has two different forms: GNU and C99.
> In GNU mode we can use 'extern inline' to make inline functions work like macros. The function is only inlined--it is never output as a definition in an object file.
> In the new C99 mode 'extern inline' has a different meaning--it causes the definition of the function to be output in each object file where it is used. This will result in multiple-definition errors on linking. The 'inline' keyword on its own (without extern) has the same behavior as the original GNU 'extern inline'.
Посоны, верно ли я понял? Если я компилирую ГЦЦ, то:
1. С флагом -std=c99 inline функция будет подставлять себя в код примерно так же, как макрос?
2. С флагом -std=c99 extern inline функция будет доставлять ошибку, если объектных файлов больше одного
3. Без флага extern inline функция будет работать как макрос.
4. Без флага inline функция будет (а хз что).
> Без флага
Нет никакого "безфлага". Если явно не укажешь стандарт, GCС подставит -std=gnu99 или -std=gnu11, (или что там у него теперь по умолчанию? может даже -std=gnu17), в зависимости от того, насколько он старый. Но это не играет никакой роли, потому что обсуждаемое поведение будет только с явным указанием -fgnu89-inline (может, когда-то было и по-другому, хуй знает).
> The 'inline' keyword on its own (without extern) has the same behavior as the original GNU 'extern inline'.
Наглый пиздеж.
> Без флага inline функция будет (а хз что)
Вот это самый интересный вопрос, как и пункт 1. А будет вот что. Вот такой код:
// main.c:
inline void hello(void) {}
int main(void) { hello(); }
// hello.c:
#include <stdio.h>
void hello(void) { puts("Hello, world!\n"); }
может вывести хелловорлд, а может и не вывести - зависит от компилятора и флагов (в случае GCC - указано ли -O0 или -O1 и выше, причем с -O0 и без hello.c оно там вообще не соберется). Поэтому inline-функции с -std=c99 явно делают static и не выебываются.
> Поэтому inline-функции с -std=c99 явно делают static и не выебываются.
А если функция нужна во всех файлах?
Клади static inline yoba сразу с телом в .h-файл. В худшем случае (если компилятор решит не инлайнить), у тебя будет по одной копии функции в каждом файле, подключившем .h.
Почитал. Эталонный пример плохого стайлгайда. Куча подводных камней в приводимых примерах, куда ни ткни. Да и устарело к тому же.
Это копия, сохраненная 16 июля 2019 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.