Вы видите копию треда, сохраненную 1 ноября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пользуйтесь https://ideone.com/ или http://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 помогает читать сложные сишные декларации.
Прошлые треды:
- №30: https://arhivach.cf/thread/366174/
- №31: https://arhivach.cf/thread/366210/
- №32: https://arhivach.cf/thread/375538/
Проверяй
Ты путаешь легаси и инфраструктуру. А еще си до некоторого предела проще.
Один сделали больше 45 лет назад и он до сих пор нужен, другой сделали недавно и он уже востребован.
Хелоу гайз, счаз усиленно занимаюсь си и всем сопутствующем, очень нравится , но задумался как потом зарабатывать на чистом си , посмотрел вакансии и всем программисты хай лвл языков, понятно что всегда можно писать что то свое на си , но в интерпрайзе что делать то потом ?
странно язык оч крутой , прикольно на нем реализовывать вещи которые есть в других языках , да и вообще удобный
ОП, конечно, некрофил, ты прав. Он пишет на Си фор фуд. Некоторые заказчики ОПа до сих пор не то, что от крестов шарахаются, а даже от C11/C99. Такие дела.
>>54215
В интерпрайзах Си нет, там надо быстро сделать, потом выбросить и снова сделать. В embedded Си востребован, ни про какие расты там не слышали. Но сам по себе, без знания предметной области, Си нигде и никому нахуй не уперся. Впрочем, как и большинство других языков.
Блядь, перестаньте называть язык C clangом, имбицилы. С каких это пор шланг стал единственным компилятором языка, если он не может собрать Ядро.
Ядро, как минимум... Умер твой мозг. C будет еще долго жить, хотя конечно под современные процессоры он не очень явно. Все эти оптимизации компиляторов работают с вероятностью почти нихуя ( 1 / дохуя ).
Никто не называет и не путает с компилятором. Имеется в виду c language, потому что просто "c" - слишком коротко. Тег был добавлен модером для одного из предыдущих тредов, он же прописан в навигаторе в прикрепе. Если есть лучший вариант тега - проси модера исправить.
Я понимаю, но это вам не язык Go, который является глаголом в английском языке. Язык этот слишком стар чтобы его так называть.
Распарсил с третьего раза, думал что-то про асики и прочие верилоги. Алсо, почему анси, а не исо?
никто в здравом уме регулярками на си не парсит, есть Перл и если очень нужно есть Бизон
мимо парсерогосподин
>C будет еще долго жить, хотя конечно под современные процессоры он не очень явно
альтернативы?
Вакансии называются «программист Linux».
жирно
не говоря о его детских проблемах, шанс что он займёт хоть какое то весомое место на интерпрайзер - ничтожно мал, ибо никто не будет переходить на ржавчину, с готовой сишной\плюсовой базы, взаимозаменяемой.
Язык уровня - накатать пет проект
https://www.viva64.com/ru/b/0324/
>Язык уровня - накатать пет проект
Чмошники движок мозилы на него потащили, пизда ей... аж триасет...
Не жирно. В расте как-раз есть явные векторные типы. А это пиздец как важно на сегодня. Не заставлять asm-говновставками векторизацию делать ебясь с выравниванием, и не надеятся блядь на уличную магию компилятора что он ебать не взбредет и не решит что векторизация невозможна.
парсеродобоеб.
Если бы знал хоть теорию немного, то знал бы что лексированием занимается lex (flex).
Нет, ты ехидный и злой, а не любопытный, тебя это не очень-то и интересует на самом деле, ухади.
>Все эти оптимизации компиляторов работают с вероятностью почти нихуя
Ну ты и спец. Т.е разницы между -O0 и -Os у тебя нет?
> никто в здравом уме регулярками на си не парсит
Чем здравый ум Сишника отличается от здравого ума Perl`овчанина или тогоже PHP`девелопера, которые для парсинга везде юзают PCRE, а в PHP так и вообще юзают эту самую libpcre2, только API от Сишного отличается в куда более понятную сторону
У меня вот криптобиблиотека, собранная с -O2 даёт выигрыш в производительности В ДВА РАЗА по сравнению с -О0.
march/mtune юзаешь?
>PCRE — библиотека, реализующая работу регулярных выражений в стиле Perl.
>отличается от здравого ума Perl
>PHP`девелопера, которые для парсинга везде юзают PCRE, а в PHP так и вообще юзают эту самую libpcre2
Неправда.
char andron[] = "sosi"*
static char foo[] = "sosi"; // Строка в секции данных, писать можно (не более sizeof("sosi")). Инициализация при компиляции.
char foo[] = "sosi"; // Вне функции аналогично предыдущему (не считая linkage). Внутри функции: фактически выделяет 5 символов на стеке и инициализирует их символами (т.е., каждый раз при входе в функцию будет делаться strcpy(foo, "sosi")). Зато реентерабельно.
static const char foo[] = "sosi"; // Строка в секции данных, писать нельзя. При использовании foo поведение будет полностью аналогично тому, как если бы ты написал вместо foo сразу "sosi" (обратное в большинстве случаев тоже верно: чаще всего использование строкового литерала создает вот такую переменную в секции данных). Инициализация при компиляции. Наиболее предпочтительный способ, если ты не собираешься писать в строку, но хочешь дать ей имя.
char ∗foo = "sosi"; // Хранит адрес строки из 5 символов, которая лежит где-то в секции данных. Т.е., фактически, это аналогично static const char literalXXX[] = "sosi"; char ∗foo = literalXXX; Правильнее сразу говорить const char ∗foo, потому что писать в литералы нельзя. При доступе к отдельным символам (foo[n]) будет лишний дереференс по сравнению со предыдущим вариантом.
В первые два варианта можно. В последний тоже можно, но только в саму переменную foo, без дереференса.
> Почему?
Ну вот же:
> фактически, это аналогично static const char literalXXX[] = "sosi"; char ∗foo = literalXXX;
Ты не можешь делать ∗foo = 'l' или foo[1] = 'e', потому что это изменение уже не самого foo, а того, на что он указывает, т.е., literalXXX, а он const (и даже если он не const почему-либо в каком-либо компиляторе, писать все равно запрещено). А вот в сам foo ты можешь присвоить другой литерал или другой символьный массив, или другой указатель, никто тебе не мешает:
foo = "xxx";
static const char bar[] = "yyy";
foo = bar;
char baz[6];
foo = baz; // А вот сейчас foo указывает на массив, который можно изменять, поэтому можно:
∗foo = 'h'; foo[1] = 'e'; 2[foo] = 'l'; strcpy(foo + 3, "lo");
> После этой строчки на литерал "ххх" больше ничего не указывает?
Ну, в идеальном мире да. Но, так как в литералы писать все равно нельзя (или, наоборот: нельзя писать, чтобы можно было так делать), компиляторы могут устранять дублирование строковых литералов в секции данных. Вот этот код может трижды напечатать один и тот же адрес:
const char ∗ptr = "xxx";
printf("%p %p %p\n", "xxx", "xxx", ptr);
Мало того, вот этот код тоже может напечатать один и тот же адрес (т.е., если одна строка является концом другой, они могут схлопнуться):
printf("%p %p\n", "hello, world", "world" -7); // 7 = sizeof("hello, ")
>Ну, в идеальном мире да.
Так же можно засрать литералами всю память, а указетелей на них не останется.
Спасибо за отличное объяснение!
>т.е., каждый раз при входе в функцию
Когда именно это происходит?
> указетелей на них не останется
Ну и хуй с ними. Твоя программа все равно в память целиком грузится, и от того, что на литерал есть указатель, или на него нет указателя, размер секции данных не поменяется.
>>56637
> Когда именно это происходит?
Детали реализации. Когда-то после того, как код функции получил управление (т.е., функция была вызвана) и до того, как переменная будет использована. В целом, примерно так:
void foo(void) { char bar[] = "test"; puts("bar"); }
// превратится в:
void foo(void) { char bar[5]; static const literal_test[] = "test"; strcpy(bar, literal_test); puts(bar); }
// естественно, в этом конкретном случае даже хуевый компилятор со включенными оптимизациями сгенерирует:
void foo(void) { char bar[4]; static const literal_test[] = "test"; strcpy(bar, literal_test); puts(barliteral_test); }
Но если bar не только выводить, но и модифицировать, с условиями и т.п., то такое уже не соптимизируешь.
>Но если bar не только выводить, но и модифицировать, с условиями и т.п., то такое уже не соптимизируешь.
Где ты такими заумностями научился? Годы проведенные с дизассемблером и отладчиком?
Здесь есть битовое поле LinkFlags (первый пик), чье последнее значение (второй пик) оставляет 4 пустых бита после себя (третий пик). Надо инициализировать его как unsigned : KeepLocalIDListForUNCTarget : 5 (четвертый пик) или как?
sizeof на массив не работат к сожалению же. Он, вроде, возвращает размер первого элемента массива и все.
Ебать я умный!
Постарайтесь не всирать переменную, в которой храните размер области памяти из кучи, когда выделяете.
> элементами которого является переменные массив
Чо? Переменные типа массив? Или динамический массив? Или VLA?
> Как это будет хранится, как массив указателей или как смещение?
Если ты про int foo[2][3], то оно хранится точно так же, как записано: два массива по три элемента. Элементы массива один за другим, массивы один за другим. Т.е. {{1,2,3},{4,5,6}} -> {1,2,3,4,5,6}. Если тебе нужен массив динамических массивов, то да, ты сделаешь массив либо с простыми указателями на данные, либо со структурами типа data_ptr/elements_used/elements_avail.
>>56738
> sizeof на массив не работат к сожалению же
Есть идиома: #define countof(arr) (sizeof(arr) / sizeof((arr)[0])), она отлично работает, пока ты скармливаешь ей массив (или VLA). Она не работает с указателями, потому что указатель не несет информации о размере. Она не работает для аргументов фукнций типа void foo(int arg[3]) { printf("%zu\n", countof(arg)); }, потому что аргументы функций неявно кастятся к указателям и, естественно, при этом теряют информацию о размере.
>>56707
> Всегда ли будет выполняться условие выхода из цикла ровно, когда кончается массив?
Если ты всегда будешь заканчивать свой массив нулевым элементом. Этот подход имеет право на жизнь. Как заметили выше, он используется для строк >>56791, но его используют не только для строк, а еще, например, для массивов структур, когда нет возможности передать информацию о размере, но есть возможность сделать какой-то невалидный элемент (sentinel), который будет использоваться только чтобы пометить конец массива.
Например, в импортах PE-файла в винде список DLL (массив структур IMAGE_IMPORT_DESCRIPTOR), заканчивается нулевым структурой, инициализированной нулями, а список функций для каждой из этих DLL - массив структур IMAGE_THUNK_DATA, тоже заканчивается нулем. Эти списки генерируются линкером, и из-за особенностей подхода к сборке таблицы импортов, было проще завершать списки нулевыми элементами, чем писать куда-то количество длл и функций.
>>56702
> Надо инициализировать его как unsigned : KeepLocalIDListForUNCTarget : 5 (четвертый пик) или как?
Начнем с того, что не надо пользоваться битфилдами для парсинга бинарных файлов. У нас не далее как в прошлом треде были грабли: где-то около >>1243344. Твой KeepLocalIDListForUNCTarget очевидный однобитовый bool, за которым идут пять неиспользуемых битов. Для KeepLocalIDListForUNCTarget ты делаешь bool KeepLocalIDListForUNCTarget:1 или bit KeepLocalIDListForUNCTarget:1 (хуй знает, как твой bit определен). Затем, если ты целиком и полностью доверяешь компилятору, можешь больше ничего не писать. Если частично доверяешь, можешь сделать безымянный член unsigned:5, явно указав, что 5 бит не используются, или сделать unsigned:0, сказав компилятору, чтобы больше в этот битфилд ничего не пихал.
> элементами которого является переменные массив
Чо? Переменные типа массив? Или динамический массив? Или VLA?
> Как это будет хранится, как массив указателей или как смещение?
Если ты про int foo[2][3], то оно хранится точно так же, как записано: два массива по три элемента. Элементы массива один за другим, массивы один за другим. Т.е. {{1,2,3},{4,5,6}} -> {1,2,3,4,5,6}. Если тебе нужен массив динамических массивов, то да, ты сделаешь массив либо с простыми указателями на данные, либо со структурами типа data_ptr/elements_used/elements_avail.
>>56738
> sizeof на массив не работат к сожалению же
Есть идиома: #define countof(arr) (sizeof(arr) / sizeof((arr)[0])), она отлично работает, пока ты скармливаешь ей массив (или VLA). Она не работает с указателями, потому что указатель не несет информации о размере. Она не работает для аргументов фукнций типа void foo(int arg[3]) { printf("%zu\n", countof(arg)); }, потому что аргументы функций неявно кастятся к указателям и, естественно, при этом теряют информацию о размере.
>>56707
> Всегда ли будет выполняться условие выхода из цикла ровно, когда кончается массив?
Если ты всегда будешь заканчивать свой массив нулевым элементом. Этот подход имеет право на жизнь. Как заметили выше, он используется для строк >>56791, но его используют не только для строк, а еще, например, для массивов структур, когда нет возможности передать информацию о размере, но есть возможность сделать какой-то невалидный элемент (sentinel), который будет использоваться только чтобы пометить конец массива.
Например, в импортах PE-файла в винде список DLL (массив структур IMAGE_IMPORT_DESCRIPTOR), заканчивается нулевым структурой, инициализированной нулями, а список функций для каждой из этих DLL - массив структур IMAGE_THUNK_DATA, тоже заканчивается нулем. Эти списки генерируются линкером, и из-за особенностей подхода к сборке таблицы импортов, было проще завершать списки нулевыми элементами, чем писать куда-то количество длл и функций.
>>56702
> Надо инициализировать его как unsigned : KeepLocalIDListForUNCTarget : 5 (четвертый пик) или как?
Начнем с того, что не надо пользоваться битфилдами для парсинга бинарных файлов. У нас не далее как в прошлом треде были грабли: где-то около >>1243344. Твой KeepLocalIDListForUNCTarget очевидный однобитовый bool, за которым идут пять неиспользуемых битов. Для KeepLocalIDListForUNCTarget ты делаешь bool KeepLocalIDListForUNCTarget:1 или bit KeepLocalIDListForUNCTarget:1 (хуй знает, как твой bit определен). Затем, если ты целиком и полностью доверяешь компилятору, можешь больше ничего не писать. Если частично доверяешь, можешь сделать безымянный член unsigned:5, явно указав, что 5 бит не используются, или сделать unsigned:0, сказав компилятору, чтобы больше в этот битфилд ничего не пихал.
>Если тебе нужен массив динамических массивов, т
Мне нужен массив статических массивов переменного размера, но тратить на него 64бита слишком дохуя, придется пилить массив смещений на буфер данных. И подумать о том, чтобы конпелятор не распидарасил его своим выравниванием.
char buf[512] = "abcd kl jcd wef";
char m1[100], m2[100];
sscanf(buf, format, m1, m2);
Мне нужно, чтобы в m1 оказалось abcd, а в m2 вся оставшаяся часть строки. В реальности оставшаяся часть строки может быть разной, с другим количеством пробелов. Как составить format для такого?
Разве не надо сделать unsigned : 4? Так как у меня меня всего 5 битов, а один занят под KeepLocalIDListForUNCTarget.
И прости за тупой вопрос, что означает именно unsigned в битовых полях?
>Начнем с того, что не надо пользоваться битфилдами для парсинга бинарных файлов.
И как мне тогда парсить подобные структуры? Сделать кучу чаров и вытаскивать биты побитовыми операциями что ли? Я просто новичок в этом деле, особо сказать за это не могу.
> Так как у меня меня всего 5 битов, а один занят под KeepLocalIDListForUNCTarget.
Либо я разучился считать, либо ты.
>>56965
> И как мне тогда парсить подобные структуры?
По-хорошему: читать побайтово, собирать инты размером больше байтов побитовыми операциями, разбирать поля меньше байтов побитовыми операциями. Естественно, не вручную, а делать себе няшный binary stream reader. Но если тебя переносимость не интересует, тогда можно и битфилды из файла напрямую читать, тем более, что студия типа "родной" компилятор.
>Либо я разучился считать, либо ты.
Это я, пересчитал биты и оказалось, что я обосрался.
Но все-таки странно, почему не стоит использовать битовые поля? Они же как раз для таких задач вроде и создавались.
char i[1000];
int c;
for (int k=0;(c=getchar())!= '\n'; ++k,i[k]=c);
printf("%s",i);
После того как поменял местами заработало, но в чем была проблема? Понятно конечно, что i[0] не присваивалось значение, но разве это проблема?
Сделай вот так i[k++] = c - это короче и читабельнее.
А не работало, так как у тебя сначала увеличивалось, а затем уже присваивалось значение, то есть пропускались элементы массива i.
Когда хочешь, чтобы функции была передана сама переменная, когда инициализируешь динамические массивы, когда создаешь связанные списки, когда итерируешь по массиву, когда выделяешь память в куче, когда небеса.
Спасибо.
Во-первых, что ты собрался с чем объединить.
Если бы строковый литерал с указателем на строку, то зачем разыменовывать?
Во-вторых, конкатенация литералов происходит на раннем этапе компиляции, на твой i всем насрать там.
Ну вот в таких-то случаях можно было inline-функцию вметсо макроса сделать.
В чём фишка макросодрочерства? Ты демонстрируешь, что ты олд?
скопировать всё в массив -> qsort -> обратно в список
>printf(“%c",CHR)
И нахуй ты printf используешь для одной буквы?
static inline void printch(unsigned i, char c) (while(i--) { putchar(c); })
Лол, никто не будет так делать.
> почему не стоит использовать битовые поля
Из прошлого треда:
> компилятор может выделить под элемент char, а может и int, может начать заполнение со старшего бита, а может с младшего
Использовать битовые поля стоит, но не стоит напрямую читать-писать их из файлов или сокетов, если предполагается какая-никакая переносимость программы.
>>57151
> Я хотел, чтобы пробел был напечатан i раз
Следи за руками: printf("%*s", i, ""); но это работает только с пробелами. Умножения для строк, как в питоне, в Си нет.
Как заебали эти "адепты стандарта", у которых в байт может быть не 8 бит, просто иди нахуй.
Сам иди. Я писал под DSP с 16-битными байтами, сосалписал под big-endian, периодически отсасываю у alignment requirements на разных процах, а в прошлом треде был кун, у которого битовые поля из Праты распидорасило. А ты продолжай думать, что переносимость - это когда линукс под пеку и малинку.
>периодически отсасываю у alignment requirements на разных процах
Я тоже, но большинство программистов не столкнутся с нее восьмибитными байтами, так что тыкать и носом в стандарт необязательно.
В пизду иди сука ебливая, в рот тебя ебал макросами.
Поясните наконец анону про goto
Чем чуханью оно так не приглянулось? Это ж жесть как удобно и не затратно по ресурсам. "Плохой тон" программирования? Лол што блять? В asm есть целая директива jump через которую работают циклы и переходы, с хуя ли ее аналог в Си есть зло?..
> Чем чуханью оно так не приглянулось?
Давным-давно был язык BASIC, в котором тогда не везде был даже GOSUB (вызов подпрограммы). Код на бейсике представлял из себя мешанину из 100 IF COND GOTO 210, был абсолютно нечитаем - фактически для его модификации приходилось реверсить все эти хитросплетения потока выполнения. Поэтому, с появлением структурного программирования (в том числе и в бейсике) нужно было как-то запугать существующих программистов, чтобы больше не видеть этой лапши. Тогда Дейкстра написал свою знаменитую статью, а потомки, не сильно вспоминая, в какое время она была написана, проклинают GOTO до сих пор. С тех пор появилось много последователей с %фичанейм% considered harmful - например, if considered harmful и даже considering harmful considered harmful. Не превращай классические статьи в религию, и все будет норм.
> Это ж жесть как удобно и не затратно по ресурсам.
Если тебе удобно, чаще всего это означает, что ты не осилил структурное программирование. Есть простой детектор: если ты хочешь сделать goto вверх или внутрь { блока } - ты что-то делаешь не так. В Си goto не зло, а вполне себе используемая фича с минимум двумя основными юзкейсами:
1) goto error_handler/release_resources/итд в конец функции, чтобы не писать глубоко вложенную лесенку из if (если if-ов всего пара, и новых не предвидится, тогда goto - говнокод).
2) goto outside_loop для выхода из вложенных циклов (обычно можно выделить циклы в отдельную функцию и заменить goto на return, но если почему-то нельзя - пользуются goto).
> В asm есть целая директива jump
Но ты-то не на асме пишешь, тебе дали язык для людей. Алсо, не директива, а инструкция/мнемоника. Директивы управляют поведением транслятора и в объектный код не попадают.
> в питоне нет такой херни
Ты лишь наполовину прав. С одной стороны, в питоне абсолютно все сущности, до которых ты можешь дотянуться - ссылки (т.е., точно такие же указатели на объекты, как и в Си, только всегда валидные). С другой стороны, в питоне и правда нет двойных указателей, т.е., не получится сделать foo = 123; def func(arg): arg = 456 так, чтобы при вызове func(foo) оно меняло foo, но можно сделать костыль, обернув это в какой-нибудь композитный тип, сымитировав таким образом указатель на указатель с помощью ссылки и индекса:
def func(arg):
# Тут (неявно, при обращении к любой переменной) по ссылке на arg
# сначала берется объект массива, а потом по индексу 0
# пишется (ссылка на) значение.
arg[0] = 456
foo = [123]
func(foo)
print(foo[0])
>>58440
Было на сайте, было на вебархиве, но выпилено отовсюду (и слава богу). Есть на торрент-трекерах ("Learn C the Hard Way[ 2015[X7]" в гугле с кавычками). Но лучше возьми Прату.
А всё, нашёл, сорян.
> Может ктонибуть набросать простой пример как юзать pcre2_substitute?
>>54519
> так и некто и не помог мне с pcre2_substitute :(
Всего две недели ебли, и я сам себе помог, спасибо анончики, понял как это говно юзать, если кому надо вот накатал пример:
https://pastebin.com/AHm7gkwK
Я всего глазком видел С и не знаю CUDA.
Но мне всего-то нужно сделать простенькую программу для вычисления длинных чисел, что-то вроде (или чуть сложнее):
While True:
x=+1
y=cos(x)
If y целый или количесто нулей после запятой огромно до других чисел, тогда:
записать значение в лог
Только числа должны быть очень длинные, желательно без ограничений вообще или много много знаков. Поэтому проблема с float итп.
Поэтому ещё мне и понадобился C/CUDA - для ускорения расчётов.
Искать нужно бы в диапазоне, а то компьютер у меня всего один и одна видеокарта. Т.е. x должен задаваться диапазоном (просто от и до).
Все найденные числа должны записываться в лог, при этом это действие НЕ должно приостаноавливать поиск чисел.
И подозреваю, что искать я буду, как минимум неделями, вероятно, буду перезапускать не раз, поэтому не плохо бы, чтобы программа хотя бы иногда записывала во второй лог одно число, какое сейчас число перебирается, чтобы я потом просто передал это число программе и она начала с него.
+ Ещё неплохо сделать опцию - процент нагрузки на железо, ну чтобы графика не лагала, чтобы не горел проц и видяшка итд. Тоже передавать параметром при запуске программе.
А что там не понятно?
Подскажите, как написать кастомный printf и зачем это может понадобиться?
Знаю, что используется write(), но пока недостаточно разбираюсь, чтобы толком поисковый запрос сделать.
А либы есть готовые, чтоб было всякое наследование (не множественное), полиморфизм, и прочее ооп?
Плюсы мне не нравятся, там слишком много лишнего говна, да и все сторонние библиотеки, которые я юзаю для разработки, написанны на чистом Си, инклюдить их к Цпп не вижу смысла, плюс разрабатываю в основном под разный эмбеддед, и Си туда проще компилить чем цпп, мень ше гемора
> Подскажите, как написать кастомный printf
https://ideone.com/9r6T6x - обрабатывать форматную строку, получать аргументы с помощью va_arg, преобразовывать их в строку и выводить. Или вот я когда-то видел формировалку сетевых пакетов, формат ей так же printf-like синтаксисом задавался, а она вместо текстового представления делала из всяких интов и флоатов big-endian слова, а перед строками втыкала длину.
> и зачем это может понадобиться?
Например, сделать поддержку [color=red]text[/color] и преобразовывать такие вещи в ANSI-последовательности в линуксах или вызовы SetConsoleTextAttribute в винде.
>>59363
Оно и на английском-то не нужно. Обычно достаточно одного уровня наследования (common object->specific object, а чаще всего это даже просто linked_list_header->payload) и изредка какая-нибудь наколеночная табличка с методами. И никаких макросов.
>Например, сделать поддержку [color=red]text[/color] и преобразовывать такие вещи в ANSI-последовательности в линуксах или вызовы SetConsoleTextAttribute в винде.
Not bad.
>Оно и на английском-то не нужно. Обычно достаточно одного уровня наследования (common object->specific object, а чаще всего это даже просто linked_list_header->payload) и изредка какая-нибудь наколеночная табличка с методами. И никаких макросов.
Этот шарит.
2. Для чего нужен си кроме академических целей и низкоуровневой боли?
>Почему это работает?
Потому что тебе повезло и мусор в указателе не указывал на несуществующую страницу.
> низкоуровневой боли?
Именно. Драйвера/OS/микроконтроллеры.
можна, токо паламается моцк
И криптография ещё.
Ты попробуй так со структурой или массивом сделать. Сегфолт обеспечен на 100%.
Есть типы данных int,float,char и т.д.
Временные переменные обязательно объявляются вместе с типом. Когда до мэйны мы объявляем константу типа #define NUMBER 10 - то компилятор автоматически понимает, какой тип данных соответствует 10. Вопрос - нахуя тогда еботня с временными переменными?
Дефайн это не константа, и не тип данных, даже не переменная, дефайн это макрос.
Допустим у тебя есть #define ten 10
Препроцессор буквально идёт по всему коду и везде где у тебя написано ten заменяет ten на 10.
Ааааа, хмм, но всё равно непонятно, зачем нужна тогда еботня с типами данных, если можно так.
Ебать удобно будет такой код читать конечно.
Я гуидятину на Qt писал
Вообще, иногда просто удобно.
Мне вот недавно надо было скрипт на баше выполнить, но скипнуть всю серединку. Комментить всю эту кучу не хотеелось, обрамлять как тело другого оператора - тоже. Было бы классно выполнить начало, а потом сделать goto в конец, но не завезли. Пришлось переделывать в другой скрипт.
На Си ты можешь #if 0 ... #endif
За деньги можно поиметь любую лучшую писечку, и купить покушать заодно
Потому что auto в Си - это storage class для автоматических переменных, т.е., таких, которые удаляются при выходе из области видимости. int main(void) { auto int foo = 1; printf("%d\n", foo); } Обычно никто не пишет auto явно, потому что переменные, определенные внутри функций, уже по умолчанию автоматические. А вот крестах, куда auto пришло из Си, реюзнули ключевое слово для автоматического вывода типов, там можно auto foo = 1.
int func(int *a, int size)
{...}
int main()
{ func({1,2,3,4}, 4); }
Так как я написал нельзя. Но может существует другой синтаксис?
Можно, называется compound literal, появилось в C99: func((int[]){1,2,3,4}, 4). К сожалению, В этом случае тебе придется считать количество элементов вручную или дублировать литерал, что еще хуже: func((int[]){1,2,3,4}, sizeof((int[]){1,2,3,4}) / sizeof(int)); но для простых случаев очень удобно.
Благодарю.
посоветуйте как научиться работать с графикой в си , то есть прям понять что и как
а не qt юзать
Ну так window manager глянь исходники. Линуксовых с открытым кодом точно есть.
Си - никак не рисует. В его стандартной библиотеке GUI нет. В ней вообще мало что есть. А рисует или графическая либа, или GUI либа, или иногда ОС через API. Qt, например, берет у ОС только окно, а кнопочки внутри него рисует самостоятельно. На Windows API ты можешь попросить винду рисовать в том числе и кнопочки. В линуксах ты можешь попросить Gtk+ рисовать кнопочки. А можешь взять какую-нибудь левую либу типа Nuklear, взять OpenGL и рисовать кривые кастомные кнопочки. Еще ты можешь взять только графический апи и самостоятельно рисовать свои кнопочки, графику и самостоятельно же реагировать на события, изобретая свою GUI-библиотеку, попутно охуевая от объема требуемого для этого кода.
Капай опенГЛ. Там верхнее апи это сишное апи для макак. Заодно начнешь в графическом конвеере разбираться, битковлены майнить
пожалуйста милипиздрическое
Там часть функций выводит симметричную матрицу как верхнедиагональную (а значения под главной диагональю не трогает). Как потом с этим работать? Написать функцию, которая прописывает элементы под диагональю?
Например, пусть есть 2 матрицы:
A = {{1,2}, {2,3}}
B = {{2,3},{3,4}}.
Хотим посчитать (AT×A)×(B×B).
Кусок кода:
gsl_blas_dsyrk(CblasUpper, CblasTrans, 1.0, A, 0.0, ATA);
gsl_blas_dsyrk(CblasUpper, CblasTrans, 1.0, B, 0.0, BTB);
gsl_blas_dsymm(CblasLeft, CblasUpper, 1.0, ATA, BTB, 0.0, ATABTB); // Это не работает.
(Aᵀ·A) = ATA = {{5, 8}, {0, 13}} -- ок, gsl_blas_dsyrk вернул симметричную матрицу как верхнедиагональную.
(Bᵀ·B) = BTB = {{13, 8}, {0, 25}} -- Ок.
(Aᵀ·A)·(Bᵀ·B) = ATABTB = {{65, 290}, {104, 469}} -- А это неправильно.
1. Есть переменная:
char delimiter[4] = "\n";
2. Есть её вывод
printf("%s", delimiter); //выдаёт CRLF
3. Есть аргумент -d \t
4. Далее, в цикле - следует это:
sprintf(delimiter, "%s", argv); //где argv - это "\t" c аргумента "-d"
5. Дальнейший вывод printf("%s", delimiter);
выдаёт два символа "\t", а не символ табуляции.
Полагаю "\\t" в argv. Как сделать Unescape?
http://rextester.com/KFH11573
Сделал так, для однобайтного разделителя: http://rextester.com/PZTCBT99810
А вообще вопрос о том, как передать escaped string в переменную,
сделав при этом unescape, и этот вопрос - остаётся открытым...
Манька, твои эскэпе символы во время конпеляции заменяюися аски немечатными эквивалентами, а в аргументы ты передаешь аски строки, пиздец...
Пиздатую распиздатую
Есть регион shared memory, несколько процессов имеют к нему доступ. Как им обращаться к семафору?
https://www.systutorials.com/docs/linux/man/3-sem_init/
Тут написано следующее:
>Initializing a semaphore that has already been initialized results in undefined behavior.
Каким образом тогда синхронизировать их инициализацию? Я не моуг сказать одному процессу, чтоб он создавал семафор, а все остальные чтоб читали.
Про sem_open() знаю, но интересует именно описанный подход.
Там охуеть какая сложная функция: если встретил \, то делаешь свитч по известным символам. Если ни с чем не сматчилось, в default свитча выводишь как есть.
> Про sem_open() знаю, но интересует именно описанный подход.
А почему тебя интересует именно он, если он тебе не подходит? Это для форкающихся процессов, когда процесс может сделать инит и нафоркать себе потомков.
Потому что он использует shared memory, а он мне как раз и нужен для синхронизации вокруг shared memory. Спасибо за пояснение, всё понял.
Привет, пишу на жс, хотел бы для общего развития обмазатся сишкой, порикоминдуйте книжку.
Прата, в шапке. Или K&R. Или обе.
Смотрите, есть у нас char. Это численный тип для хранения кода символа. Но мы же можем запихнуть и просто число и использовать его как тот же int в арифметических выражениях, правильно?
Так вот, как быть со знаком? Принято считать, что он по-умолчанию знаковый как с интом и беззнаковость указывать явно? Допустим, есть функция, которая принимает две строки.
Я хочу их посимвольно сравнить и пишу что-то типа while(✯a++ == ✯b++)
ну и вывести разницу, если не равны.
Нашел, что в реализации strncmp делают приведение к типу (unsigned char) и разименовывают с приведением. Но зачем?
В каких случаях мое сравнение без приведений даст сбой?
void alltolower(char♥ src) {
while(♥src) {
if (src[0] >= 'A' && src[0] <= 'Z') src[0] += 32;
src++;
}
}
Сталкивался с мнением, что наборы строчных и прописных буков могут отличаться не на 32 или еще какие-то последствия могут быть, короче, не советуют. Рассудите, кали ласка.
И в этот же вопрос. Я нашел такую табличечку: https://en.cppreference.com/w/c/string/byte/isprint
Там в колонке isprint, например, видно, что все значения от кода 32 до кода 126 включительно true (даже пробел с какого-то перепугу), можно ли теперь делать свою проверку как (c >= 32 && c <= 126)?
Извините, если задолбал нубовопросами, тогда просто ткните носом, где именно это читать (всего Прата прочту обязательно, но потом, а тут сдавать срочно).
А, пардон, ты про это.
>while(✯a++ == ✯b++)
Ты можешь только один символ инкрементировать. Пикрелейтед.
На, вот с этим поиграйся: http://rextester.com/BBL45561
> Принято считать, что он по-умолчанию знаковый
В отличие от инта, по умолчанию он хз какой, и если тебя волнует знаковость или беззнаковость - надо указывать. Фактически в известных реализациях он signed.
> Нашел, что в реализации strncmp делают приведение к типу (unsigned char)
> Но зачем?
Это делается, чтобы результаты strcmp не противоречили результатам memcmp (за исключением особой обработки \0). memcmp сравнивает unsigned байты, и если strcmp решит, что (char) -1 < (char) 1, то возникнет противоречие, потому что (unsigned char) 0xff > (unsigned char) 1.
> В каких случаях мое сравнение без приведений даст сбой?
-1 - 1 = (int) -2 vs. (unsigned char) -1 - (unsigned char) 1 = (int) 255 - (int) 1 = (int)
>>62270
> Сталкивался с мнением, что наборы строчных и прописных буков могут отличаться не на 32
254
Компьютеры, где так было, давно вымерли. Но x += 'a' - 'A' банально читаемее.
> можно ли теперь делать свою проверку как (c >= 32 && c <= 126)
Можно, но isprint() читаемее. Плюс он зависит от локали, если она не "C". iswspace() тоже руками писать собрался?
> даже пробел с какого-то перепугу
Для непечатаемых символов у терминала может быть специальное поведение. Печатаемые выводятся как есть. У терминала есть специальное поведение для пробела?
%s : Scan a character string. The scan terminates at whitespace. A null character is stored at the end of the string, which means that the buffer supplied must be at least one character longer than the specified input length.
https://www.tutorialspoint.com/c_standard_library/string_h.htm
еще есть strtok для других разделителей
Кириллицу получилось распечатать, но помимо неё там ещё такое попадается: ���
Есть какой-нибудь диапазон значений для условия, чтобы эту хрень не выводило?
Нихуя не понял, но сходи в вики посмотри, как UTF-8 устроен. Вкратце, ты можешь в поисках начала UTF-8 символа пропускать все байты, у которых (x & 0xc0) == 0x80.
__нет,_столкнуться __прошу_привести_пример из Ядра.
парсер сожрал пробелы в " ", их там было много, а выводится будут столько сколько указанно в i
Я хочу сделать strdup и strcat джва в одном. Принимаю две строки и возвращаю новую, содержащую обе подряд.
Памяти мне нужно strlen первой плюс strlen второй плюс 1 байт на нолик в конце. Всё верно?
И может ли на какой-то архитектуре char быть не 1 байт?
> Я хочу сделать strdup и strcat джва в одном
asprintf(), оно нестандартное, но много где есть.
> Памяти мне нужно strlen первой плюс strlen второй плюс 1 байт на нолик в конце. Всё верно?
Да.
> И может ли на какой-то архитектуре char быть не 1 байт?
Нет.
Спасибо. А что значит много где есть?
Я привык в плюсах, что могу писать sizeof(int) и получать размер инта. А как в чистом си, нужно включать какой-то заголовочный файл или тоже можно везде писать и рисков с портабельностью нет?
Ты тупой.
> А что значит много где есть?
Это значит, что оно вроде как во фре появилось, но всем очень понравилось, и другие разработчики тоже завезли в свои либц. Даже если asprintf нет, его легко реализовать самостоятельно, пользоваться им удобнее, чем strcpy/strdup/strcat, а оверхед на парсинг форматной строки редко критичен.
> могу писать sizeof(int) и получать размер инта
Ну так и пиши, и получишь, в чем проблема-то?
> нужно включать какой-то заголовочный файл
limits.h, если тебе нужно знать не размер, а максимальные-минимальные значения.
Под linux/* разве не хедеры для модулей ядра лежат?
У компилятора по дефолту может не быть этого пути в include_path.
Анон, смотри: на картинке, обрабатываются 64-битные числа - в 32-битной Windows XP!!!
Ахххах, бля! :3
Модератор, затери путь!
Я тебе даже portable MSPaint.exe могу скинуть - вот тут он лежит:
http://www.oldversion.com.ru/windows/microsoft-paint-xp
Кстати, в исходном коде используется
#include <inttypes.h>
а также uint64_t
Вот исходник: http://rextester.com/FMRL5648
Всё работает в XP, наверное потому, что процессор поддерживает x64.
А компелировал обычным gcc, но для 32-битных систем нужно указать ключ -m32
>gcc -m32 -o count_strings.exe count_strings.c
Сява, мы и без тебя это знаем.
> Всё работает в XP, наверное потому, что процессор поддерживает x64.
Проиграл. Нет, работает в XP потому, что 64-битные числа можно обрабатывать как пару edx:eax, что, собственно, гцц и делает. А можно вообще точно таким же макаром запилить арифметику произвольной точности.
setjmp()/longjmp() позволяют выпрыгнуть наружу, а не впрыгнуть внутрь. Покажи лучше код, наверняка там ни гото, ни longjmp не нужны.
Спасибо. Всё так и получается. Сорь, не могу сурц показать. Закрытый проект. Просто в нём break завершит лишь выполнение функции и вернётся, если условие наступит на уровень выше и всё закончится. У меня это для критического участка, что если что-то утекать начнёт, то это максимально быстро всё остановит и прыгнет в другую функцию. Я знаю, что там можно через несколько уровней вложенности функций разрешить эту проблему, но очень сильно читаемость ухудшит, а мне же этот проект потом ещё долго пилить и через полгода возвращаться обратно. Хотя может тогда поумнею и пойму как разрешить этот кривой прыжок.
>64-битные числа можно обрабатывать как пару edx:eax
Так, насколько помню - BigInteger'ы считают, там длинная арифметика тоже к простым действиям сводится.
Но x64 тем и лучше, что позволяет одной инструкцией ассембера 64-х битные числа считать, а не двумя как эта пара 32-х битных.
Я слышал давненько, что в процессора даже специально заводят отдельные логические схемы для AES256,
и замыкают их на одну инструкцию, чтобы быстро потоковое шифрование-дешифрование делать.
Если так смотреть на это, то процессора эти - вообще 256-битные. Но конечно же эти схемы не универсальны, а специфичны...
8096 запили с пруфами, а то я видел RSA-ключи для PGP и SSH такой длины.
Наверное же не без причины так длину ключа загнули...
Можно и через BigInteger считать, но лучше и быстрее - организованной и оптимальной
последовательностью стандартных инструкций.
В си нет ссылок.
Спасибо за дельный ответ.
Ты, наверное, имел ввиду 8192. Но зачем?
Для RSA-то понятно, но свою математику я использовал для эллиптической криптографии, а там в основном ключи 256 / 512.
НАМНОГО лучше. В своей либе мы отказались от поддержки 32-бит в принципе. Вернее, старая реализация осталась, но новая пилилась только под 64. Просто потому что намного быстрее и намного удобнее.
> Антоны, решился писать дрова под винду. Кто-нибудь имел опыт с этим? Что качать и где?
https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk
Здесь написано что WDK входит Studio 2017, но почему-то его нет!
Карацуба и монтгомери. Слижи исходники у OpenSSL. Они на этом собаку съели (пару CVE поймали для случая с AVX-512)
Уже давно прикручено и производительность я получил феноменальную. Каратсуба для 512 бит не нужен.
Прикручено - это я про монтгомери.
AVX-512 классная штука, но мало где есть, мне разрешили только avx и avx2 использовать.
Отлично, молодец. Действуй именно через эти алгоритмы когда есть операции умножения огромных по битности чисел, возведения таких чисел в степень с взятием остатка. На данный момент это самый эффективный способ реализовать RSA. AVX регистры операции, то ладно, а вот что делать для ускорения того же кода на ARMv8 - писать под NEON(!). Вот почему я и топил за раст как за язык с явной векторизацией, так как никакой компилятор тебе гарантировать не может что он без явного интринсика или asm-вставки будет использовать SIMD, а все эти интринсики стоят переносимости до момента пока их в стандарт не запихнули.
Второй момент - реализовывать для прикладных проектов сегодня кривули - стоит. Причина проста - они меньше по размерам операндов, и немного так быстрее, вот только - нужно с особой осторожностью это делать: Juniper также съели на этом говна.
>так как никакой компилятор тебе гарантировать не может что он без явного интринсика или asm-вставки
Собственно, большую часть арифметики я на асме и писал, потом линковался.
Но зачем ебать RSA (с ключами, стремящимися к одноразовому шифроблокноту) если есть эллиптическая криптография с ключами в 10 раз короче при той же надежности?
Собственно, изначальный автор как раз эллиптическую и реализовал, но отвечающие почему-то начали упоминать rsa.
Вот преимущества слабой типизации!
> 256 же
Блядь, вот когда написал, так и подумал, что кто-нибудь обязательно возведет и решит, что это про биты. Да, оно GF(256), но в форме GF(28) нагляднее: 8 - это степень полинома, у коэффициентов которого арифметика по модулю 2. Т.е., это 8-битный байт с XOR в качестве сложения-вычитания и хитровыебанными умножением и делением (тоже по модулю).
> И да, там по всей группе значения перемешиваются.
Это ближе к SIMD.
Long c=5,d=100; //допустим лонг 4 байта
И если вызову printf(“%ld %ld %ld”,a,c,d); то первые двачисла будут выведены рандомные а третье выведенное число будет выведено правильно. Разве не должно быть типа первый %ld читает последние 32 бита из стека, и вторые два %ld читают еще по 32 бита из стека и по идее вроде как должно выводить первое число рандомно но два последних правильно хотя на деле так как я выше написал. В общем подозреваю во всем то что не понимаю что такое стек и как работает, выручай анон
Ты понимаешь, что такое стек. Но забываешь, что у тебя там наверняка 64-битный код, а 64-битные конвенции вызова передают часть аргументов через регистры. Подробнее https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions или просто на годболте смотри дизасм.
>Ты, наверное, имел ввиду 8192.
Да.
>Но зачем?
Как тут:
https://www.thechiefmeat.com/pgp/
>Для RSA-то понятно, но свою математику я использовал для эллиптической криптографии, а там в основном ключи 256 / 512.
Если это действительно арифметика произвольной точности (точность которой задана),
то она подойдёт для чего угодно ввиду своей универсальности.
Главное чтобы с числами такой длины можно было оперировать быстро, производя при этом с ними - все основные арифметические операции,
из которых потом как из инструкций могут комбинироваться n-битные программы.
>>63524
>каратсуба
>>63583
>Карацуба и монтгомери. Слижи исходники у OpenSSL. Они на этом собаку съели (пару CVE поймали для случая с AVX-512)
Там где можно ускорить операции, чё бы и не ускорить их.
Но ИМХО, качественно написанная n-битная арифметика - уже должна быть оптмальна по коду и скорости, сама по себе.
>>63584
>Каратсуба для 512 бит не нужен.
И вот здесь где-то, у этого, должен быть пример 512-битного умножения не хуже карацубы.
>>63583
>Прикручено - это я про монтгомери.
А у тебя алгоритмы Монтгомери быстрее работают, чем на арифметике?
>>63604
>Но зачем ебать RSA (с ключами, стремящимися к одноразовому шифроблокноту)
>если есть эллиптическая криптография с ключами в 10 раз короче при той же надежности?
>>63605
Потому что ключей длиной 8192 бит в эллиптической криптографии - я ещё не видел, только в RSA.
И да, кстати, а разве на эллиптической кривой можно шифровать?
Насклько я знаю есть только ECDSA так это дело - для цифровой подписи лишь годится,
а дальше уже идёт потоком - симметричный AES от SHA256-хэша например...
Симметричная криптография, типа AES расшифровывает тем же ключём, что и шифрует,
а значит перехват ключа вскрывает шифр.
В то время на RSA реализуется асимметричная криптография!
То есть - одним ключём (публичным) шифруешь, другим же (приватным) расшифровываешь.
На сайте выше есть яркий пример асимметричной криптографии.
>>63690
>Т.е., это 8-битный байт с XOR в качестве сложения-вычитания и хитровыебанными умножением и делением (тоже по модулю).
Хочешь сказать, что GF(28) = GF(256) как и байт имеет лишь 256 состояний?
Посмотри лучше на Число возможных различных состояний кубика Рубика
(8! 38-1) (12! 212-1) 2 = 43 252 003 274 489 856 000, то есть более 43 квинтиллионов комбинаций.
>Ты, наверное, имел ввиду 8192.
Да.
>Но зачем?
Как тут:
https://www.thechiefmeat.com/pgp/
>Для RSA-то понятно, но свою математику я использовал для эллиптической криптографии, а там в основном ключи 256 / 512.
Если это действительно арифметика произвольной точности (точность которой задана),
то она подойдёт для чего угодно ввиду своей универсальности.
Главное чтобы с числами такой длины можно было оперировать быстро, производя при этом с ними - все основные арифметические операции,
из которых потом как из инструкций могут комбинироваться n-битные программы.
>>63524
>каратсуба
>>63583
>Карацуба и монтгомери. Слижи исходники у OpenSSL. Они на этом собаку съели (пару CVE поймали для случая с AVX-512)
Там где можно ускорить операции, чё бы и не ускорить их.
Но ИМХО, качественно написанная n-битная арифметика - уже должна быть оптмальна по коду и скорости, сама по себе.
>>63584
>Каратсуба для 512 бит не нужен.
И вот здесь где-то, у этого, должен быть пример 512-битного умножения не хуже карацубы.
>>63583
>Прикручено - это я про монтгомери.
А у тебя алгоритмы Монтгомери быстрее работают, чем на арифметике?
>>63604
>Но зачем ебать RSA (с ключами, стремящимися к одноразовому шифроблокноту)
>если есть эллиптическая криптография с ключами в 10 раз короче при той же надежности?
>>63605
Потому что ключей длиной 8192 бит в эллиптической криптографии - я ещё не видел, только в RSA.
И да, кстати, а разве на эллиптической кривой можно шифровать?
Насклько я знаю есть только ECDSA так это дело - для цифровой подписи лишь годится,
а дальше уже идёт потоком - симметричный AES от SHA256-хэша например...
Симметричная криптография, типа AES расшифровывает тем же ключём, что и шифрует,
а значит перехват ключа вскрывает шифр.
В то время на RSA реализуется асимметричная криптография!
То есть - одним ключём (публичным) шифруешь, другим же (приватным) расшифровываешь.
На сайте выше есть яркий пример асимметричной криптографии.
>>63690
>Т.е., это 8-битный байт с XOR в качестве сложения-вычитания и хитровыебанными умножением и делением (тоже по модулю).
Хочешь сказать, что GF(28) = GF(256) как и байт имеет лишь 256 состояний?
Посмотри лучше на Число возможных различных состояний кубика Рубика
(8! 38-1) (12! 212-1) 2 = 43 252 003 274 489 856 000, то есть более 43 квинтиллионов комбинаций.
Я начал писать нужную себе программу и слегка подохуел от нужного, но, в целом, лишнего кода, если бы я писал в любом другом достаточно популярном сегодня языке программирования.
Я пишу достаточно плохо, поэтому два дня я провёл разворачивая сегфолты. При этом Си для меня единственный на данный момент язык, в котором я чувствую себя уверенно.
Ну или скажите, как вы эту тему осваивали?
Пишу прототипы на питоне, рано или поздно перекатываюсь на сишечку, мне норм. Кресты не нравятся, больше выбирать не из чего.
>>63902
> что там под капотом, как это всё работает
В K&R реализовывали кастомный аллокатор, посмотри. Для начала сойдет, потом подумаешь про эффективную реаллокацию, фрагментацию кучи и всю хуйню.
> как его можно улучшить
Тема на очень толстую книгу.
Руст
Можно ли как-то сделать, чтобы файл записался после
>system("pause");
?
Сунул её чтобы окно не закрывалось, когда двойным кликом по exe запускаешь,
но только после нажатия кнопки или после закрытия окна файл записывается и видно контент...
Надо сделать так, чтобы до pause - он уже записался.
>что там под капотом
Для линуха это системные вызовы brk (передвигает границу разрешённой кучи для малых аллокаций) и mmap (мапит дохуя памяти страницами, для большой ёбы)
Поверх этой выделяемой памяти программно реализована хуйня на каких либо структурах данных, которая сохраняет инфу об освобожденной памяти и позволяет переиспользовать куски подходящего размера не прося OS выделить больше. Реализация этой хуйни зависит от кода конкретной реализации стандартной библиотеки. Современные достаточно сложные, как можешь убедиться:
https://github.com/lattera/glibc/tree/master/malloc
Не-а, всё равно надо клавишу нажимать или окно закрывать. Иначе - в файле пусто...
Хэххэх.
Сначала подумалось что он фитиль какой-то зажёг, показывая на понтах как стартует Falcon9,
затем чё-то показалось что это кальян - оказалась сигара "с травкой" по словам Джо Рейгана...
Там, внутри травы, насколько я знаю есть тетрагидроканнабинол, принадлежащий более широкому классу вещество - терпеноиды.
Многие из них проявляют свойства антиоксидантов, и противоопухолевых препаратов.
Их даже рассматривают как потенциальные геропротекторы.
>>64130
https://www.libsdl.org/download-2.0.php
Для сишки лучше варианта нет, поддерживается везде, есть в репах, в стике куча игр написанных таким образом, даже под steamos вальвы обновляют.
Я лично проходил эти туториалы и билдился с gcc, несмотря на то, что автор использует g++. Код весь сишные, либа написана на си и в первую очередь для использования с си (хоть и не только).
Брат жив.
мне вот интересно - а как писались игры на С во времена доса без всяких этих API?
Всегда было какое-то апи.
А до него рисовали командами "покрась точку 32:16 в цвет 114.
Вон, в играх на пс1 (писались на си) через контроллер, замаппленный на участок оперативки, передаются группы байт, являющиеся командами "нарисовать примитив такой-то с координатами такими-то". Но и это упаковывалось в некоторое апи в виде стандартной библиотеки пс1.
CreateWindowEx/XCreateSimpleWindow
Осталось начать дебажить и писать код на листке.
>Выкинуть SDL и накидать создание окна вручную.
Это ж ебануться можно - писать таким образом кроссплатформу.
Хотя это никакая не кроссплатформа уже.
> Хотя это никакая не кроссплатформа уже.
Из коробки кроссплатформенными бывают только хелловорлды. Для чего-то более сложного всегда нужны куски кода под конкретные платформы.
Понимаю что кодить лучше в тишине, но у меня нет такой возможности
Драм энд бэйс.
>Пишу на си и плюсах
Пруф или не было.
>Замазал языки и скинул своей тян
А она тебя добавила в чс, потому что такую хуйню только конченый олигофрен скинет. Хотя какая тян, кому ты пиздишь?
>Вышло, что я перл
Вышло, что ты пёрнул в тред, пидор гнойный.
Что с тобой не так?
Без знания высшей математики? В НИИ? Точно?
Ну ты дурак или родом так? Чтобы ответить на твой вопрос проще книгу написать.
Бля, ну давай моё мнение с моей скромной колокольни. Есть фразочка на хабре вроде гуляет: "на с++ я могу написать всё что угодно... На Си я могу написать с++" На си писали отцы. Линукс написан на сях чистых. Так что щитай, что большая часть интерената функционирует за счёт чистых сей. Я вот лично думал как организовать полиморфизм в сях. И ничего кроме вызовов функций по объединениям в качестве агрументов не придумал. Хотя это костыльное, как мне кажется, решение. Наследование делается через вложенные сруктуры и функции в них. Инкапсуляция это хуйня какая-то о которой не помню. Но если ты не еблан и пишешь собственный с++ на сях, то в ногу не выстрелишь, память не расплескаешь и методы структур не будут изменяться. А вот Страуструп в своей книжке, кстати вообще за памятью не следит и некоторые сурцы у него текут, ага. Пруфы сам нароешь.
Как проверить является ли аргумент или строка числом uint64_t?
Есть ли функции наподобие isNumber(str)//true, false
В смысле строка uint64_t? У тебя вроде как по умолчанию строка содержит char по одному байту (8 бит). И твоя строка содержит 8 ASCII-символов, которые могли бы уместиться в uint64_t. А чтобы узнать состоит ли у тебя строка из циферок, то прогони в цикле каждый символ, чтобы его шестнадцетиричный код лежал в диапозоне от 0x30-0x39. и Правая цифра после 0x3? будет твоей цифрой ASCII.
Чиво блядь? Ты хоть представляешь сколько цифор на свете? Их бесконечное множество! Как я в цикле могу их прогнать? Сначала кумекай, потом кукарекай! Что мне от 0 до 9 даст цикл, если мне надо проверить что-то за пределами этого диапазона?
Я не этот >>64889
Итак... Что тут у нас?..
>>64885
>В смысле строка uint64_t?
Да.
>У тебя вроде как по умолчанию строка содержит char по одному байту (8 бит).
>И твоя строка содержит 8 ASCII-символов, которые могли бы уместиться в uint64_t.
>А чтобы узнать состоит ли у тебя строка из циферок, то прогони в цикле каждый символ,
>чтобы его шестнадцетиричный код лежал в диапозоне от 0x30-0x39.
Поначалу тоже подумалось мне, но наловил багов...
Всё по причине того, что
fgets(string, 255, stdin);
сохраняет в конце строки '\n', когда вводишь значение.
Пришлось сделать strtok(string, "\n"); после этого.
>и Правая цифра после 0x3? будет твоей цифрой ASCII.
Но я по-другому решил.
У меня есть функция string_to_u64(str),
поэтому сначала я прочитал строку в uint_64,
затем sprintf(temp_string, "%" PRIu64, uint64_t_value);
после чего - if(!strcmp(temp_string, string)). Дальше либо - return либо 1, либо 0.
Всё в отельную функцию пхнул и работает как надо.
>>64889
>Чиво блядь? Ты хоть представляешь сколько цифор на свете?
Их radix, на самом деле в числе.
>Их бесконечное множество!
Не все считают в бесконечноричной системе счисления, как ты.
>Как я в цикле могу их прогнать?
По цифрам, очевидно же. В идеале - по битам.
>Сначала кумекай, потом кукарекай!
Этот залётный, потроллить решил.
>Что мне от 0 до 9 даст цикл, если мне надо проверить что-то за пределами этого диапазона?
Ну, смотри сюда, что-ли: http://rextester.com/ZYP23810
>>64890
ЧТО ЗАТРАЛЛЕЛ.
>>64891
ЛАЛ.
Я не этот >>64889
Итак... Что тут у нас?..
>>64885
>В смысле строка uint64_t?
Да.
>У тебя вроде как по умолчанию строка содержит char по одному байту (8 бит).
>И твоя строка содержит 8 ASCII-символов, которые могли бы уместиться в uint64_t.
>А чтобы узнать состоит ли у тебя строка из циферок, то прогони в цикле каждый символ,
>чтобы его шестнадцетиричный код лежал в диапозоне от 0x30-0x39.
Поначалу тоже подумалось мне, но наловил багов...
Всё по причине того, что
fgets(string, 255, stdin);
сохраняет в конце строки '\n', когда вводишь значение.
Пришлось сделать strtok(string, "\n"); после этого.
>и Правая цифра после 0x3? будет твоей цифрой ASCII.
Но я по-другому решил.
У меня есть функция string_to_u64(str),
поэтому сначала я прочитал строку в uint_64,
затем sprintf(temp_string, "%" PRIu64, uint64_t_value);
после чего - if(!strcmp(temp_string, string)). Дальше либо - return либо 1, либо 0.
Всё в отельную функцию пхнул и работает как надо.
>>64889
>Чиво блядь? Ты хоть представляешь сколько цифор на свете?
Их radix, на самом деле в числе.
>Их бесконечное множество!
Не все считают в бесконечноричной системе счисления, как ты.
>Как я в цикле могу их прогнать?
По цифрам, очевидно же. В идеале - по битам.
>Сначала кумекай, потом кукарекай!
Этот залётный, потроллить решил.
>Что мне от 0 до 9 даст цикл, если мне надо проверить что-то за пределами этого диапазона?
Ну, смотри сюда, что-ли: http://rextester.com/ZYP23810
>>64890
ЧТО ЗАТРАЛЛЕЛ.
>>64891
ЛАЛ.
strtoull, посмотреть результат и проверить, что после вызова указатель указывает на '\0'.
Смотрите:
char x = '\t'; //символ
printf("x = \%c", x); //print string 'x5 = TAB' <------ хуле тут слэш не котируется? Ожидалось '\\t' -> '\t'
printf("\n");
Шо нема разве функций по эскапу унескапу чарактеров?
Вкиньте я их сразу инклюдить буду, а то по свичу писать в каждое условие ну не очень удобно...
Вот тут https://stackoverflow.com/questions/29477345/how-to-print-special-characters-explicitly-in-c
лежит функция escape с большим свичем. Называется она str_escape(char str[])
Что она делает? А как раз-таки - эскапает стринги и чарактеры.
И вот так юзается она: http://rextester.com/EQH57181
а ты не пеши а сделай:
char unecsape[128][] = {"\\0", "\\1",...}
и потом пишеш
printf("%s\n", unecsape[x])
но вот команда не работает? Может я что-то сделал не так?
В прыщах, и в убунте особенно, архивы с исходника и ко-ко-компелировать необходимо прежде чем использовать. Если пакет изначально не был предкококомпелирован.
А так убунта тебе поямо сказала что тебе необходимо сделать, чтобы гцц встал и ко-ко-компелировал твой говнокод.
Ну милый мой, ответ я твой не принимаю
> Он что-то прогрузил там,
Я не ванга, что дать ответ на такой расплывчатый вопрос
Ой бро, да ты же, внатуре, ескапать пытался. Для эскапа я функцию запостил выше.
А постой. Что это у тебя тут? Хеш-таблица, с ключами и без значений?
И двойной массив какой-то, многомерный что-ли?
Ты туда x засунул в [x] - для чего? Это символ должен быть в виде переменной?
А как тогда тройной ключ в хеш-таблице внутри строки искать?
Там три символа, по три читать что-ли?
>>65202
>Для unescape нужно парсить строку.
Я знаю только что строка - это массив символов (числовых кодов их),
и массив этот - заканчивается символом '\0'. Уже как-бы пол дела.
Но чё-то не пойму как строку в int засунуть.
Пытался так: int code = (int) string;
по аналогии c int code = (int) char;
но оно чё-то не фурычит...
P.S.: в итоге пришёл, через гугл - к функции atoi()
Пока самая главная проблема Rust'а - слишком быстрые изменения. Язык пока ещё не совсем устоялся, бывает, что ломается синтаксис, и либу, которую полгода назад тащил в cargo.toml, сегодняшней версией компилятора уже не собрать, потому что DEPRECATED
Чё-т вбрело strtok'ом по нулю в цикле проехаться, а потом компарить.
Может есть лучшее решение вроде неведомого memmove c этими его - амперсандами?
Это необязательно, gcc предполагает имя по умолчанию.
Может ты sudo забыл в первый раз написать, когда устанавливал? Или пароль неправильно ввёл.
Блять, я всего лишь предложил способ извратиться и написать свой с++ на сях. Это же не значит, что я реально буду извращаться и фистить себе анал на с++, как Страуструпы всякие.
Там надо memset(buffer, '\0', sizeof(buffer));
вставить, а то хуйня какая-то там, в первых трех символах.
>Ты туда x засунул в [x] - для чего? Это символ должен быть в виде переменной?
да
>А как тогда тройной ключ в хеш-таблице внутри строки искать?
а зочем
вот у аноньчика символ x = '\t'
у него будет хранится в x девятка, есле её вызвать как число
потом мы хотим сделать этот таб пичатаемым
мы просто напишим unexcape[x] и под этим адрисом будет у него строчка "\t", илижи "\\t\0", есле быть точным
ООП, разрушение объектов при выходе из области видимости, исключения, шаблоны, перегрузка операций
>почему С не умер с приходом последнего
С очень сильно усох с приходом плюсов. У плюсов есть свои минусы (типа отсутствия стандарта на бинарные интерфейсы), которые ограничивают их использование в системном софте.
>>64882
Многие писали велосипедное ООП с полиморфизмом на С. В геймдеве это было обычным делом в 90е.
Я уже ескпал функцией со свичем, но твой пример я тоже не забыл.
Поигрался с ним, и вот что получилось: http://rextester.com/OGRD62658
Не знаю правда насколько правильно оттуда возвращать '\1' '\2' '\81'
но вроде-бы строки совпадают. Однако всё это дело - не унескапает,
и надо как-то циклом парсить...
>Многие писали велосипедное ООП с полиморфизмом на С. В геймдеве это было обычным делом в 90е.
В геймдеве 80х-90х обычным делом было выдумывание/взятие готового DSL и написание скриптового движка, после чего байтоёбля заканчивалась и начиналась разработка игры.
Вспомнить тот же лукасовский SCUMM. Или лишп в играх серии Crash Bandicoot.
Даже на денди, блядь, разработчики упрощали себе жизнь:
https://habr.com/post/259761/
А анекдотов про боевых байтопидорасов (вот в наше-то время, ууууххх!!!!, не то что вы скрипто сосунки кхекхекхекококо, вот тогда то только байты ебали, ууу прямо на ассемблере с сишными вставками, кококо) уже потом с подачи кармака и его кодлы позёров и графоманов насочиняли.
Так как раз кармак в квейке 1,2 и делал ООП на С. На счет 3 части не уверен на чем они ее писали.
>Так как раз кармак в квейке 1,2 и делал ООП на С
Так в квейке два он как раз вроде выкинул виртуальную машину и сказал "ебитесь с нативными DLL и вижуалстудией", а в третьей вернул вместе с конпелятором.
Но я вообще к тому, что вот эта вся байтоёбская движуха с ассемблером началась именно с кармаковской компании, миха абраш в своих талмудах ссал всем тогдашним школьникам как ебать байты и быть крутым хакиром-гейдевелопером, А кармак и вовсе типа был богом и ПРИДУМАЛ ТРИДЕ-ГРАФИКУ11111.
Разве наличие виртуальной машины обязательно для ООП?
Или у него сеть отвалилась при первой скачке и при запросе к репозиторию ему ответили соси хуй.
давно программисты настолько отупели, что не могут даже по описанию понять в чем дело?
>Даже на денди, блядь, разработчики упрощали себе жизнь:
Ясен хуй разрабы не стали бы срать семь мегаменов с нуля, или три финалки, или там драгон квесты какие.
Мегамены, впрочем, к отличным от других играм не относятся, в отличие от думов. Хотя, даже когда дум раз появился, мало кто егово второй раз переписывал.
Ну, блять. Я себя впервые вспоминаю как вкатывался в пинус и в си соответственно, дак, блять, у меня попоболь не утихала постоянно. Начиная с того, что bash чувствителен к регистру и заканчивая английскими сообщениями компилятора. За год вроде уж привык к такому. Алсо вопрос. Сколько нужно, минимум, надрачивать си, чтобы уверенно себя начать чувствовать и топать на первые собеседования?
Читаю книгу, еще первую главу. Чую на указателях вроде & сгорю нахуй. До этого разве что в школе под досом на бейсике писал программы. В 27 лет не поздно начинать учить язык?
>Сколько нужно, минимум, надрачивать си, чтобы уверенно себя начать чувствовать и топать на первые собеседования?
До момента понимания сорцов ядра linux, использованных там приемов и уверенного написания helloworld-драйвера под него же.
Ну, от тебя по крайней мере польза в том, что я в свои 23 не чувствую себя теперь стариканом, который поздно уселся учить Си. Ну, кстати я представляю как указатели работают в 32-разрядной архитектуре, но я так до сих пор и не понимаю как организована память в x86_64. А так вроде жеж это несложно... Просто представь всю оперативку как массив длинной 4 гига ну или сколько там у вас?. Каждый байт - это ASCII-символ. А указатель - это номер индекса этого огромного массива оперативки. И вот указатель позволяет получить содержимое этого символа(ака, байта, ака ячейки памяти). И строки напримр начинаются с определённого адреса(показываемого оператором &) и идут до бесконечности за границы твоей оперативки, пока не будет встречен нулевой байт. Это вкратце об атаке переполнения буфера, но сейчас, наверное, ей никого уж не пронять. Алсо есть вопрос... Стоит ли размер массива держать в нулевом элементе? Чтобы при работе с массивом исключать его нулевой элемент из обработки а в условии выхода из цикла ссылаться на этот нулевой элемент.
>>65419
Спасибо, анон. Как раз в декабре собирался за модули ядра усесться. Типо после НГ попробую жопу от дивана оторвать. В итоге я два чистых года учу Си и всего год только эффективно, по книгам и по педивикиям.
>как организована память в x86_64
Так же как и в 32 в страничном варианте и двумя сегментами, с той лишь разницей что первые 16 бит пока не используются и адрес на самом деле 48-битный.
Ну и сегменты там в нули все выставлены.
>Стоит ли размер массива держать в нулевом элементе?
так в паскале хранились строки. какие накладывает это ограничения, думою, сам понимаеш
в C11 появились безопасные версии функций которые сами прекращают работу при превышении числа элементов
можно ещо сделоть struct massiv {unsigned char rozmer; char bukvy} a; и обращатся через a.rozmer
а можно просто (unsigned char)(&a) но компелятор может выровнять так что тебе придёться читать символы не с адреса (unsigned char)((&a)+1) а с адреса (unsigned char)((&a)+3)
struct massiv {unsigned char rozmer; char⁕ bukvy} a;
a.rozmer
(unsigned char⁕)(&a)
(unsigned char⁕)((&a)+1)
(unsigned char⁕)((&a)+3)
ну ты понел
Какого хуя программа по всей видимости не выходит из цикла while? Внутри же цикла считает нормально.
#include <stdio.h>
main()
{
int c;
int t=0;
while((c=getchar())!=EOF)
if (c == '\t')
{++t;
printf("%1d \n", t);
}
printf("result: %d\n", t);
}
Как именно не делать? В книге именно так и пишут, говорят так запись короче.
Надо так делать?
c=getchar();
while(c!=EOF)
Нихуя тоже не работает.
Где это у меня скобки нет? Все на месте же.
А в андроиде? Если жму текст и потом ctrl+d то ничего не происходит. Приходится вводить текст, жать энтр, потом уже ctrl+d и тогда только работает. Получается я символ eof ввожу отдельно. Выглядит это вот так:
ghjfdyygfeuhtr
1
2
3
4
result: 4
>первые 16 бит пока не используются
Потому что нахуй не нужно, так как и так помещаемся с головой?
Ситуативно.
есле ты просто обьявляеш структуру, то память сама аллоцируеться
ты выделяеш динамически тогда, когда у тебя укозатель
>Потому что нахуй не нужно, так как и так помещаемся с головой?
А потом, когда межгалактическая связь и квантово-многомерные штеуды попрут?
Так как не надо делать то?
Я могу просто писать unsigned, как пишут в некоторых старых туториалах или есть какие-то подводные камни (окромя нубопонятности)?
И еще одно: обязательно ли в объявлении типа int foo(void){return 666;} писать этот войд в скобках? Знаю, что работает и без него, но как это всё делать с т. з. best practice и coding style, кароч чтобы прям комильфо. Вы как делаете?
если void внутри скобок не будет то формально функция принимает любое количество аргументов
Ищешь MISRA-C и изучаешь.
https://en.wikipedia.org/wiki/C_data_types#Basic_types
Если в одной строчке, то нет разницы, как видишь можно писать просто unsigned и просто signed.
Хуй знает, я с си копался один семестр в универе, потом около года с++, с первого же интервью попал в неплохую компанию джуном по разработке кернел драйвера, вот за несколько месяцев вроде втянулся уже.
20-лвл
В 32 битной системе вроде правые 12? бит это смещение по странице, а левый остаток это номер записи в таблице страниц.ну это не учитывая ещё что есть таблица таблиц страниц
В кернел-коде обязательно писать и void и unsigned int
Вроде нет, при неправильном вводе пароля система предупреждает.
Скорее всего сбой в загрузке был.
> Алсо есть вопрос... Стоит ли размер массива держать в нулевом элементе? Чтобы при работе с массивом исключать его нулевой элемент из обработки а в условии выхода из цикла ссылаться на этот нулевой элемент.
По ситуации.. функция Malloc не забивает массив нулями , а его аналог Calloc забивает.
Он говорит про содержание размера массива в самом массиве, а не про значения элементов внутри массива.
Это приплюснутое говно, зачем оно здесь?
> размер массива держать в нулевом элементе?
Зачем в нулевом, если можно в минус первом:
int ∗alloc_array(size_t length) {
int ∗x = malloc(length + 1); x[0] = (int) length; return x + 1;
}
int ∗array = alloc_array(20);
printf("Size of array: %d\n", array[-1]);
(length + 1) * sizeof(int), ну вы поняли.
>>65693
Это же очень часто делается. Например, у тебя есть либа (сишный рантайм, ОС и т.п.), которая хочет читать и писать массив (или, еще чаще, сишную строку), а еще хочет ее хранить, возвращать или передавать обратно тебе в колбек. При этом ты хочешь иметь полноценный динамический массив, т.е., хранить used/allocated как минимум. И ты такой говоришь, окей мол, и хранишь эту информацию в отрицательном элементе (если инты или если char, но длина гарантированно влезает в байт) или чаще в структуре по отрицательному смещению. Т.е.:
typedef struct { size_t avail; size_t used; } strdesc;
static inline strdesc ∗str_get_descriptor(char ∗str) {
void ∗raw_ptr = str - sizeof(strdesc);
return ALIGN_DOWN(ptr, alignof(strdesc));
}
Делая это ты даже почти не нарушаешь сишный стандарт, и нет практически никаких подводных камней (кроме варианта, когда ты попытаешься прочитать дескриптор обычной строки, у которой этого дескриптора никогда не было).
Ты так говоришь, как будто ядро = ядро линукс, а у других ОС и приложений ядер нет.
Практически уверен, что в линуксе такое встречается в десятках вариантов, просто оно там по обыкновению обмазано макросами, поэтому ты и не замечаешь. Нет, искать и доказывать не буду. Тебе нужно - ты и ищи.
Я говорю ядро, потому что первое, что приходит в голову при разговоре о си это ядро линукса.
Ну и там есть годный кодстаил.
не вижу никаких преимуществ, если ты передаешь массив в либу, ты знаешь его размер и можешь хранить нормально, в структуре например, вместе с массивом
крестоносец-долбаёб. УХАДИ. На плюсах пишут дауны. Это не я скозал. Это Deus Vult.
Так пишут только люди, которые не занимались ничем профессионально.
алсо я работаю на си, т.к. пишу драйвер под линупс
У меня число decimal 1234567891011121314
в hexadecimal даёт 112210F4B2D230A2
В файл записывается оно не так:
11 22 10 F4 B2 D2 30 A2
а вот так:
A2 30 D2 B2 F4 10 22 11 (A230D2B2F4102211)
Задача - прочитать его из файла как 1234567891011121314 (64 bit)
или хотя-бы как (unsigned long long) 0x112210f4b2d230a2
Как правильно это сделать?
Так и не понял где этот флаг ставить -
и решил с помощью fread, вот так:
http://rextester.com/UECYH23057
Вариант 1.
int x;
int^ xptr;
x = 10;
xptr = &x;
Вариант 2.
int x = 10;
int^ xptr = &x;
Вариант 3.
int x = 10, ^xptr = &x;
Вопрос: как правильно, учитывая, что между строчками в 1 и 2 ничего дополнительно не происходит (а даже если и происходит?)?
1 не нужно почти никогда, даже скорее никогда.
2 удобнее всего.
3 имеет риск быть неудачно прочитанным глазами, да и экономить строчки смысла нет.
правельно никогда не ставить звёздочку после типа, а перед именим переменной
>(а даже если и происходит?)
а есле во втором между строчками что-то происходит, то у тебя в c90 это не заработаит
>никогда не ставить звёздочку после типа, а перед именим переменной
Я тоже нахожу это логичным и пишу так, но никакого "правильно" в этом нет.
>то у тебя в c90 это не заработаит
Это та параша, где нельзя переменную объявить в шапке for()? Нинужная версия.
ну сматри какое дело
вот ты объявляеш
int a, b;
и b у тебя не int, как можна было бы думать, а int
так что не надо
ну сматри какое дело
вот ты объявляеш
int^ a, b;
и b у тебя не int^, как можна было бы думать, а int
так что не надо
Мне кажется под си, чего-то свежего, кроме офф документации особо не найдешь.
https://developer.gnome.org/gtk3/stable/ch01s03.html
Могу только сказать, используй Glade и билдером подключай, так проще будет. Хотя в глейде могут отсутствовать какие-то свойства виджетов и приходится их руками дописывать.
> 1 не нужно почти никогда, даже скорее
никогда.
if (...) { x = 10; xptr = &x; } else { z = func(); xptr = &z; }
Да, чот тупанул.
>Очевидный GCC.
Не забываем ставить флаги оптимизации при компиляции. Как например, флаг -O3, ускряющий софтину.
Подробнее про O3 - тут: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Меня этот пример сбил с толку. Что это означает?
Вопрос был чисто об идеологии - объявлять и инициализировать сразу или отдельными утверждениями (1 vs. 2) и можно ли в одну строку все запихать (3). Я понял, что объявлять одним выражением тип и указатель на него это совсем некомильфо. А вот с 1 и 2 как быть?
>>66005
А можешь тогда назвать ситуации, где реально нужны и лучше работают подходы 1 и 3:
int x;
int ^xptr;
x = 10;
xptr = &x;
или
int x = 10, ^xptr = &x;
Всё это время речь идет только об одной переменной и одном указателе. То есть, идее как вообще принято делать и как надо учить делать.
У меня старенький препод требует, чтобы строго как в первом было. Отдельно в самом начале функции все переменные объявили (каждую в свой строке с ; в конце). Потом строчку отступили и дальше инициализируем по мере надобности. Я не понимаю, чем продиктовано такое ограничение. Подозреваю, что из каких-то древних эпох. Но за варианты типа
int x = 10;
int ^xptr = &x;
нещадно бьет по рукам и говорит нельзя, не буду мол, даже и объяснять ничего.
Что с ним не так?
У меня, почему-то, cmake с релизным флагом собирает более производительное приложение, чем я ручками с -О3. Видимо, в -О3 не всё включено.
>А можешь тогда назвать ситуации, где реально нужны и лучше работают подходы 1 и 3:
Там речь не об этом, а о том, где звёздочку ставить.
int x;
int ^xptr;
x = 10;
xptr = &x;
В данном случае нет смысла писать на четырёх строчках то, что и на двух читается прекрасно.
int x = 10, ^xptr = &x;
А так не очень хорошо читается, на двух строчках лучше, чем на одной.
А пробелы и табы можно сколько угодно хуячить? Компилятор же их игнорирует полностью?
> объявлять и инициализировать сразу
Не всегда возможно, о том и был пример с if.
> У меня старенький препод требует
Считай это локальным кодстайлом и делай, как просит. А для себя делай так, как считаешь правильным.
> Подозреваю, что из каких-то древних эпох.
Ну в древних эпохах не было C99, нельзя было декларации с кодом мешать, это да. А вот проблем с инициализацией не припомню. Возможно, баги в каких-то компиляторах. В любом случае, препод не прав, но кодстайл важнее чьей-то правоты.
>>66528
> В данном случае нет смысла писать на четырёх строчках
В данном - нет. Если есть возможность инициализировать при определении переменной - нужно инициализировать.
>>66735
> -Werror
И куча отключенных, хороших предупреждений, которые могли бы сэкономить тебе время. Или куча анального ублажения компилятора и нечитаемого кода из-за этого. Попробуй с clang -Weverything -Werror собрать что-нибудь более-менее крупное, лол.
Почитай код ядра линукса, посмотри как там выглядит блок инициализации, тебе не нужно думать, что там происходит, просто посмотри как выглядит объявление.
ядро це канон
Реверс кристмасс три ордер декларейшен навсегда в моём сердце
> тебе не нужно думать
Вся суть. А между тем там протухший C89 с расширениями и куча абсолютно ебнутых решений вроде явного использования struct вместо typedef.
А с гитом-то что? Он же работает вроде, или нет?
>(https://pastebin.com/rJxchrEQ) когда я ввожу букву, scanf просто игнорируется и программа зацикливается?
УМВР.
Ты уверен, что у тебя функция scanf_s существует, а не просто возвращает мусор по счастливой случайности?
> -858993460
0xcccccccc, т.е., неинициализированная область стека. Т.е., твоя функция НЕ работает и возвращает тебе 0, а ты ее результат не проверяешь.
>>67215
Хранишь код в CVS?
Алсо, не используй _s функции. Это дерьмо от Microsoft, и место ему на помойке. Скажи
#define __STDC_WANT_LIB_EXT1__ 0 и/или #define _CRT_SECURE_NO_WARNINGS перед всеми инклудами, чтобы тебе перестали ее продавать.
>Алсо, не используй _s функции. Это дерьмо от Microsoft, и место ему на помойке.
Разве они не определены в C11?
И почему их лучше не использовать?
> Разве они не определены в C11?
Оно optional. И весь Annex K признали ошибкой и вроде даже обещали задепрекейтить в C18/20, или когда он там выйдет: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm
> И почему их лучше не использовать?
Вкратце: никому нахуй не вперлось, неудобно, избыточно и ненадежно. Если тебя в каком-то конкретном случае волнует, обрезало ли тебе строку при snprintf - возьми и проверь возвращаемое значение.
Нет, ты можешь зарегать функцию, которая скажет юзеру "до свидания" или можешь попросить ничего не вызывать, потому что ты будешь проверять код ошибки. Фактическое отличие от обычных функций в том, что ты дополнительно передаешь еще больше размеров (обычно ненужных) и в том, что они считают, что если что-то куда-то не влезло и обрезалось - то это ошибка, в то время как обычные функции пихают сколько влезло.
>лексированием
вот блин, это так нужно называть похоже, если ты пишешь хрень которая разбивает текст на части - лексемы, токены? а я это регекспом называл, но у меня нет никакой замены, никакой манипуляции над текстом.
> Lexing can be divided into two stages: the scanning, which segments the input string into syntactic units called lexemes and categorizes these into token classes; and the evaluating, which converts lexemes into processed values.
что-то я совсем запутался. значит есть лексирование-токинизирование - разбивка текста на какой-то минимальный смысл, с высоты которого которые позже будет анализировать парсер. но в принципе, если я не конвертирую сегменты текста, то это просто сканер? - как часть лексера.
Как же бесят эти предупреждения. Пишу русскими буквами в printf(), на консоль всё выводится нормально, но компилятор всё равно меня предупрпеждает. Почему? Я что, не имею права на русском писать? Можно это как-нибудь отключить? Ещё хочу предупреждение о пропущеном типе функции отключить, я-то знаю, что по-умолчанию там int и поэтому не пишу, но он меня опять-таки предупреждает постоянно. Компилятор LLVM, кстати.
Там нормальным английским языком написано, проблемы с кодировкой.
Если у тебя русский в Юникоде, тогда ищи, как работать с Юникодом в Си.
Я понял, но я не знаю как это сделать.
Gcc таких предупреждений не выводит, так что венда тут не причём.
while ((c = getcharO) != EOF)
if (c >= '0' && c <= '9' )
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
Что значит выражение ++ndigit[c-'0']? Зачем от с отнимать ноль? Разве если мы хотим в массив записать число 5 пятым в массиве - надо делать [с - 1], т.к. массив начинается с нуля, нет?
Чего я подумал, так ведь даже -1 не надо делать, если считать тоже от нуля. Тогда какой вообще смысл в с-'0'?
Короче в твоем примере подсчитывается количество встреченных символов разных цифр (в массиве ndigit[10]) и пробелов/табуляций (в nwhite).
>>66770
Спасибо. Я так примерно и догадывался. Выходит, до C99 строго необходимо как в пасцале сначала всё объявлять, а уже только потом работать?
Кстати, если локальный кодинг-стайл запрещает делать пустые строки, это чему-то хорошему учит? Я просто привык логически отделять, а портянка на 20+ строк кажется даже эстетически… что ли неприятной. Как вы ставите пустые строки?
Ты можешь делать пустые строки, но они должны быть буквально пустыми, без пробелов/табов на этой строке.
Но если твой препод требует по-другому - делай по-другому.
https://habr.com/post/304034/
https://habr.com/company/nixsolutions/blog/265427/
Где эти строки будут записаны? В стеке/на куче? В сегменте данных? Кто автоматически ставит в них \0 в конце, чтобы можно было с ними работать как со строками через argv?
Ты автор? Статья может и интересная, но не существует настолько интересной темы, чтобы ради нее продираться через настолько деревянный текст. Еще раз промптом с китайского и обратно переведи.
Нет, автор не я. Кстати я тоже заметил, что с текстом что-то не так,лол.
Правда я почему то подумал, что это я недостаточно хорошо знаю русский, для того что бы понимать сложные научные текста. Я и не подумал, что кто-то это переводил.
А на что это влияет? Кроме того чтобы мне вдруг захотелось спрятать исходник на Whitespace внутри исходника на C?
>Я и не подумал, что кто-то это переводил.
>habr
Что ты ожидал на этой помойке? Почитай еще хвалебные комментарии местных говноедов
Кроме читаемости ни на что.
если ты про пробелы/табы в пустой строке это просто требование для кола в ядре, модель пропустить свои исходники через checkpatch.pl и посмотреть, что он тебе выдаст, но там много требований именно к внешнему виду, что будет противоречить, скорее всего, требованиям твоего препода :^)
> Я что, не имею права на русском писать?
Имеешь, но делаешь это неправильно. Выставь -finput-charset=UTF-8 (хотя оно и так по умолчанию, поэтому оно и ругается на исходник в 1251) и -fexec-charset=cp1251 (или cp866, или что тебе там нужно), и не забудь пересохранить исходник в UTF-8. Можешь еще попробовать -finput=charset=cp1251 (или cp866), но у шланга вроде с этим какие-то проблемы были, да и хранить код в чем-то кроме UTF-8 - это плохой тон.
> я-то знаю, что по-умолчанию там int
Начиная с C99 уже нет. Добро пожаловать в будущее и хватит писать говнокод.
>я-то знаю
Все, что делается неявно лучше делать явно, это как минимум защита от возможных изменений в компиляторах.представь что твой говнокод в попенсорсе, ты же и представить не модель на чем его попробуют собрать
А уж неявный инт это мало того, что помогает избавиться от лишнего времени поиска бага, если вдруг что-то подменяют, но ещё и увеличивает читаемость кода.
> ты же и представить не модель на чем его попробуют собрать
Вот тут ты не прав. Либо компилятор соответствует стандарту, либо это компилятор си-подобного языка, с которым не нужно поддерживать совместимость.
Тебе уже сверху ответили про C99, я имел в виду, что версия компилятора относится к конкретному стандарту
>>67941
>Все, что делается неявно лучше делать явно, это как минимум защита от возможных изменений в компиляторах.
делая что-то в с99 или с11, это что-то в следующих стандартах может оказаться неявным - никогда не знаешь.
пусть пишет на каком хочет стандарте. а то каждая недозревшая, и дозревшая, сперма, советует что делать - программистская культура.
> но ты же не всегда знаешь какой будет меньше, оперируя полями структур
Ты пишешь на языке, где тебе дали контроль вместо безопасности. Если ты чего-то не знаешь - ты идешь и смотришь объявление.
Почему работает __uint128_t и __int128_t на 64-бит компе? Это какая-то эмуляция?
uint128_t может быть реализован как пара 64-битных регистров, сложение/вычитание через adc/sbb, 128-битное делимое x86-64 и так умеет, умножение и делитель - отдельной функцией. Алсо, ты кастишь к long double, который вполне может быть 80-битным. Алсо, все это может работать хоть на 8-битном компе, если разработчики компилятора запилят поддержку.
При вылезании за границы проблемы вызывает не реализация умножения, а его атомарность.
Я тут осваиваюсь с libevent и что-то написал типа сервера.
Теперь прошу у вас подсказку: как можно спровоцировать разные ошибки? Хочу проверить, как у меня идет их перехват, да только пока недостает знаний что это за ситуации и чем их можно вызвать искусственно:
case _EVENT_LOG_DEBUG: s = "debug"; break;
case _EVENT_LOG_MSG: s = "msg"; break;
case _EVENT_LOG_WARN: s = "warn"; break;
case _EVENT_LOG_ERR: s = "error"; break;
Что мне делать, чтобы появились эти заветные ошибки?
(И как они вообще появляются? Я привык к такому языку, где в исключительной ситуации кидаются исключения и их ловят трайкечем, а тут какой-то калбек (казах что-ли) и как мне его, самому надо вызывать, проверяя результат системного вызова или как?)
Ну типо важны стандарты написания, для переносимости кода.. к тому же ты сам возможно захочешь поправить или апдейтнуть код в будущем и ахуеешь его читать.
>Шо нема разве функций по эскапу унескапу чарактеров?
>>61992
>Ну и как эту ASCII унескапнуть попроще?
>>65378
>всё это дело - не унескапает,
>и надо как-то циклом парсить...
>>66006
>Как '\\t' в '\t' унескапнтуть?
>>53747 (OP)
Антуаны, вот так унескапаются стринги: http://rextester.com/JAQV34599
Два дня проебал в эту хуятину - , пользуйтесь на здоровье.
> Антуаны, вот так унескапаются стринги
Как же ты заебал. И нет, так делать не надо, ты двигаешь всю строку на каждый чих. Надо примерно так: http://rextester.com/HGY79496 (парсинг \x я говнокодил уже, по-хорошему надо вообще лукап сделать). \u сам осилишь, принцип там тот же, но там уже лучше задуматься о strtoul.
Выше мейна у меня есть две функции с говнокодом, но я их вызываю после того, что я написал в пикрл. В голом файле этот код нормально выполняется.
При этом с gdb при нажатии n все работает.
Не имеет отношения к сабжу, но main должен возвращать int, чтобы ось поняла, что все ок.
Лол, как раз таки имеет. Сделал int и ретурн 0 после 56й строки - все заработало. Спасибо за совет.
Кто-то может обьяснить почему?
Странно, ну ладно, если в кратце, то твой процесс не завершался, т.к. операционная система не получала от него сигнал, что он выполнился.
но почему у тебя принтф не работал после цикла непонятно, на самом деле
Но это, вероятно, проделки оптимизации компилятора.
sort это моя функция, вохможно там костыли. Но какое это имеет значение, если не выводится то, что до сорта?
> нихуя, кроме 01234567
Нихуя, кроме первой линии рандомных чисел которые выводятся на 57й строке
фикс
>но почему у тебя принтф не работал после цикла непонятно, на самом деле
Потому что не было fflush();
как подключить sdl к mingw64 на виндовс?
Тогда будешь страдать.
Не, ну нахуй этот пердольский инструмент, из которого даже по человечески выйти нельзя
Если я использую memcpy N байт из строки меньшей N байт, словлю в лучшем случае сегфолт или почитаю говна.
Если я использую strcpy на строке, а строка вдруг больше выделенных N байт, то в лучшем случае словлю сегфолт.
И что использовать тогда?
Что за юморески?
>>69027
1) Часто забывают, что strncpy в Си сломана, для ее использования нужны дополнительные танцы с бубном. Пример: https://ideone.com/FMwQlp
2) Она не только сломана, но еще и неэффективна, потому что забивает остаток целевой строки нулями. Т.е., если делать char dest[4096];strncpy(dest, "x", 4096), оно не только положит два байта строки в dest, но еще и будет долго и бессмысленно втыкать туда 4094 нуля. Это, конечно, быстрее, чем strlen + memcpy, но все равно не ок.
Вообще, белые люди придумали strlcpy, но ее нет в стандарте. Алсо, можно использовать snprintf(dest, sizeof(dest), "%s", x) - на сколько-нибудь больших массивах (не из пары символов) это внезапно будет быстрее, чем strncpy. И надежнее.
Ты не припух гнать на лучший блокнот всех времен и народов?
Где еще ты сможешь сделать документ как n секунд/минут назад?
Я уже не знаю, что делать со строкой:
strcpy(((char∗)(∗(fourfold)+j∗COLS)), token);
Я представляю это так: у нас есть массив, состоящий из указателей. В каждый элемент массива мы сохраняем указатель, указывающий на массив строк, а т.к. у нас строк нет и есть массив символов, то мы заставляем выделять указатель на COLS∗MAXLINE символов, который и отправляется храниться в массив указателей.
Как надо писать, чтобы работало?
CSV читать
Яб тоже не отказался такие строки уметь читать
Если у тебя COLS и MAXLINE известны на стадии компиляции, зачем такие сложности? Сделай нормальный массив с известными последними измерениями char (*rows)[NUM_COLS][NUM_COL_CHARS], и вычисления адреса сильно упростятся. Ну или массив строк и массив массивов из NUM_COLS указателей на токены. Алсо, у тебя условие неправильное в цикле считывания столбцов - там && должно быть.
Как оказалось, я пересыпал звёздочек, всего-то три надо. И не надо быть умнее компилятора, выделяя двухзвёздному указателю место на х∗у байт, надо сначала выделять указатель на х байт, а потом внутри этого указателя на у байт.
Ну и вообще да,
>char (*rows)[NUM_COLS][NUM_COL_CHARS]
куда проще. Я даже и не вспомню, зачем я захотел динамически задавать память вместо простого как доска решения.
>Как же ты заебал.
Я тебя ещё голым не видел.
>И нет, так делать не надо, ты двигаешь всю строку на каждый чих. Надо примерно так: http://rextester.com/HGY79496
Вот это - сразу понятно стало. Я вижу ты используешь dest, чтоб писать символы туда. Годный совет.
>по-хорошему надо вообще лукап сделать
какой look up? Не пойму...
>\u сам осилишь
Ты имеешь в виду код юникод-символа?
>там уже лучше задуматься о strtoul
А как потом прицепить его к \u?
У меня хуйня какая-то получается тут: http://rextester.com/WPPNV63707
Оно просит hex - сразу после \u и не принимает %d.
Надо просто два слеша заменить на один, если стринга ескапед.
Можно конечно проверить являются ли следующие 4 символа hex-кодом,
но цеплять их можно и вместе с u. Что-то типа конкатенации.
Но один слеш так просто не прицепишь... Их надо два.
Поэтому, смотри что я принёс:
#include <stdio.h>
void printCard(int card) {printf("\xF0\x9F\x82%c\n", 0xA1 + card % 13);}
int main(void){for (int i = 0; i<10; i++){printCard(i);}}
Этот пример - выводит 1 символ из нескольких \x байт.
Как его сюда пришпандорить к \u - хуй знает.
>Как же ты заебал.
Я тебя ещё голым не видел.
>И нет, так делать не надо, ты двигаешь всю строку на каждый чих. Надо примерно так: http://rextester.com/HGY79496
Вот это - сразу понятно стало. Я вижу ты используешь dest, чтоб писать символы туда. Годный совет.
>по-хорошему надо вообще лукап сделать
какой look up? Не пойму...
>\u сам осилишь
Ты имеешь в виду код юникод-символа?
>там уже лучше задуматься о strtoul
А как потом прицепить его к \u?
У меня хуйня какая-то получается тут: http://rextester.com/WPPNV63707
Оно просит hex - сразу после \u и не принимает %d.
Надо просто два слеша заменить на один, если стринга ескапед.
Можно конечно проверить являются ли следующие 4 символа hex-кодом,
но цеплять их можно и вместе с u. Что-то типа конкатенации.
Но один слеш так просто не прицепишь... Их надо два.
Поэтому, смотри что я принёс:
#include <stdio.h>
void printCard(int card) {printf("\xF0\x9F\x82%c\n", 0xA1 + card % 13);}
int main(void){for (int i = 0; i<10; i++){printCard(i);}}
Этот пример - выводит 1 символ из нескольких \x байт.
Как его сюда пришпандорить к \u - хуй знает.
Короче, сам вижу, что \u можно просто через слеш указать
в строке вида: char x[] = "xx\\\\xxx\\ty\\r\\n\\\'\\\?\\\"hello\\x22\\x7e\u1ed8";
и оно пойдёт в символ, и останется ним. И не нужно писать никакой отдельный сase для 'u'.
Если же перед '\u' стоит ещё один слеш '\\u', то ебануться можно.
> какой look up? Не пойму...
Массивчик, который символу, который возможно является шестандцатеричной цифрой сопоставляет значение 0..15 или -1, если символ такой цифрой не является. Таким образом исчезнет необходимость во всех toupper и isxdigit, которые сами в такие массивчики ползают. Только они еще и от локали зависят, поэтому ползают медленно.
> А как потом прицепить его к \u?
Читаешь 4 (если \u) или 8 (если \U) символов (не забывая о том, что на каждом шагу тебя может подстерегать конец строки), делаешь strtoul(..., ..., 16), проверяешь, что endptr - ptr == 4 (или 8), т.е., это были валидные hex-цифры, которые сконвертировалось целиком, а вот что делать дальше - зависит от задачи. Можно сделать sprintf("%lc"), можно самому кодировать в валидную последовательность UTF-8. А если у юзера текст не в UTF-8, тогда сосать.
Алсо, я сейчас посмотрел на свой код - он тоже говно, там по-хорошему нужно выкинуть все потуги обработки всяческих "\ХУЙ и \x" и встретив любую невалидную последовательнось честно возвращать false, не пытаясь продолжать.
>>69309
> И не нужно писать никакой отдельный сase для 'u'.
Это компилятор за тебя "\uXXXX" в строках и символах обрабатывает. А ты хочешь сам обрабатывать, поэтому речь идет как раз о "\\uXXXX".
>Массивчик, который сопоставляет значение 0..15 или -1, если символ такой цифрой не является.
Аа, так ты имел в виду lookup table, как вон тот твой
static const char xvalue[]. Вот теперь ясно...
Пытался я сделать этот твой массивчик, и додуплил аж потом, что он же не возвращает нихуя за диапазонами.
Вот он - тут, закомментированный: http://rextester.com/QNH73934
В итоге, решил switch использовать, и циклом по строке протоптаться,
прописал оффсеты в свич и засунул это дело - в отдельную функцию.
>Читаешь 4 (если \u) или 8 (если \U) символов (не забывая о том,
>что на каждом шагу тебя может подстерегать конец строки),
>делаешь strtoul(..., ..., 16), проверяешь, что endptr - ptr == 4 (или 8),
>т.е., это были валидные hex-цифры, которые сконвертировалось целиком,
Вот ты там про байты выше пишешь и битовые сдвиги...
Лучше скажи как из двух байт 1e d8 получить эту букву Ộ.
Там какие-то UTF-байты дополнительно добавляются, как в примере, что я вкинул выше.
Я так и не получил эти байты из выходного символа, который выводится там.
>а вот что делать дальше - зависит от задачи.
Всё просто. Пользователь, в коммандной строке, вводит разделитель - в виде аргумента:
>program.exe -delimiter "\\u1ED8" и должен получить символ Ộ.
Надо как-то убрать один слеш из строки,
чтобы в строке содержалось "\u1ed8" и символ этот - после printf("%s", "\u1ed8");
При этом сама escaped string, должна бы содержать в себе два слеша перед u "\\u1ed8"
и выводиться как "\u1ed8" - причём выводиться ASCII-текстом.
В процессе унескапинга этого, "\\u" должно бы заменяться на "\u",
но так нельзя, оно просит hex цифры после \u, и...
>printf("\u%d", 7896). //1ed8 (decimal)
не работает...
Поэтому, можно было бы, каким-то образом, пришпандорить байты к u,
вроде 'u1ed8', а потом к слешу прицепить.
Но я ебу как это делать правильно... Проще наверное на ассемблере ядро переписать.
>Это компилятор за тебя "\uXXXX" в строках и символах обрабатывает.
Ну вот в этом и прикол, значит.
Как обрабатывает, куда байты подавать, как получить ебанный чарактер?..
Всё это надо знать, блядь и расколупывать после на уровне машинных инструкций...
АААААААААААААААААА!!!!
Но я вижу твой пример просто слеш добавляет.
В строке из твоего примера:
char x[] = "xx\\\\xxx\\ty\\r\\n\\\'\\\?\\\"hello\\x22\\x7e\\xf";
я вижу 4 слеша, и если добавить \\\\u1ed8 туда, вот так:
char x[] = "xx\\\\xxx\\ty\\r\\n\\\'\\\?\\\"hello\\x22\\x7e\\xf\\\\u1ed8";
то очевидно, что заменяется двойной слеш, и заменяется он на один,
это просто потому что двойной слеш и эта замена - есть в условии switch.
А надо чтобы "\\u" заменялось на "\u", без багов и лагов.
Сделали бы нечто вроде printf("%"u, unsigned_short_int charcode); //да в стандарт ввели бы...
P.S. И после всего этого - унескапнул два раза свою дрянную "\\u1ed8", и всё стало заебись.
>Массивчик, который сопоставляет значение 0..15 или -1, если символ такой цифрой не является.
Аа, так ты имел в виду lookup table, как вон тот твой
static const char xvalue[]. Вот теперь ясно...
Пытался я сделать этот твой массивчик, и додуплил аж потом, что он же не возвращает нихуя за диапазонами.
Вот он - тут, закомментированный: http://rextester.com/QNH73934
В итоге, решил switch использовать, и циклом по строке протоптаться,
прописал оффсеты в свич и засунул это дело - в отдельную функцию.
>Читаешь 4 (если \u) или 8 (если \U) символов (не забывая о том,
>что на каждом шагу тебя может подстерегать конец строки),
>делаешь strtoul(..., ..., 16), проверяешь, что endptr - ptr == 4 (или 8),
>т.е., это были валидные hex-цифры, которые сконвертировалось целиком,
Вот ты там про байты выше пишешь и битовые сдвиги...
Лучше скажи как из двух байт 1e d8 получить эту букву Ộ.
Там какие-то UTF-байты дополнительно добавляются, как в примере, что я вкинул выше.
Я так и не получил эти байты из выходного символа, который выводится там.
>а вот что делать дальше - зависит от задачи.
Всё просто. Пользователь, в коммандной строке, вводит разделитель - в виде аргумента:
>program.exe -delimiter "\\u1ED8" и должен получить символ Ộ.
Надо как-то убрать один слеш из строки,
чтобы в строке содержалось "\u1ed8" и символ этот - после printf("%s", "\u1ed8");
При этом сама escaped string, должна бы содержать в себе два слеша перед u "\\u1ed8"
и выводиться как "\u1ed8" - причём выводиться ASCII-текстом.
В процессе унескапинга этого, "\\u" должно бы заменяться на "\u",
но так нельзя, оно просит hex цифры после \u, и...
>printf("\u%d", 7896). //1ed8 (decimal)
не работает...
Поэтому, можно было бы, каким-то образом, пришпандорить байты к u,
вроде 'u1ed8', а потом к слешу прицепить.
Но я ебу как это делать правильно... Проще наверное на ассемблере ядро переписать.
>Это компилятор за тебя "\uXXXX" в строках и символах обрабатывает.
Ну вот в этом и прикол, значит.
Как обрабатывает, куда байты подавать, как получить ебанный чарактер?..
Всё это надо знать, блядь и расколупывать после на уровне машинных инструкций...
АААААААААААААААААА!!!!
Но я вижу твой пример просто слеш добавляет.
В строке из твоего примера:
char x[] = "xx\\\\xxx\\ty\\r\\n\\\'\\\?\\\"hello\\x22\\x7e\\xf";
я вижу 4 слеша, и если добавить \\\\u1ed8 туда, вот так:
char x[] = "xx\\\\xxx\\ty\\r\\n\\\'\\\?\\\"hello\\x22\\x7e\\xf\\\\u1ed8";
то очевидно, что заменяется двойной слеш, и заменяется он на один,
это просто потому что двойной слеш и эта замена - есть в условии switch.
А надо чтобы "\\u" заменялось на "\u", без багов и лагов.
Сделали бы нечто вроде printf("%"u, unsigned_short_int charcode); //да в стандарт ввели бы...
P.S. И после всего этого - унескапнул два раза свою дрянную "\\u1ed8", и всё стало заебись.
Так стоп! Но ведь в программе из книжки с и так имеет тип int. И как раз для указание на конкретный массив и нужно число в int. В чем тогда смысл?
Или после операции с=getchar() с меняет свой тип на char что-ли?
{
char✮ res = dst;
while(✮dst++ = ✮src++);
return res;
}
Это нормальный strcpy?
Спрашиваю, ибо жалуются, что сложна-нипанятна. Мне всегда казалось, что именно так и общепринято и любой программер на C такую конструкцию распознает не задумываясь. Что скажете?
Хз, чет погуглил и не нашел ответа
если ты ввел число 5 оно в кодировке ANSII там хуй пойми какое , поэтому мы с него отнимаем кодировку нуля ('0') и записываем итерацию в элемент массива под номером '5'-'0' = 5 , и тем самым в массиве останется инфа что ты нажал число 5
Стандарты SEI или чего-то ещё надо читать, там должно быть описано. Хотя, в целом, стандарты сводятся к тому, чтобы не заниматься гимнастикой с указателями и прочими подразумеваемыми вещами, а то словишь УБ и бида-бида.
Наверно, в условии цикла должно было бы стоять сравнение с нулём, или к указателям обращались бы с дополнительной переменной, я не знаю.
Выражение в while - это идиома. Все нормальные люди такое понимают и сами так пишут. А в ололобезопасных стандартах запрещают делать и многие другие нормальные вещи, но обоснований при этом не приводят - просто какой-то анонимный эксперт сказал им, что так нельзя.
мимо анонимный эксперт
>смотри что я принёс:
>#include <stdio.h>
>void printCard(int card) {printf("\xF0\x9F\x82%c\n", 0xA1 + card % 13);}
>int main(void){for (int i = 0; i<10; i++){printCard(i);}}
>Этот пример - выводит 1 символ из нескольких \x байт.
>Как его сюда пришпандорить к \u - хуй знает.
>>69310
>Это компилятор за тебя "\uXXXX" в строках и символах обрабатывает.
>А ты хочешь сам обрабатывать, поэтому речь идет как раз о "\\uXXXX".
Итак, если, в твоём примере
указать "\\u1ed8" в строке, то слеш унескапается и получается '\u1ed8'
Получается оно так - и при выводе escaped string, и после функции.
Если же указать просто "\u1ed8", видно символ 'Ộ'
причём и при выводе escaped string, и при выводе результата функции.
Почему так? Да потому что разные байты в строках "\\u1ed8" и '\u1ed8'
Вот они, здесь: http://rextester.com/NMOR60766
И есть ещё конвертер, вот такой: https://r12a.github.io/app-conversion/
Эти байты можно видеть там где UTF-8 code units.
Как можно видеть, байт этих три, ничего общего между ними и кодом 1ed8 я не вижу,
но они выводятся одним символом, если их записать через \x
Так чё мне, делать lookup table и хеш-таблицу замен для всех юникод-символов что-ли?
>смотри что я принёс:
>#include <stdio.h>
>void printCard(int card) {printf("\xF0\x9F\x82%c\n", 0xA1 + card % 13);}
>int main(void){for (int i = 0; i<10; i++){printCard(i);}}
>Этот пример - выводит 1 символ из нескольких \x байт.
>Как его сюда пришпандорить к \u - хуй знает.
>>69310
>Это компилятор за тебя "\uXXXX" в строках и символах обрабатывает.
>А ты хочешь сам обрабатывать, поэтому речь идет как раз о "\\uXXXX".
Итак, если, в твоём примере
указать "\\u1ed8" в строке, то слеш унескапается и получается '\u1ed8'
Получается оно так - и при выводе escaped string, и после функции.
Если же указать просто "\u1ed8", видно символ 'Ộ'
причём и при выводе escaped string, и при выводе результата функции.
Почему так? Да потому что разные байты в строках "\\u1ed8" и '\u1ed8'
Вот они, здесь: http://rextester.com/NMOR60766
И есть ещё конвертер, вот такой: https://r12a.github.io/app-conversion/
Эти байты можно видеть там где UTF-8 code units.
Как можно видеть, байт этих три, ничего общего между ними и кодом 1ed8 я не вижу,
но они выводятся одним символом, если их записать через \x
Так чё мне, делать lookup table и хеш-таблицу замен для всех юникод-символов что-ли?
1ed8 -> 0001'1110'1101'1000 (влезает в трехбайтовую последовательность UTF-8, которая хранит от 12 до 16 бит):
Leading UTF-8 byte: 1110 (префикс) 0001 (первые 4 бита).
Continuation byte: 10 (префикс) 111011 (еще 6 бит).
Continuation byte: 10 (префикс) 011000 (еще 6 бит).
Получаем: 11100001, 10111011, 10011000->e1, bb, 98.
О, ваще красава, годно расписал.
А префиксы эти статичные там, или они меняются?
Если не меняются, то вот что получилось: http://rextester.com/LANI21353
Только, по идее должен был бы печататься символ, а не строка.
Как в этом примере: http://rextester.com/NMOR60766
Но там два слеша перед x, в строке этой, поэтому и так...
Можно байты эти и прямо, цифрами в строку всунуть, как-то вот так:
char string[] = {225, 187, 152}; //e1, bb, 98
printf("%s", x);
Но руки только щас до этого дошли.
В общем, добра тебе, анон.
Коротко и ясно пояснил. Держи няшу.
>>1269824 (OP)
>>1269824 (OP)
>>1269824 (OP)
>>1269824 (OP)
Не заметил, что мы в бамплимите, извините.
> А префиксы эти статичные там, или они меняются?
Ну сходи ты хотя бы в википедию, там есть красивая табличка. У continuation bytes у всех префикс одинаковый: 10, после него 6 бит значения. У leading byte либо нолик в старшем бите, означающий ASCII-совместимый 7-битный символ, либо префикс из последовательности единиц и нолика за ними, количество единиц указывает количество битов в последовательности. Вот >>69795 тут 11100001 означает, что в последовательности 3 байта, считая и стартовый.
Вы видите копию треда, сохраненную 1 ноября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.