Вы видите копию треда, сохраненную 26 ноября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Хочу программировать под микроконтроллеры и байтоебить. Подкиньте хорошей литературы. И еще интересно, является ли знание сабжа, на достаточном уровне, так сказать плюсом в карму, при устройстве на работу. Алсо, большой роли плюсы в карму не играют, больше для себя собираюсь этим заниматься.
Си - это печать на всю жизнь
Освоил c#, python, erlang, haskell, go
А работа все равно уже 16 лет находится только на си и иногда на крестах
Все это мое "саморазвитие" нахуй никому не нужно
Прям хоть профессию меняй
Сидел в туалете, думал над твоим вопросом... Я вижу такой путь развития:
1) Читаешь K&R
2) Накатываешь FreeBSD
3) На няшной пишешь свой вариант утилиты dd, поглядывая в исходники оригинала при необходимости (https://svnweb.freebsd.org/base/release/10.0.0/bin/dd/). Если ты еще совсем нуб в Си - пишешь сперва эту: https://svnweb.freebsd.org/base/release/10.0.0/bin/mkdir/
4) Теперь пора делать проект средней сложности. Например накати иксы (gnome2 какой-нибудь) и с использованием gtk напиши какую-нибудь альфа-версию эмулятора некроприставки вроде NES. Чтобы можно было поиграть в марио без звука. Попутно осваивая потоки, работу с графикой через анальные прокладки GTK.
5) Сделал? Ты охуеннен. Ты уже можешь начать читать вот это http://www.osrtos.com/ с пониманием того, что тебе больше потребуется. Параллельно изучай спрос на рынке труда на различные мощные микроконтроллеры и необходимые применения.
6) Заказываешь отладочную плату подходящего тебе МК, например на пикриле распространенная плата ARM Cortex-M3 от NXP.
7) Портируешь на какую-нибудь RTOS свой некроэмулятор NES.
8) Выкладываешь на ютуб работу устройства чтобы потешить ЧСВ (хотя даже этим там уже никого не увидишь).
9) Начинаешь обивать пороги автомобильных, промышленных компаний, производителей бытовой техники, и прочих.
10) Работаешь в Рашке, тут главное не сдаться и не начать писать селекторы каналов для телевизоров Рекорд на 8-битном winchip до конца жизни.
11) Сдаешься в Корею в самсунг. Профит.
Слишком сложно? Ну тогда будешь максимум как дихальт - поддерживать некрожелезо на некропредприятиях за еду, как бомбила с паяльником и ассемблером. А насчет сложности - многие умудряются такие вещи делать на энтузиазме в свободное от работы время, но на С-way радикально не становятся.
Да что не так с жтк? Мне хоть один кутепидор может уже прояснить или нет?
У крестов был шанс, но шиза строструпа, мэнглинг и RTL-то все равно есть, а значит ее надо портировать. Это может быть и ок, быстрые программы писать можно, но быстро их писать уже нельзя.
> Идут года, сохнут глотки евангелистов, но на настоящий день не существует языка, который позволяет быстро писать быстрые и портабельные программы, за исключением няшной сишки
> Кроме сишки сиблядь нихуя не знает и не умеет
> 1. forth
> сейчас сейчас, еще неделю, я форт-систему уже почти совсем дописал
> 2. виртоговно
> сейчас сейчас, еще недельку, я собиратель мусора на стеке допишу
> 3. петухан-куриханыч
этот язык пока да, не знаю и не умею. У него есть библиотека времени выполнения
> У него есть библиотека времени выполнения
Надо полагать, сишные printf и malloc являются инструкциями процессора?
Собственно, хит эрат демонстрандум. Roost не смог стать еще толще и вытек из треда.
> Надо полагать, сишные printf и malloc являются инструкциями процессора?
Это СТАНДАРТНАЯ БИБЛИОТЕКА языка Си, но не библиотека времени выполнения. Программу без стандартной библиотеки написать на языке программирования можно, без RTL нет.
ОСТАНОВКА
Петухан таки в деле, даже как-то удивительно.
http://www.reddit.com/r/rust/comments/2iwtjh/151byte_static_binary_for_x8664_linux_in_rust/
Кстати где-то там еще годебилы на хабре были, правда они изящнее поступили и просто не стали писать сборщик мусора, объявив его НЕ НУЖНЫМ.
Ах ты гад, так это ты как раз та самая мифическая сиблядь, которая погрузила братюню в пучины отчаяния, заставив высрать очередную копипасту?
Тогда не знаю, поймешь ты или нет, но вот. Видишь, нет библиотеки времени выполнения, маллоков и принтфов.
>мэнглинг и RTL-то все равно есть
Мэнглинг не мешает, а без стдлибы вполне можно обойтись, так очень многие делают. На самом деле и без libc вполне можно жить - все равно обычно или при инициализации память берешь сколько нужно, или постраничными кусками. Так что без разницы, маллок дергать или сисколл. Работа с файлами через простенькую обертку, а больше ничего и не нужно по большому счету.
Удвою этого господина
>при инициализации память берешь сколько нужно, или постраничными кусками
На рубеже нулевых делали некий проект под freebsd
Быстро выяснилось, что стандартный malloc не использовал повторно освобожденные блоки
Короче в итоге так и обошлись - при старте делали sbrk на сконфигурированное значение, а управление кучей свое
Понятно. Очередные религиозные прыщефобии.
> самые охуенные языки программирования
> байтоебское дерьмецо, осваиваемое за 2 дня
Посмотри го-тред к примеру. Обсуждать тупую элементарную парашу смысла нет, поэтому обсуждают Илюшу.
Ada - элементарный язык? Ты ебанулся? Можно придумать и посложнее, конечно, но элементарным я бы не назвал.
Что касается C, то тут я тоже не согласен. Сам язык минимален, но для того, чтобы научиться писать на C надежный и легко поддерживаемый код, нужно времени побольше, чем 2 дня. И если в C нет "поддержки" ООП или ещё каких-то там возможностей в виде ключевых слов, то это не значит, что всего этого нет совсем, тебе точно также, как и с другими языками, нужно разобраться как на C правильно реализуются дженерики, рантайм полиморфизм и прочее. Зато простота и минималистичность самого языка дает преимущество в том плане, что сишный код всегда однозначно понятен, что сильно упрощает изучение чужого исходного кода.
>чтобы научиться писать на C надежный и легко поддерживаемый код, нужно времени побольше, чем 2 дня
Ясен хуй - он ведь для этого не предназначен. Можно и ложкой бассейн вычерпать больше чем за 2 дня.
>как на C правильно реализуются дженерики, рантайм полиморфизм и прочее
Через нечитаемые костыли. Плавали - знаем.
>сишный код всегда однозначно понятен
Троллинг_ор_джаст_ступид.жпг
>Ясен хуй - он ведь для этого не предназначен. Можно и ложкой бассейн вычерпать больше чем за 2 дня.
Суть в том, что на C научиться писать надежный и поддерживаемый код таки можно (см. успешные ОС), а такой же производительный на каком-нибудь хачкелле – нет.
>Через нечитаемые костыли. Плавали - знаем.
Нечитаемые костыли в C получаются, когда на него пытаются искусственно навесить слишком толстый слой абстракций, которого там не должно быть. Если рассматривать задачу всегда с практической точки зрения (то есть цель – то, как должна в итоге работать программа), то окажется, что все необходимое на C отлично реализуется, и не более многословно, чем в какой-нибудь джаве.
>>сишный код всегда однозначно понятен
>Троллинг_ор_джаст_ступид.жпг
Что не так?
> слишком толстый слой абстракций, которого там не должно быть
В самом деле, зачем нужны абстракции? Копипаст наше всё.
Это как посмотреть. В C копипаст, так или иначе, всегда делает какую-то реальную работу, и при этом его в большинстве случаев возможно заменить на функции/макросы, или как-то ещё переструктурировать код, избавившись от большинства повторений; в то время как в какой-нибудь джаве, например, "абстрактная" иерархия классов там, где это не нужно, вполне может оказаться кодом, по сути вообще ничего полезного не делающим.
> надежный и поддерживаемый код
> и не более многословно
Этот поехал уже в своем манямирке, уносите.
Сравнивая с джавой. Там обработка исключений точно также занимает немалую часть кода.
Для такого есть функции и в них циклы.
Открываешь все файлы, передаёт их на обработку, закрываешь — всего три функции.
Вызываются они внутри ещё одной функции.
Файлы будут закрыты в любом случае, т.к. в Сишке нет исключений, так что выполнение в любом случае приползёт к последней функции, закрывающей их.
Данный товарисч конечно же OCHE UMNY VIIYNOSHA но к сожалению он мудак.
Пiчальбида.
А если надо подгружать файлы в рантайме, ммм?
>правильно реализуются дженерики
мм, а как? я токо два варианта могу - на макросах запилить, тогда будет типизация работать по итогу, но отладка отвалитца
или на void*, тогда типизации не будет
C11 дает тебе еще один путь: делаешь копипастой сколько надо функций, а потом макрос с _Generic, который по типам аргументов выбирает нужное говно.
Правда нахуй это говно нужно кроме как "преобразовать в строку для печати" в толк не возьму. Ну да, есть еще трюки с "дефолтными аргументами", но это все настолько ненужно, что я прям даже не знаю.
Нет. _Generic это про другое. Суть дженериков же как раз заключается в избегании копипасты. А _Generic+макрос ближе к оверлоаду (правда толку от него все равно нет).
>>519350
На макросах типа #define GENERIC_SORT(name, type, comp_func) самый лучший вариант я считаю. С отладкой проблем нет, т.к. тот же clang, выдавая ошибку, показывает не только на строчку с инстанциированием, но и кусок раскрытого макроса с ошибкой. Плюс всегда есть ключ -E, позволяющий целиком увидеть во что раскрывается макрос.
Там тебе надо общий пррнцип понять, на примере каких-нибудь 8 ми битных микроконтроллеров.
RTOS не всегда нужна, для начала разберись как раьотает периферия.
Полно заказов на разраьотку по под процы, только мало кто умеет.
Одна из реальных задач: FSK модем на msp430.
> #define GENERIC_SORT(name, type, comp_func)
Ох уж эти костыли-костылики. Не говоря уже о том, что нет ничего более уёбищного, чем макросы на основе переписывания строк.
Плюс в том, что в этом случает ты используешь их только тогда, когда это действительно нужно, в отличие от крестов, что положительно влияет на скорость компиляции и размер кода.
В С++ ты делаешь весь класс темплейтным, хотя часто можно обойтись парой методов, а все тяжелое убрать из хедера. В си ты десять раз подумаешь, надо ли использовать дженерик на макросах.
Согласен. Веет чем-то настоящим. Но Java тоже пойдёт.
> нужно разобраться как на C правильно реализуются дженерики, рантайм полиморфизм и прочее.
Няшная - это низкоуровневый язык, который нужен чтобы возить байтики в тележках. И точка.
Хотя нет, это было когда-то там. Сейчас спецификации на всякие там кристаллы разрослись, одно Intel HD Audio чего стоит. Из-за этого начинают криво писаться драйвера, код плохо реюзается, каждому приходится разбираться заново. Так что эти ваши полиморфизмы с субтипами начинают быть все более нужными, даже в няшной.
>Так что эти ваши полиморфизмы с субтипами начинают быть все более нужными, даже в няшной.
No thanks. У нас уже есть эталон кривизны - драйвера ATI (хотя и Nvidia не отстает), нового не надо.
Эталон кривизны - это что-то из средневековья, этакое демонстративное устрашение темного люда.
Надо искать эталон прямизны, и, найдя его, пользоваться на здоровье и рассказывать другим.
>Надо искать эталон прямизны, и, найдя его, пользоваться на здоровье и рассказывать другим.
Абсолютно согласен, но где ж его найдешь?
Даже люди, проектирующие процессоры (невероятно ответственная работа), до сих пор не могут найти золотую середину в вопросе обратной совместимости, да так, что у одних дескриптор сегмента по всем восьми байтам распидорасило, а другие вешают новые команды на опкоды старых с префиксом.
1) задать разрядность signed/unsigned в битах/байтах?
2) обрушить программу при переполнении целого?
Вопрос про стандарты самого языка, однако, про gcc отдельно тоже интересно.
>который нужен чтобы возить байтики в тележках. И точка.
И правильно - ведь компьютеры и предназначены для перевозки байтиков. Бойлерплейт из абстракций не нужен, особенно сейчас, когда закон Мура закончился.
>задать разрядность signed/unsigned в битах/байтах?
#include <inttypes.h>
Там есть int8_t/uint8t/int16_t/uint16_t и так далее.
>обрушить программу при переполнении целого?
Насколько я знаю, в gcc нет такой фичи, только самопальные проверки. С ассемблерной вставкой полегче, но код превращается в нечитабельное говно:
add eax, dword ptr some_number
jo overflow_handler
Обосрался, не inttypes, а stdint.
Не пойми неправильно, дженерики на макросах и динамик диспатчинг бывают нужны в сишке в первую очередь как средство достижения максимальной эффективности программы, но никак не ради абстракций или облегчения кодинга. Например дженерик сортировка в виде макроса + инлайн функция сравнения = ноль оверхэда, в отличие от того же qsort из стандартной библиотеки. Также иногда бывает необходимо работать через общий интерфейс с массивом указателей на разные объкты - соответственно прицепляем к структурам vtable'ы или просто указатели на функции, т.к. это тупо самый быстрый способ выбора реализации функции когда конкретный тип объекта заранее не известен.
Вообще я имел ввиду то, что изучить сишку (как и любой язык) - это ведь не только запомнить синтаксис, который действительно можно за 2 дня выучить. Многое, для чего в большинстве других языков имеется какая-то специальная фича, в C возможно сделать кучей разных способов, и нужно не так уж мало времени потратить, чтобы выработать самые годные техники для всех ситуаций.
Алсо да, сорт оф RAII при помощи goto (как тут выше заметили) - жизненно важная штука. Также всем советую еще всегда возвращать из функции код ошибки, а результат - через переданный параметром указатель, тогда можно делать
if (((rc = func1(...)) != 0) ||
((rc = func2(...)) != 0) ||
((rc = func3(...)) != 0)) {
switch (rc) {
//обрабатываем ошибки
}
}
это самый компактный способ выполнить ряд операций, которые могут зафейлиться и, в случае чего, обработать ошибки.
Всё это очень простые вещи конечно, но таки тоже требуют уделить им внимание при изучении языка.
Тоже байтоебствую с stm32, компилятор gcc.
Передаю данные на индикатор функцией, которая на вход получает указатель на строку. Соответственно надо знать когда строки кончаются. Функция strlen из string.h успешно работает. Но она порождает слишком много ассемблерного кода - НИНУЖНА.
Непонятно как вообще может быть определена длинна строки, если передается только указатель? Нуль-терминатор? Но оно же токо в плюсах?
Попытался найти код функции strlen, нифига не нашел. Но если проект собирается, очевидно она есть. Где её можно взять?
Нуль-терминированные строки есть не только в плюсах, они появились задолго до появления языков высокого уровня, лол.
Я вижу два варианта:
1) Можешь сам написать аналог strlen,там ничего сложного.
2) Если не хочешь использовать нуль-терминированные строки, запили строки кортежем длина строки + сама строка.
Для байтоебства первый вариант предпочтительней.
В K&R вроде была strlen. Там же код тривиальный типа while(звезда str++)++len;
>ноль оверхэда
Указатели на функции, определение которых доступно компилятору, почти всегда инлайнятся. Разницы по скорости с темплейтом не будет.
Т.е. компилятор не будет вызывать библиотечный qsort, а сгенерит для меня специальную версию qsort'а с заинлайненым сравнением, так что ли?
Только если компилятору будет доступно определение qsort. Если бы qsort была объявлена в хидере, как и функция сравнения, то вызов бы заинлайнился.
От это да, потом нужно будет самому проверить. Я что-то всегда думал, что он инлайнит только вызовы по имени функции, а тут получается, что отслеживает значение в указателе и тоже инлайнит. Все ж таки действительно немало тонкостей в няшной.
Если инициализировать массив string literal'ом, при этом указав размер массива равный количеству букв, то '\0' в конец строки не добавится.
Напр. char str[4] = "test"; - нуль-терминатор добавлен не будет.
> Для байтоебства первый вариант предпочтительней.
Но почему, ведь второй вариант эффективнее, длина вычисляется за О(1)?
А вот это не работает с указателем. Так сразу попробовал.
Попробуй передай &stroka[0], ничего хорошего не получишь.
Байтоебство байтоебству рознь. Где-то нужно оптимизировать по памяти (вариант с кортежем отпадает), где-то по скорости.
Все равно в индикатор выталкиваю символы по 1ному. Да и строки короткие (1-5 символов).
Зато strlen вызывать не нужно - компилятор уже все посчитал.
Если для себя то не еби мозги себе и покупай Ардуину. Если хочешь действительно байтоебить то идешь на сайт easyelectronics и там проходишь учебный курс по AVR там все начинается с тру байтоебства ассемблера, но написано очень годно. Ну а по Си Кериган и Ричи классика.
че за плата на пике? Какую годноту посоветуешь почитать для того что бы впердоливать во всякие ARM Unix'ы?
а все в глаза долблюсь увидел что за плата.
LTO по идее должна и в объектном файле инлайнить. А из хидера должно и без LTO инлайнится.
1. Искусство программирования Unix.
2. Справочник по сям.
3. Хуилиарды кода на сях в СПО.
Опционально: собор и базар.
Зависит от операционной системы. Если что-то переносимое, то лучше два буфера, а если работает и так...
Алсо, почему C тред опять тонет?!
Мб как свифт-обезьяна переменную именует не буковками а смайликами.
Если допилю до вменяемого состояния, то будут конечно, правда там смотреть особо не на что. Просто в начале automatic блока создается объект – стэк, в который потом записываются указатели на объекты и указатели на деструкторы, в конце блока это всё в цикле вызывается и уничтожается. Сейчас мне надо придумать как лучше сделать обработку ошибок. Вообще, таких велосипедов уже написано > 9000, мне просто свой сделать захотелось.
В общем вот, если нужно:
http://rghost.net/download/6YFd4XFfB/cd85f1cdc7210c06eb4fda7ec6a15e654c36a32c/c_raii.zip
А теперь то же самое через подмену адреса возврата, чтобы с return работало, а не только с break.
>через подмену адреса возврата
Будет не портабельно же. Если там добавить глобальную переменную const struct deinit_stack deinit_stack и потом сделать #define return auto_deinit(&deinit_stack); return, то будет тоже работать с return по идее. Алсо, в любом случае это всё хуита, ни один нормальный человек не станет всерьёз использовать что-то такое.
поясните за ключевые слова automatic и release, в гугле ничего не нашел. Это точно чистый Си?
а все понял
>впервые увидел как меняют синтаксис сишки макросами
Ни в коем случае не заходи на http://libcello.org/, вообще охуеешь.
Стоп, а разве в pure c запрещены {}-блоки без костылей типа do-while (0)? Может быть, я что-то не понимаю, но разве вместо autovar нельзя просто объявить переменные внутри блока, чтобы они автоматическими были? Или у меня мозги поражены крестами, лол.
То есть у тебя break'и используются в блоках как "исключения для бедных", лол? Я бы на твоем месте сделал для такого обычные блоки и отдельный макрос, который делает goto за закрывающую скобку. Вроде был инструмент для генерации уникальных меток, но я запамятовал. Гулять так гулять, а по производительности это будет лучше, чем циклы, которые выполняются один раз.
Алсо, цикл выкидывается, даже если без оптимизаций собирать - этой идиоме больше лет, чем тебе.
\tdouble a = 123.45678901234567;
\tprintf("%.14lf\n", a);
выводит 123.45678901234567, как он умещает 17-й разряд?
можно по подробнее я правильно понимаю, что иногда, когда в экспоненте хватает места, часть мантисы он может переложить в экспоненту? В мантисе храниться 1.9290123283179010, а не 1.2345678901234567, как я думал. Или где тогда она?
Да похуй, зачем пессимизировать преждевременно? А еще - отдельный макрос на выход с деинициализацией будет няшнее, чем break, выглядит, как отдельная команда.
Они там совсем ебанулись, добавили лишних знаков и конструкций и пишут про повышение уровня си. Лучше бы библиотеку стандартную расширяли.
Кстати, почему для сей нет человеческой библиотеки коллекций? Даже обосранный резиновый стэк самому приходится писать.
Энджой ер сишечка.
Потому что после блока {} не должно быть точки с запятой, если ожидается else.
Во всех языках с сишным синтаксисом после if и else надо statement. Или это expression statement (выражение, которое на ; заканчивается) или это statement с ключевым словом (ну тот же do или вложенный if), или это compound statement ({ такая хуйня в фигурных скобочках }).
Если ты написал if (expr) {y}; else ..., то после (expr) у тебя уже ДВА statement (compound в { скобочках } и пустое выражение с ;). Компилятор после второго statement уже не ожидает никакого else, поэтому и охуевает, внезапно его встретив.
А если просто писать HUI (hui), без точки с запятой? Тогда ведь можно обойтись блоком, его можно будет вставить везде.
Брайан Керниган, Деннис Ритчи: «Язык программирования Си»,
Tony Albrecht: «Pitfalls of Object Oriented Programming»,
MISRA-C:2004 Language Guidelines,
Rob Pike: «Notes on Programming in C»,
Peter Krzyzanowski: «C Programming Style»
И незабывайте-про:
http://fprog.ru/2009/issue1/eugene-kirpichov-fighting-mutable-state/
А не то.
> fprog.ru/2009/issue1/eugene-kirpichov-fighting-mutable-state/
Хуета какая-то от неосилятора.
А ну да, у тебя ж еще и MISRA в списке. Тогда понятно: ты перечисляешь способы скатить мощь сишечки до своей любимой функциональнойпарашинейм.
>Rob Pike: «Notes on Programming in C»
Где можно скачать полностью? На первой странице в гугле только маленький кусок.
gcc/MinGW.
Вроде бы одно и то же, но в Кернигане и Ритчи int не объявляют, а в интернетике во всех кодах его ставят. Зачем?
Для шиндоус: Pelles C (полная поддержка C99/C11), и, внезапно, вижуал студия 2015 (там почти все необходимое, наконец, запилили, да и сам компилятор весьма неплох).
>>531750
Во времена K&R все функции по умолчанию возвращали int, если не было указано иное. В современных редакциях стандарта это пофиксили, теперь нужно писать тип возвращаемого значения, а старое поведение deprecated и кое-где уже даже не поддерживается. Я не уверен, но вроде в свежей редакции K&R тоже уже правильно, посмотри сам.. Алсо, int main() - это плюсы, а в сишечке - int main(void) или int main(int argc, char argv).
Бери Community Edition, она бесплатная: входишь в аккаунт Microsoft, она сама активируется, опционально выходишь и удаляешь аккаунт Microsoft.
Спасибо! Может, есть новое издание, попробую поискать.
А вот int main(void), кстати, ни разу не видел. Везде в скобках ничего нет. Это тоже уже устаревшая версия записи?
Пустые скобки в C в отличие от C++, где они эквивалентны (void) означают неизвестное число параметров. Например:
[code lang="c"]
int foo (); //declaration
//...
foo (1); //call
//...
int foo (int input) //definition
{
//...
}
[/code]
#include <stdio.h>
#include <string.h>
Если я не делаю второй инклуд, то компилятор ругается на встроенную функцию strlen.
[Warning] incompatible implicit declaration of built-in function 'strlen'
Почему так? Ведь без инклуда string.h этот код просто не должен компилироваться. Должна быть ошибка "такой функции нет".
Ты упоминаешь ее, и тем самым неявно объявляешь. Компилироваться должно, компоноваться нет.
А теперь и пустые скобки нельзя. Для функций с переменным числом аргументов надо как минимум один аргумент и ..., а для остальных нужно явно указывать аргументы.
>>531799
Компилятор "знает" такую функцию, чтобы в определенных режимах (с оптимизацией) заменять ее вызов на эквивалентный код. Это "знание" не на уровне языка (не декларация), а на уровне компилятора. Так как функция при вызове неявно >>531753 объявляется как int strlen(), а компилятору известно о другом, он ругается.
Кстати, вот ещё вопрос: в программах в интернетике в конце описания функции main ставят действие "return 0;". Обязательно ли его вставлять?
Нет, для main (и только для нее!) есть исключение: если выполнение доходит до конца функции, неявно возвращается 0.
0 - код успешного завершения программы. передаётся выше в ОС. любой не 0 = в ходе выполнения была ошибка.
В стандарте весело, кстати. Есть 0, EXIT_SUCCESS (может совпадать, и таки совпадает с 0) и EXIT_FAILURE, а остальные коды возврата - implementation defined. На деле, конечно, так, как ты сказал.
Это тоже хинт, как register, restrict и const. Если register предлагает компилятору ускорить доступ к переменной, то inline предлагает ему ускорить вызов функции. И, в отличие от register, компиляторы хоть и не всегда, но все же часто обращают на это внимание, подставляя тело inline-функции в месте ее вызова (что позволяет потом оптимизировать код еще больше). Современные компиляторы, опять же, и сами инлайнить умеют очень хорошо, но если функция несложная, маленькая, то inline можно указать а если ты уверен, что так точно будет лучше, то иногда даже какой-нибудь нестандартный __forceinline/__attribute__((always_inline)), т.е., "инлайни и ниебёт" можно воткнуть. Обычно в пример оправданного инлайна приводят какую-нибудь векторную арифметику - несколько выражений без ветвлений будут развернуты в десяток-два инструкций в месте вызова и отработают гораздо быстрее, без затрат времени на передачу аргументов, не сбрасывая конвейер процессора и т.п.
LGPL же. Можно линковать со своими проектами.
Это могила Берроуза?
лал
Да, const по сути просто хинт. Но ты-то, как и с другими хинтами, в любом случае обязан соблюдать ограничения, которые спецификатор накладывает.
Юрия Петухова.
Вот без сорсов луа:
C:\gcc-lua-install\tdm-gcc\bin>gcc C:\gcc-lua-install\srlua.c
C:\gcc-lua-install\srlua.c:19:17: fatal error: lua.h: No such file or directory
compilation terminated.
Вот с ними:
http://pastebin.com/6wXWCtLN
Без сорсов, очевидно, нужны заголовочные файлы и либа.
С сорсами, очевидно, тоже нужны заголовочные файлы и... лучше собрать либу.
CMake поставить не пробовал? Хочешь руками?
Возьми на http://luadist.org/ уже собранные либы lua (тебе нужны оттуда include/.h и lib/.a? ну и .dll потом), укажи пути в команде компилятору (gcc -Iпуть-к-папке-с-h srlua.c полный-путь-к-liblua.dll.a)
ЕМНИП, не нужно. Но компилятор ругнётся, что выполняется неявное преобразование.
Хуй тебе. Нужно преобразовывать иначе пикрил. Хотя возможно, это зависит от компилятора.
То, что ты написал long, а по факту там хитровыебанный int, потому и не ругается. Ты могу бы вообще char написать.
Пикрелейтед. Ничего, что MinGW?
Даже если из float в long или даже в char. Компилятору плевать на это.
Ну по поводу float, все немного по-другому... А вообще, почему мы спорим? Я говорю, кто-то написал, что компилятор выдаст ошибку, я говорю что компилятор не выдает ошибки, ты говоришь почему так, я и так знал почему и мы спорим не из-за чего.
Это я написал, что компилятор выдаст предупреждение. По-хорошему, вот если так по-честному, то должен бы.
Watcom.
GCC
Это от машины зависит:
> Тип short часто имеет размер 16 бит, long — 32 бита, a int — или
> 16, или 32. Компилятору разрешено самостоятельно выбирать размер в соответствии с
> характеристиками аппаратуры и следующими ограничениями: числа типа short и int
> должны иметь длину не менее 16 бит, long — не менее 32 бит; тип short должен быть
> не длиннее int, a int — не длиннее long.
У меня, например, на x86 long идентичен int и переполнение в обоих случаях.
Как мне это скормить fscanf, чтобы он считал эту запись в соответствующие переменные?
Как мне это скормить fscanf, чтобы он считал эту запись в соответствующие переменные?
fscanf - хуета для одноразового кода, парси вручную (strtok, strtol, strtod, все дела).
> fscanf ("%s[^:]%d", key, &value)
Да, примерно так оно и делается. Только у тебя размер буфера не указан (что будет, если введешь больше, чем размер key?). Надо:
"%размер[^:]: %d"
>-Wconversion
В примере >>534007 это не сработает, потому что там присваивается произведение переменных с типом int переменной с типом long. int может быть преобразован в long без потери информации, значит неявное преобразование не может испортить значение, т.е. предупреждение не выведется. Значение портит переполнение вызванное произведением переменных типа int. Чтобы этого не было, нужно один из операндов преобразовать в long.
Если это единственный return, то лучше ничего не писать. А вообще, exit для других функций оставь, а в main лучше return (вопрос вкуса, реальной разницы нет).
А, вы о таких вещах. Ну это да.
Если ты можешь пропустить где-то \0, то и решай эту проблему - напиши раз и навсегда себе модуль для работы со строками, ну и внимательнее будь. А так, да, calloc может немного подстраховать. Но ты с таким же успехом можешь в длине на 1 ошибиться и затереть самый последний \0.
А ты посмотри что происходит после return 0 - например, в gcc после этого вызывается exit(return_value)
Зачем оно тебе? С поддержкой очень безрадостно пока. Почитай лучше про pthreads/Windows processes and threads, будет намного полезнее.
Тот кусок уже не нашел, но вот аналогичный. Это из мануалов по обфускации кода и приемам антиотладки.
Теперь я понял, почему мой компилятор жаловался на метки. Честно говоря, никогда не сталкивался с такой штукой и могу предположить только, что это. Надо будет и самому почитать про это. Интересно же.
Да, это вообще охуенно. И материалы классные. Там надо знать не только си на высоком уровне, но еще и теорию чисел.
Брось ты это дело. Нет лома против иды, деобфускатора типа миазмы, и маленькой тележки знаний наподобие http://pferrie.host22.com/papers/antidebug.pdf
Еще походу в Си && используется для взятия адреса метки(label). Вот хуй знает где это в стандарте, мож кто подкинет
Вот че в инетах нашел
Note: In GNU C the operator '&&' may also be used as unary operator for taking addresses of labels.
https://ideone.com/abSF9g
Как все сложно то...
Ну видимо ты не можешь редактировать .text секцию просто так. Не знаю как на винде, на линухе надо вызвать mprotect.
Потому что ideone компилирует с gcc -O2, так что твой самомодифицирующийся код нихуя не делает.
Ничего. Он не может работать. Память с кодом всегда read-only, сделать ее read-write тебе ос не позволит, да и вообще нахуя ты собрался опкоды на бред менять? Даже если ты их поменяешь, скорее всего получишь undefined instruction.
книжку читай внимательнее, там в main вызывается makeCodeWritable(...). Наверняка выше было реализация этой функции.
https://books.google.com.ua/books?id=mig-bH3u0Z0C&pg=PT292&lpg=PT292&dq=char+p%3D%26%26begin&source=bl&ots=b3rFht4xWo&sig=LT2URWU1FAe7He7XqrjamftX17A&hl=ru&sa=X&ved=0CCwQ6AEwAmoVChMI2v7Bs-XCxwIVJaZyCh1VTw__#v=onepage&q=char%20p%3D%26%26begin&f=false
гуглить надо, у меня нет. Гугли VirtualProtect для винды и mprotect для линухи. Вроде так
Что не так в этой сортировки? Почему она работает слишком медленно. Даже 256 элементов, занимает почти секунду.
Все. Вопрос закрыт. Я кретин. Прошу прощения за то, что потревожил. Дело было в строке: 7.
OST_BALT{}y - pizdoglazyie
Она у меня тупо вызывается через call, а я хочу чтоб компилятор ее на место вызова вставил.
Скопируй исходник функции себе в проект и делай с ним, что угодно. По-другому никак.
собрать статически, не?
системные вызовы
Вызывай функцию в цикле, устраивай цикл внутри функции, запускай в цикле функции, которые выполняют внутри себя цикл, внутри которого вызываются функции.
Научись в fopen/fgetc/fputc и напиши упаковщик методом RLE.
Структуры, ссылки, указатели. Напиши наследование структур с виртуальной таблицей методов.
Она ко дну никогда не пойдёт, но востребована в очень узком секторе.
[code]
#include <sys/inotify.h>
#include <linux/limits.h>
...
const size_t kMaxEvent = sizeof(struct inotify_event) + NAME_MAX + 1;
char buf[kMaxEvent] = ""; // buffer for at least 1 event
[/code]
При этом в /usr/include/linux/limits.h:11:
#define NAME_MAX 255\t/ # chars in a file name /
А в /usr/include/linux/inotify.h:
[code]
struct inotify_event {
__s32 wd;
__u32 mask;
__u32 cookie;
__u32 len;
char name[0];
};
[/code]
Ведь конец должен считаться просто указателем? Не зря же меня заставили вручную возможную длину учитывать добавлением NAME_MAX?
[code]
#include <sys/inotify.h>
#include <linux/limits.h>
...
const size_t kMaxEvent = sizeof(struct inotify_event) + NAME_MAX + 1;
char buf[kMaxEvent] = ""; // buffer for at least 1 event
[/code]
При этом в /usr/include/linux/limits.h:11:
#define NAME_MAX 255\t/ # chars in a file name /
А в /usr/include/linux/inotify.h:
[code]
struct inotify_event {
__s32 wd;
__u32 mask;
__u32 cookie;
__u32 len;
char name[0];
};
[/code]
Ведь конец должен считаться просто указателем? Не зря же меня заставили вручную возможную длину учитывать добавлением NAME_MAX?
Разве NAME_MAX тут это не максимальный возможный размер? А sizeof(struct inotify_event) + NAME_MAX + 1 его всегда будет превышать. Хотя это не важно.
Я, вероятно, хуйню скажу, но может из-за переменного размера (хотя он и конст...) компилятор разделяет строку "char buf[kMaxEvent] = "";" на
char buf[kMaxEvent];
buf = "";
А присваивать так значение массиву нельзя, только при инициализации можно.
Можно же, их просто инициализировать нельзя.
int ar[n];
int i =0;
for (i=0; i<n; i++){
ar = i;
}
хм, там ar[и] внутри лупа, конечно же.
>Разве NAME_MAX тут это не максимальный возможный размер?
NAME_MAX - максимально возможный размер имени файла, а та структура состоит из имени файла и прочей лабуды
>>540112
>Можно же, их просто инициализировать нельзя.
Похоже, что это правильный ответ. Даже в тривиальном случае:
const size_t kMaxEvent = 10;
char buf[kMaxEvent] = {0};
Нельзя.
#define kMaxEvent sizeof(struct inotify_event) + NAME_MAX + 1;
Энджой ер сишечка, в которой const - нихуя не конст и может меняться в рантайме.
https://ideone.com/6owLDE
struct list root = NULL;
struct list *tmp = &root;
хуя ты извращенец
ну если одна звёздочка - это указатель, то две - это указатель на указатель
>>534844
Прошу тебя, не надо это писать. Хотя книгу поверхностно почитать может и полезно будет.
Лучше изучай LLVM http://habrahabr.ru/company/abbyy/blog/265871/
Господа, посоветуйте годный учебник для дебилов, где были бы изложены все нюансы С11.
Берёшь документацию и читаешь.
http://www.iso.org/iso/ru/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853
Ах да, ты же дебил. Ну извини, годной инфы для дебилов не завезли, это тебе в детсаду надо спросить.
Но он прав. Разве что покупать стандарт не обязательно. Ты ведь не разработчик компилятора, а хуй простой, так что последнего черновика (N1570) тебе вполне достаточно. Есть "21st Century C", её тут иногда советуют, но книжка на троечку. Если ты только учишь язык, найди книгу по C99, их дохуя, а потом просто посмотри список нововведений в С11.
Только не забывай, что код в K&R - адов говнокод по современным меркам, а в режиме С99/C11 некоторые примеры даже не скомпилируются.
Приведи пример говнокода из K&R. Именно говнокода, а не кода, который не удовлетворяет современным стандартам.
Абзац про goto. Хотя там так и сказано, что так делают только черви-пидоры, хуже которых нет.
Так код, который не удовлетворяет стандартам - он говнокод и есть. Стандарты не из воздуха писались по крайней мере, бОльшая их часть. Множество примеров уязвимы к переполнению буфера, однобуквенные переменные, extern декларации внутри функции, implicit int, "лесенки" из вложенных for/if/while, вот это всё. Сейчас проглядел - оно лучше, чем я о нём думал. Видимо, на меня так кривой скан русского издания повлиял много лет назад. Но аргументы в силе: лучше брать что-нибудь менее протухшее.
>>544421
А вот с тобой не соглашусь. Пример для вложенного for адекватен (лучше бы туда return воткнуть, но это не всегда то, что нужно). Пример для goto cleanup - это вообще единственный способ сделать нормальную очистку без дублирования if (fp) fclose(fp) и if (obj) { free(obj->data); free(obj); } при каждой ошибке.
>Так код, который не удовлетворяет стандартам - он говнокод и есть.
Довольно странное определение. Если говорить о времени, когда была написана K&R, то код удовлетворял стандартам, а значит - не был говнокодом. Со временем стандарты поменялись, код остался тем же, но стал говнокодом. Выходит, что результат проверки, является ли код говнокодом, не постоянен во времени и зависит не от самого кода, а от того, какие на данный момент актуальны стандарты в языке.
>Пример для вложенного for адекватен
Не совсем, если fastjump ведёт не на завершение метода, а после него что-то ещё делается кроме очистки, это уже говнокод, а не fastjump.
Ну вот у нас тут goto-срач намечается. Были времена, когда можно было себе позволить писать на бейсике лапшу из GOTO, приправляя её POKE с магическими числами, и это было нормально пока один теорехтетик не вскукарекнул про considered harmful. Теперь это однозначный говнокод.
Так и с K&R. Это было нормально, например, потому, что программу писало полтора человека, которые отлично знали и сам язык, и свой код. Это было нормально, когда программы не торчали переполняющимся буфером в интернет. А теперь у нас гитхаб, и надо писать так, чтобы понял мимохуй, который сишечку вообще не учил, а учил плюсы "за 24 часа". И желательно вдалбливать про безопасность не в послесловии, а при первом упоминании массива или указателя. И про signed/unsigned тоже. И про UB до кучи, а то компиляторы стали умные и делают то, что разрешено стандартом, а не то, что ожидает человек, прочитавший K&R.
>>544449
> Не совсем, если fastjump ведёт не на завершение метода
Если бы это было завершение метода, то можно было бы сделать очистку и return прямо в for, а обычно хочется хотя бы, допустим, записать что-то в найденный элемент, что обычно и делается.
ладно, не обращайте внимания, я упорот
>Ну вот у нас тут goto-срач намечается ... Теперь это однозначный говнокод.
В низкоуровневом программировании на С оператор goto активно используется, это уже вроде 100500 раз перетирали.
>компиляторы стали умные и делают то, что разрешено стандартом, а не то, что ожидает человек, прочитавший K&R
Я не утверждаю, что код из K&R актуальный. Тот, кто изучает C по K&R, должен обязательно учитывать, что язык сильно поменялся с того времени. Но, извини, я всё ещё не могу считать исключительно по этой причине код, предложенный в той книге, говнокодом.
Для того, чтобы перевестись в другой универ, нужно за полгода хоть на каком-то уровне выучить С абсолютно очевидно потому, что у них этот курс есть, а у нас - нет.
Скачал Dev C++, но он пока не может обработать даже банальный хеллоуволд. Гугл говорит, это потому, что у меня windows 8.1, слишком новая система для MinGW. Я подозреваю, это ещё и потому, что система не простая, а 64-разрядная. Соответственно, вопрос - есть какие-то ещё среды работы с Pure C под 8.1, или стоит ебаться с Dev C++? Или вообще готовиться к анальной ебле с каким-нибудь древним Turbo C?
Ставь CodeLite + TDN-MinGW 64 (можно и х86, но зачем?). Работает везде, на 10-ке в том числе. А вообще под винду удобнее в Visual Studio писать.
Алсо проверь правильность PATH.
>>544558
Вот двачую вижуал студию. Они в 2015 допилили поддержку современной сишечки до приемлемого уровня. Пару галочек уберёшь на тему ололо-safer-функций, и для новичка будет ок. Особенно если ты не смог MinGW поставить почему-то.
>>544497
> В низкоуровневом программировании на С оператор goto активно используется
Ты код на бейсике, про который я говорю, не застал или забыл? То, как сейчас goto используется (даже в GCC-шном стиле с адресами меток), не идет ни в какое сравнение с тем, что было.
> Я не утверждаю, что код из K&R актуальный.
> Тот, кто изучает C по K&R, должен обязательно учитывать
Тот, кто изучает K&R не может этого учитывать. Он не знает, как правильно. Он не может делать скидку на возраст книги. Он язык только учит, он не может пока различать, хороший код тогда и хороший код сейчас. И после K&R ему приходится... ну не переучиваться, но ломать некоторые плохие привычки. Я не утверждаю, что K&R нужно выкинуть. Ее нужно почитать (задачки там, вся хуйня), но лучше бы, чтобы она не была первой книгой.
>Ты код на бейсике, про который я говорю, не застал или забыл?
Мы вроде о C говорим, не? Я лично с бейсиком вообще не сталкивался и особо не стремился.
>Тот, кто изучает K&R не может этого учитывать. Он не знает, как правильно. Он не может делать скидку на возраст книги. Он язык только учит, он не может пока различать, хороший код тогда и хороший код сейчас.
Ты крайне плохо думаешь о новичках. Я читал эту книгу, и я это всё учитывал.
>но лучше бы, чтобы она не была первой книгой
Поправлю, она не должна быть единственным источником информации о языке C. Но первой книгой может быть вполне, какой и была в моём случае.
>но лучше бы, чтобы она не была первой книгой
Стиль кодирования от автора, мелкие буквы, где стоят знаки подчёркивания, пробелы и т.д. все дела.
>ну на этой версии Dev C++ уже стояла сравнительно новая версия, поэтому нужно было разбираться больше. Отсюда и вопрос - стоит ли ебаться
Если тебе принципиально нужно работать в кроссплатформенной IDE, то поебаться стоит. В итоге у тебя на разных машинах будет одинаковая среда разработки, что очень удобно. На винде 99% проблем с MinGW - это кривая переменная среды PATH. Dev C++ просто не видит компилятора или инклюды. Почитай внимательнее ошибки.
Но если линукс не нужен, но ставь VS и просто забудь про эту еблю с MinGW.
>>544566
Посоны, изучаю С по K&R. Планирую после обмазаться Linux Kernel Style Guide. Этого будет достаточно?
>>544585
>она не должна быть единственным источником информации о языке C
Получается, что ты либо читаешь еще одну книгу параллельно/после (зачем тогда K&R? время не резиновое), либо гуглишь статьи и вопросы на SO - но, чтобы их гуглить, нужно уже знать, что ты хочешь найти.
Я так и не вразумею, когда прописываешь [code]int a = 10;[/code]
Программа где резервирует ~4 байта для переменной a?
Я слыхал что в block scope, ну типа в самом файле сурс кода, но в другом случае я углядел что там немного хитровыебанно, и по какой-то там hex формуле что ли хранится чето такое, потом из memory как то выгребается
кто-нить может по-русски уже сказать
2. Как написать 10^10 но так, чтобы программа calculated это значение? А то приходится писать как 1 000 000 0000 чтобы работало и калькулировала.
>зачем тогда K&R?
Вот меня этот вопрос тоже волнует. Перекатываюсь на си и кресты с шарпа, и сразу встала проблема с литературой. Ну то есть хотелось бы найти некий относительно современный толмуд, куда можно было бы обращаться по необходимости, а не только SO шкурить. В шарпе это решается очень просто - кнопкой F1 плюс хелп постоянно обновляется, следуя за новыми фишками языка и это не говоря уже про StyleCop и Resharper. По крестам книг просто вагон, С++14 уже нормально расписан, поэтому тоже вопросов особо не возникает.
А с си как-то всё печально. Не, у меня, конечно есть книга 1995 года,. но это как-то несерьёзно по-моему.
Другой нуб вкатывается. Бородатые дядьки, поправляйте.
1. Короч, есть такие понятия как declaration, definition и initialization (сори, не знаю как definition перевести). Declaration - это дать знать компилятору о новой сущности, чтобы он мог искать ошибки с ее использованием (int a;). Definition - выделяет память под эту сущность (сюрприз! в С int a; одновременно и declaration, и definition). Initialization - заполнить выделенную память чем-то на твой выбор. (int a = 10; - все три действия сразу). Разницу между Declaration и Definition легче просмотреть с функциями: void a(); - declaration; void a() { return 0; } (с телом) - definition.
Память под int a = 10; скорее всего выделена в стэке, кроме случая, если это написано вне функций - тогда в data segment.
2. Вроде в С нету такого оператора.
1. Да забей ты на её местоположение, нахуя тебе знать, где она лежит?
2. Если компилятор не вычисляет, то либо функцию используй, либо вычисляй заранее.
Я же. Теперь моя проблема.
Я родил пару минут назад гениальный код:
char a = "abc";
(a + i) = 'z'; // i == 0; ожидание: "zbc"
И получил сегфолтом по лицу.
Забегая наперед, я уже понял что "abc" это статическая строка прямо в бинарнике, который в памяти ридонли. Проблема в том, что я это понял, случайно связав воспомниания с SO и каких-то книг. До того, как меня стукнуло это осознание, я разглядывал core dump в gdb (думал что у меня a + i выскакивает) и ни к чему не пришел.
Вопрос: каков должен быть порядок действий в gdb или неважно где, чтобы дебаггинг меня провел по такому пути. Segfault at line 2 (это было) -> Segfault cause: Write to RO area -> The area = text segment (RO) ну и следующий из этого очевидный вывод, что a указывает на text segment.
В моем же случае было Segfault at line 2 -> долго смотрел на line 2 -> ДОГАДАЛСЯ))) -> a указывает на text segment. Хочу нормальный последовательный подход.
Сорян, звездочки проебал, там a это указатель, и (a + i) берется по адресу.
> когда прописываешь int a = 10;
> где резервирует ~4 байта для переменной a
Есть два с половиной стула. Либо ты прописываешь это внутри функции, тогда переменная будет автоматической, место под нее выделится в стеке при входе в функцию, а при выходе переменная с точки зрения языка перестанет существовать. Либо ты пишешь снаружи функции (а также внутри функции, но с ключевым словом static), тогда место под переменную будет один раз отведено при компиляции, и она будет жить после загрузки программы до ее завершения на одном и том же месте.
> какой-то там hex формуле
Поясни поподробнее. Может, тебе показывали код на асме для доступа к автоматической и статической переменной?
> Как написать 10^10
Ты можешь использовать scientific notation (1e10), но будь осторожнее.
Во-первых, это значение на 32-битной системе влезет только в long long (в обычный unsigned long влезает только 4.2e9).
Во-вторых, эта нотация определяет литералы с плавающей точкой (которые обрезаются до целого при присваивании к целочисленной переменной). Со всеми вытекающими последствиями в виде невозможности точно представить некоторые значения (хотя в double без потерь влезет всё, что тебе может пригодиться, лучше об этом помнить).
>>544896
> declaration, definition и initialization
Что-то типа объявление, определение, инициализация.
>>544901
char a[] = "abc";
> Хочу нормальный последовательный подход.
Сегфолт может быть либо потому, что по адресу ничего не замаплено (решается раздумьями, откуда в программе взялся такой указатель), либо потому что память не читается (то же), либо не пишется (то же + тут как раз может быть read-only память). Можешь сделать readelf -l и/или info proc mem и т. п. в gdb.
>Можешь сделать readelf -l и/или info proc mem и т. п. в gdb.
Спасибо, readelf мне показался трудночитаемым, да выше дата сегмента ничего нет, а вот (gdb) info proc mappings (и pmap) - это находка.
>зачем тогда K&R? время не резиновое
Затем, что классика. Но, согласен, если ты хочешь побыстрей всё выучить и начать зарабатывать деньги, то да, можешь не читать. Эта книга больше интересна тем, кто любит язык C и хотел бы узнать о нём, как можно больше.
>гуглишь статьи и вопросы на SO
Тащемто есть ещё man, если ты работаешь в UNIX-like ОС. Для меня это достаточно исчерпывающий источник информации. Под виндой, по идее, тоже должен быть аналог.
>Declaration - это дать знать компилятору о новой сущности, чтобы он мог искать ошибки с ее использованием
ты делаешь declaration переменной, расположенной в другой единице трансляции, чтобы сделать возможной ее использование в этой единице трансляции
компилятор же обрабатыват каждую единицу трансляции (по сути .c файл с кодом) по отдельности, формируя объектные obj файлы, далее линковщик все это собирает в исполняемый файл
другое дело, что правила declaration разные, для переменных нужно дописывать extern, для функций пишешь прототипы, свои заморочки есть для структур - тут разрабы языка поступили, как и в других случаях - строгость, формальность языка была приведена в жертву удобству и краткости
> правила declaration разные, для переменных нужно дописывать extern, для функций пишешь прототипы
Для переменных не всегда обязателен extern. Но extern позволяет избежать лишних проблем. И для функций тоже можно extern, но это не решает никаких проблем, поэтому extern не пишут.
Есть один пример, выносящий мозг новичкам:
1.c:
int foo[1];
void bar(void) {
++foo[0];
}
2.c:
#include <stdio.h>
int foo[16384];
int foo[16384];
int foo[16384];
int main(void) {
extern void bar(void);
bar();
printf("foo[0] = %i\n", foo[0]);
return 0;
}
Магия! extern нет, размерность разная, definition нет, но это почему то работает. Не отвечай. Мы-то с тобой знаем, где здесь что, как работает, и какие тут проблемы. Но дай анонам самим подумать.
> Не отвечай. Мы-то с тобой знаем, где здесь что, как работает, и какие тут проблемы. Но дай анонам самим подумать.
ох ебать, ну что за выебоны
>выносящий мозг
Ну и что в нём выносящего?
Алсо С++ компилятор пошлёт тебя в жопу с твоими int foo[16384]. Пример говнокода as is.
>Но, согласен, если ты хочешь побыстрей всё выучить и начать зарабатывать деньги, то да, можешь не читать.
За живое задел. Я изучаю С УЖЕ отрезав время от других, более перспективных в отношении денег, вещей. И переутомление подсказывает, что совмещение всего мне пора заканчивать. С - самое интересное и, увы, самое низкоприоритетное из моих занятий, а время и силы в следующий раз где-то через год будут.
>но это почему то работает
> This is mentioned in the C standard in informative Annex J as a common extension:
>
> J.5.11 Multiple external definitions
>
> There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
>>545125
Тут следукт понимать, что кроме стандарта есть и реализация, произвольная. Например, IAR такой код проглатывает, но не проверяет сигнатуру функций.
А от extern функций тоже бывает польза. Вот я в текущем проекте ими реализовал своего рода интерфейс модуля расширения, и проверка его корректности съехала, таким образом, на линковщик.
А хуле ещё обсуждать? Не инжекты в процессы же, лол. Зато сверху вон привели классический пример, из-за которого Си люто ненавидим. Любой, сука, зстет может превратить код в нечитаемое и несопровождаемое говно. Что в мэйнстримных языках сделать несколько сложнее.
Я и не говорил, что это хороший код. Я говорил, что этот код работает.
> J.5.11
Фактически, про UB там написано потому, что в одном translation unit может быть int, а в другом float, и тогда это, конечно же, UB. Одинакового размера. А механизм, позволяющий код типа >>545125 был введен в свое время не потому что >>545109
> строгость, формальность языка была приведена в жертву удобству и краткости
а потому что весь механизм заимствован и поддерживался для линковки с Fortran. И оно будет работать, потому что это де-факто стандарт и еще из-за того, что линкеру на стандарт сишечки похуй, что бы там комитет по этому поводу не думал. Хотя это и не повод так писать в наши дни.
>>545258
> С++ компилятор пошлёт тебя в жопу
У нас тут про сишечку тредик, если ты не заметил. А в сишечке это полностью валидный код. Ну, пока типы/размеры совпадают, да.
>>545303
Не совсем понял, о чём ты. Функции и так extern. Их можно сделать static, но по умолчанию они extern.
задачка такова.
есть ОП пик - на нем изображена оптопара.
необходимо на любом доступном вам языке написать код осуществляющий инкремент и декремент переменной в зависимости от вращения колеса относительно оптопары.
так как было очень дахуя тупых школоты=тролей которые в глаза не видали мышку с шариком.
оптопара это 2 расположенных максимально близко датчика излучения.
колесо диск похуй как назовите можно сравнить с колесом обычного веласипеда со спицами ПРИ ЭТОМ известно, что расстояние между датчиками в опто паре МЕНЬШЕ чем толщина спицы.
развадить электрически ничего ненадо.
тое
мы имеем 2 бита изменяющихся во времени - скорость обсчета заведомо больше на несколько порядков чем скорость реакции датчиков на внешнее возбуждение.
оп пик слегка изменен красным относительно колеса в масштабе показано соотношение окон датчиков и лепестков диска (спиц ебаного веласипеда)
в прошлом треде до конечной реализации так и не дошли( выдерну наиболее перспективнаи идеи.
>>544283
>>544300
>>544321
ну и как жеж без него)
>>544366
ну на тебе задачку решиш моя помосчь тебе наврятле больше понадобится.
>Я и не говорил, что это хороший код. Я говорил, что этот код работает.
В твоём конкретном случае работает. У кого-то это уже может не завестись. Для этого и существует понятие "неопределённое поведение". Например, если ты в 1.c сделаешь инициализацию
int foo[1] = { 1 };
то линковщик уже ругнётся.
>весь механизм заимствован и поддерживался для линковки с Fortran. И оно будет работать, потому что это де-факто стандарт и еще из-за того, что линкеру на стандарт сишечки похуй, что бы там комитет по этому поводу не думал.
Было бы ещё интересней, если бы ты какие-нибудь ссылки приложил к своему заявлению, где о подобном говорится.
Я несовсем понял задачу, но давай подумаем. Я так понимаю тебе нужно знать куда вращается колесо со спицами?
Суть проста - чередование активации фотодиодов задаёт направление.
Вот тебе функция:
//это должны быть названия твоих диодов и их коды, физически их сопоставь как левый\правый или передний\задний или верхний\нижний, а код может быть любым значением.
#define LEFT 0b00000001
#define RIGHT 0b10000000
unsigned char previous = NULL;
unsigned char kudablya(unsigned char value)
{
if(value & LEFT && previous & RIGHT)
{
previous = value;
return RIGHT;
}
if(value & RIGHT && previous & LEFT)
{
previous = value;
return LEFT;
}
return NULL;
}
Я несовсем понял задачу, но давай подумаем. Я так понимаю тебе нужно знать куда вращается колесо со спицами?
Суть проста - чередование активации фотодиодов задаёт направление.
Вот тебе функция:
//это должны быть названия твоих диодов и их коды, физически их сопоставь как левый\правый или передний\задний или верхний\нижний, а код может быть любым значением.
#define LEFT 0b00000001
#define RIGHT 0b10000000
unsigned char previous = NULL;
unsigned char kudablya(unsigned char value)
{
if(value & LEFT && previous & RIGHT)
{
previous = value;
return RIGHT;
}
if(value & RIGHT && previous & LEFT)
{
previous = value;
return LEFT;
}
return NULL;
}
Она принимает код активного диода и возвращает 1 из трёх значений - левый\правый и NULL, нужный для колибровки направления. Хотя о его нужности можно и поспорить. Тогда функция примет ваще примитивный вид
#define LEFT 0b00000001
#define RIGHT 0b10000000
unsigned char previous = NULL;
unsigned char kudablya(unsigned char value)
{
if(value & LEFT && previous & RIGHT)
{
previous = value;
return RIGHT;
}
previous = value;
return LEFT;
}
Однако для её правильной работы нужно колесо двинуть туда-сюда, чтобы условие начало выполняться.
> какие-нибудь ссылки приложил к своему заявлению
Ну, например: http://www.lurklurk.org/linkers/linkers.html#dups
>аргументы командной строки можно раздобыть где-то вне main
Можно. Хуяришь глобальную переменную и оттуда ковыряешь данные по необходимости.
Я думаю, это и так было очевидно. Можно и как аргументы передавать другим функциям. Но в каждом случае тебе нужно сделать какие-то манипуляции в main() для этого.
Если у тебя нет контроля над main(), в чем проблема написать GetCommandLine и аналоги под каждую следующую платформу, которую необходимо поддерживать?
обычно делают так: описывают структуру с полями где перечислены возможные аргументы, заводят глобальную переменную (зачастую сразу делают безымянную структуру), пишут функцию разбора - в нее прямо передается argc, argv, в этой функции происходит разбор и заполнение глобальной структуры
таким образом, main не засоряется - функция разбора вызывается один раз в самом начале
дальше уже пользуются данными из глобальной структуры, ну либо еще дописывают функции доступа и вызывают уже их, а не напрямую читают из структуры
XCode, homebrew
1) MISRA-C:2004 Language Guidelines
2) http://fprog.ru/2009/issue1/eugene-kirpichov-fighting-mutable-state/
А эти компиляторы не кривые? А то не хочу как на виндоусе со всякими ошибками в стиле "вы взяли scanf, а не scanf_s".
А можно поподробнее? Я в Си меньше недели, про все ништяки еще не знаю. Что за Дарвин?
Вот спс!
>Либо ты пишешь снаружи функции
Ну по идее для базовых кодов, все всегда пишется внутри int main(), не? Я так и не совсем понял почему это так обязательно, тот же "printf("Hello, World!\n");" засовывать в main, почему без него то не работает?
>Поясни поподробнее. Может, тебе показывали код на асме для доступа к автоматической и статической переменной?
Ну наверное, это было на слайде, и там колонка была, типа программа резервирует память в этом месте и.т.д.
> Ну по идее для базовых кодов, все всегда пишется внутри int main()
Код да. А переменные можно делать глобальными (в пределах программы или только одного файла, причем последнее предпочтительнее). Ну, когда ты уверен, что это необходимо.
> засовывать в main, почему без него то не работает?
Так задумано. Код программы описывается функциями, выполнение программы начинается с функции main() и заканчивается после выхода из неё. Код вне функций никому не нужен, но можешь подумать, что было бы, если бы тебе разрешили так писать: ты линкуешь программу из двух файлов, в обоих код вне функций, какой из двух файлов должен выполниться первым? В плюсах есть такая проблема. Там у глобальных объектов конструкторы вызываются до main(). В случайном порядке.
Ананасы, нид совет, я вообще ничего не понял по той ссылке
>Странно что полно дряни типа errno, а argv, которые актуальны на всём протяжении работы, для любого потока в переменную не вынесены.
Я думаю, это связано с тем, что размер argv непредсказуем.
Хотя я сейчас подумал, что если учитывать, что argv, argc будут лежать на стеке main() на протяжении всей работы программы, то фактически не нужно их куда-то копировать в кучу. Тащемто действительно странно, что не продумали глобальный доступ к ним by design. Может, кто из местных анонов пояснит, почему так сделали.
Ну так-то в некоторых компиляторах (не будем показывать пальцем на Microsoft) есть __argc, __argv и даже __wargv.
>argv, argc будут лежать на стеке main
Лежать будут указатели на них.
А вообще командная строка хранится в process environment block (PEB) которые создается системой при старте нового процесса. PEB кладется куда-то в адресное пространство процесса, в отличие от остальных структур процесса, что прячутся в адресное пространство системы. Это для винды, под юниксами делается как-то похоже скорей всего.
Забирать агрументы командной строки можно еще и функцией GetCommandLine.
Но тебе это знать не нужно, тк ты слишком маленький еще.
> Лежать будут указатели на них.
Почему это? Будут лежать именно argc и argv. На x86 на любой ос их даже найти там можно без проблем (если main не модифицировала).
> А вообще командная строка хранится в process environment block
Скорее в _PEB.ProcessParameters, но тебе это знать не нужно, тк ты слишком маленький еще.
Не обращай внимания, у нас тут байтоебский чатик. А ты бы лучше рассказал поподробнее, зачем это тебе понадобилось?
>зачем это тебе понадобилось?
Я не тот анон, которому нужен доступ к argv вне main() из коробки. Я просто участвовал в обсуждении.
Наконецто.
над пилить перекат.
и от макаки требувать отдельного треда микроконтроллеры.
с двымя под ветками да с сиськами как у мамки ыыыыыыыыыыыыыыы
первая электроника второй код а третий дружба как у поней мать их так.
да дети да я пишу код еще под архитектуру ебаных конца восьмидесятых.
мне предлогает атмел я его нахуй шлю с его удобностью и сраными 3-5 мегагерцами.
тупым подсчетом реакции на прерывание мы видим что нас жестоко хотят наебать.
да проще да ненужен програматор да архитектура "ЗАТОЧЕННА ПОД С"
НО я на своем разогнаном ВИЖУ на порядок больше чем ты на сваих сраных 10 мегагерцах.
а если ты код неумееш писать кто тебе в этом виноват?.
мы имеем тоже что и вы да у нас нет встроенной флеши но кто мешает ее подключить?
написать код - размять сваи мазги
поиграть в угодайку погуглить даташиты всю хуйню.
как правило все идет на скрутках или на пайке.
эта смола меня раз пиздец как подъхебла
смантировал ну и думаю пачистю пайку бянзинчиком ОГА - ЭТА ХУЙНЯ РАСТВОРЯЕТСЯ в бянзинчиге.
и термоусадка в гавно превратилась... плак плак.
девайс надо переделывать(
То не я, уже пояснили.
Мне-то просто знать наверняка надо было.
Я фана ради конпелятор теперь уже транслятор осилить пытаюсь, вот и использую в качестве "универсального ассемблера". Собственно и думал, не используя волшебных имён, подобно питону совместить тело програмы с блоком инициализации верхнего модуля и вынеся аргументы и прочее в отдельный модуль. Вобщем-то и так можно проинициализировать их из main, однако лишь для полностью подконтрольного приложения, не библиотеки например.
Библиотеке аргументы должны либо скармливаться явно, либо она вообще не должна о них знать.
Го свой напишем? Ну типа WxWidgets только для сишки и более аккуратный/интуитивно понятный. Сделаем кашерный ученик по нему и плюсофаги соснут хуйца, т.к. весь мир перейдет на сишку, кек.
сорта говна
Ну вроде я находил бесплатные версии в тырнете.
препринты
Есть TR, там всё то же, но бесплатно. Тебе хватит. Если у тебя какие-то проблемы с этим, можешь на K&R/C89 писать - многие так и делают, фанатично искореняя всякие C99измы, какой уж тут C11.
А ты вычти введение про environment (там, в основном для разработчиков ОС и компиляторов), описание стандартной библиотеки (если уже учил Си, там не так много функций добавилось), приложения (проглядеть по диагонали или вообще не читать), и из 700 останется 150 страниц про язык. Хотя учить язык по спеке - это максимум мазохизм, конечно.
Если байтоёбишь просто потому что ты дохуя 1337, то чтоб выебнуться. Если для performance, то а как ещё-то? Конпелятор же не знает, какие у тебя данные, как они поступают и т.д. Да и в общем случае не всегда оптимально оптимизирует.
Как ты без ассемблера напишешь полностью ядро ОС???
Нет у меня конечно получилось 1 раз, но это было только благодаря создателям тулчейна, которые сделали так, что все само сохранялось и восстанавливалось, и предоставили интринсики для работы с указателем стека...
Для общего развития, лол.
1) Сложный дебаг, дебаг чужого блоба, реверсинг.
2) Понимание, в какие примерно инструкции соберется код, помогает понять, как делать не надо (например, почему на этой конкретной системе исключения пиздец медленные, на этой часто можно пренебречь выравниванием, вот в той big-endian, и если ты хочешь совместимости, изволь ебать байтики, а вот та - вообще DSP с 24-битными словами, иди ищи пидараса, который к размеру int привязался).
3) Ну, и если у тебя сколько-нибудь критичный к скорости код, то ты рано или поздно придешь к Intel VTune Amplifier (или аналогу), а там без знания архитектуры никуда.
>нахуя знать тыщщщу архитектур
Я не думаю, что кто-то реально шарит в большом количестве архитектур. Обычно на какой-то одной специализируются, разве нет?
>Какая нахуй разница: ARM, AVR, MIPS, x86?
DA TI OHUEL
мимо-работающий-со-SPARC'ом
> на этой часто можно пренебречь выравниванием
Ты блять внатуре уебок чтоли? А ну пошел на хуй отседова на зассаные кресты, там тебе и место
Ну умеет x86 alignment fault проглатывать, ну пользуются этим часто. Оттого, что ты тут порвался, ничего не изменится ведь.
На stm8 выравнивание не нужно, например...
sqlite почитай для начала.
Нагуглировал такую штуку.
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724958%28v=vs.85%29.aspx
Из той структуры, похоже, мало интересного можно узнать. Только о процессоре и архитектуре.
WinAPI
Ебать ты крут
Тебе нужно WMI + реестр на предмет всяких VirtualBox Additions.
Вобщем смысл в том, что нужно создать сегмент с заранее заданым shmid, а не рандомным, как делает функция shmid().
Далее аттач уже работает, и все хорошо.
Или подскажите, как такие сегменты создавать, чтобы id=0, 1, итд было, а не рандомное uint32_t число?
~ # ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 admin 666 557056 7
0x000006fd 32769 admin 666 12692 1
Вот тут пример, как работать с шаред мемори.
https://www.cs.cf.ac.uk/Dave/C/node27.html
Базарю, ID знать не надо, надо знать key.
Ну, проблема немного шире: я пишу интерфейс к махровой проприетарщине, которая работает через shm, так вот в качестве shmid там может быть число от 1 до 16, и оно жестко зашито во всех программах в этом комплексе.
И вот каким-то образом оригинальный интерфейс управления создает сегмент shmid с id равным 0-16, в то время, как функция shmid из uclibc (а эти программы тоже на uclibc писаны) возвращает совсем не те значения.
>>553788
Key мне никак не поможет. Видишь листинг ipcs? Там key=0, а если я сделаю shmid с таким key, то он вернет совсем не 0, а функцию от этого key с результатом ближе к концу uint32_t.
Вообще, полное задание имеет вид "скопировать shmid 0 в shmid 1", при этом shmid=1 не существует, т.е. его надо как-то создать.
Да, пробовал IDA на этих утилитах, но постиг неудачу: архитектура MIPS, а для нее нет hex-rays decompiler, и вообще многих штук, которые бы повысили читаемость кода до того уровня, чтобы я осилил листинг.
Ка грустно быть тобой!
Начнем с того, что стандарт posix определяет только api, соответственно нет переносимого надежного способа заставить shmget сгенерировать тебе сегмент памяти с id из определенного диапазона.
То есть в этой твоей пипиетарщине используют грязный хак с системными вызовами в обход uclibc.
И самое хуевое, что после обновления Ядра может перестать работать сама пипиетарщина.
Непереносимый код мне и не нужен, учитывая то, что эта проприетарщина также никуда перенесена быть не может.
Вот только я не понял, как там этот shmget дергает системные вызовы?
в системный вызов ведь также передается и key, т.е. получается там ядро хакнуто?
вот код uclibc:
int shmget (key_t key, size_t size, int shmflg)
{
return __syscall_ipc(IPCOP_shmget, key, size, shmflg, NULL, 0);
}
#define __NR___syscall_ipc __NR_ipc
#include "ipc.h"
_syscall6(int, __syscall_ipc, unsigned int, call, long, first, long, second, long,
\t\t third, void , ptr, void , fifth)
А безопасный - это как? Границы проверять при доступе? Ну так сделай Array_Get, Array_Put и проверяй.
Да, границы от перезаполнения
Не могу, я их выдумал. Если тебе нужно проверять границы - проверяй их при каждом доступе. Чтобы не забыть о проверке случайно, оберни доступ к массиву в функцию.
А как это реализовать? Ассертом?
Не обязательно, может там просто задана определенная конфигурация при которой может быть всего 16 сегментов, х.з короче.
Обрати внимание на два крайних аргумента, что будет, если они будут не нулевыми?
они похоже, зарезервированы для совместимости, дальше вызов имеет вид:
case SHMGET:
return sys_shmget(first, second, third);
Проблема только одна: не могу найти код самого sys_shmget, может я настолько туп? Ищу в исходниках ядра, и не нахожу конкретики.
Не, их можно создавать через shmget с номерами явно большими, я проверял.
запили функцию, которой будешь контролировать все свои опасности и работай с массивом только через неё.
Ты забыл про Windows API.
http://lxr.free-electrons.com/ident?i=sys_shmget
Надо в гугле искать, а не самому исходники рыть, она платформеннозависима, соответственно ты и не можешь её найти п кроссиплатформенном коде.
Спасибо, анон!
По твоей наводке удалось проследить, как оно создается:
отсюда http://lxr.free-electrons.com/source/ipc/shm.c?v=2.4.37#L231
идем сюда http://lxr.free-electrons.com/source/ipc/shm.c#L484
и начинаем греть голову, как бы это все вызвать в реальном коде. Пока идей нет.
У линуса на гитхабе это все тоже есть.
И да smid <= 16 это колдунство то еще,
такое впечатление, что эти куски памяти создаются в самом начале работы ядра.
А то, что программа как-то использует именно их - это все быдлокодерство и грязные хаки...
Да, там 2.6.30, я естественно с оглядкой на это ядро делаю.
>>554401
Да, сейчас попробовал: если не создано вообще ни одного shm-сегмента, то shmid первым создает сегмент 0, а вот уже второй сегмент создается с большим ID.
Теперь пытаюсь выяснить: то ли сегменты <16 все-таки можно создать, то ли создатели этого дела ебанутые, и остальные 15 никогда там не работали и не проверялись.
Короче, аноны, докопался:
http://lxr.free-electrons.com/source/ipc/util.h#L158
Получается, создать их все-таки можно, но не в текущем ядре, на котором крутится система.
т.к. по дефолту SEQ_MULTIPLIER = 32768, и соответственно, создаются сегменты с 32768*номер сегмента + id сегмента.
Итого, единственные вариант, где номера сегментов будут нужные: SEQ_MULTIPLIER = [0-15].
Теперь ищу в ядре, где это значение записано, и поменяю бинарно (а ядро тоже блобом, патчей, который накатил создатель этого дерьма - также нет).
>SEQ_MULTIPLIER
http://lxr.free-electrons.com/source/include/linux/ipc.h#L8
Вот оно, держи.
школьник кун
Я бы не стал так менять, ибо можно жестко наколоться!
Кто знает, что там еще поменяно???
школьник-кун
158 static inline int ipc_buildid(int id, int seq)
159 {
160 return SEQ_MULTIPLIER * seq + id;
161 }
265 new->id = ipc_buildid(id, new->seq);
266 return id;
Мне кажется, или тут fail???
seq - это номер версии,
Если ты меняешь SEQ_MULTIPLIER, то у тебя пропадает история версий этого твоего сегмента, то есть ты не сможешь отличить текущий сегмент, от того, который когда-то давно освободили.
Походу, твои быдлокодеры считают, что сегменты создаются в самом начале работы...
Вообще, возвращает оно то, что надо, так что скорее всего id = key, new->id = shmid или что-то подобное.
Ядро патчить не надо, попробуй передать вместо настоящего shmid вот такое значение:
shmid%SEQ_MULTIPLIER,
вдруг сработает???
Могу только сказать, что оно никогда не освобождается при работе, там даже перезапуск сервисов не предусмотрен.
Возможно этот юзерспейс писался для какого-нибдуь старого ядра, или для ядра с таким патчем:
http://www.programdoc.com/1272_129170_1.htm
Но я проверил, патч в ядро не брали, и в том ядрес, на котором все это работает, такого нет.
Нельзя тупые вопросы задавать, да?
> должно сработать, ибо похоже, для сегментов история не проверяется в ядре...
Не сработало: если таким образом модифицировать key, то id выдается тот же самый, ничего не меняется.
Если модифицировать id, то shmat (dst): Identifier removed
Т.е. зааттачиться к сегменту не выходит.
Значит ШМАТ проверяет версию сегмента, жаль.
>shmat (dst): Identifier removed
Ну тогда придется патчить ядро,
проследи все зависимости от SEQ_MULTIPLIER, и поправь их так, чтобы не было зависимости от версии.
А сами функции линкер берет из библиотек (.a, .lib) - там хранится набор уже скомпилированных в объектные файлы функций (статическая библиотека) или указания, в какую .so/.dll обратиться за этими функциями при запуске (динамическая библиотека). Одна из библиотек называется CRT (C runtime library) и цепляется автоматически, поэтому от тебя никаких телодвижений не требуется.
Спасибо, анон! А откуда линкер знает, к какой библиотеке это относится? Я просто пытаюсь разобраться в механизмах всего этого.
Вот я включаю заголовок либы в свой файл, по скобкам или кавычкам определяется локальный заголовок или нет. Потом что происходит? В заголовке не прописано ничего, только определение функций в данном случае.
Дальше у линковщика есть список дефолтных путей, в которых он ищет функции в библиотеках,которые там лежат, если нашел - добавил функцию в экзешник, если не нашел - будет ошибка.
> Вот я включаю заголовок либы в свой файл, по скобкам или кавычкам определяется локальный заголовок или нет.
Никакой разницы, системный это заголовок или твой. И даже заголовок ли это вообще (ты с тем же успехом можешь декларировать функции сам). Когда ты декларируешь, но не определяешь функцию или глобальную переменную, компилятор помещает в объектный файл имя (символ), помеченное как extern. Типы либо кодируются прямо в это имя (в С++, гугли name mangling), либо теряются (в С в лучшем случае в символ попадает общий размер аргументов функции).
На этом работа компилятора заканчивается, и в дело вступает линкер. У него перечислены объектные файлы (то, во что скомпилировалась программа), а затем библиотеки (дефолтная, плюс указанные тобой).
Линкер пытается для кажого extern (не определённого, внешнего) символа найти объектный файл, где определён символ с таким же именем (public символ). Т.е., он связывает, допустим, обращение к fopen из твоего объектного файла с тем объектным файлом, где лежит fopen. Поэтому он и называется линкер ("редактор связей" в старой русскоязычной литературе).
Если символ не был найден в объектных файлах, линкер идёт по списку библиотек (в том порядке, в котором они указаны). Когда он находит символ в одной из библиотек, он "достаёт" из библиотеки соответствующий объектный файл и добавляет его к списку объектных файлов, участвующих в сборке. Этот процесс повторяется, пока линкер не разрешит все extern-символы, или пока не закончатся библиотеки в списке. В первом случае линкер пойдёт компоновать исполняемый файл, а во втором он скажет "undefined reference to _some_name".
Блин, даже не знаю, как тебе благодарность выразить, настолько четко и ясно объяснил. Ебану вискаря за твое здоровье. Спасибо огроменное! Двач-помогач!
почему я получаю Segmentation fault(core dumped)?
http://pastebin.com/znRAfFhZ
Ты объявил указатель s в main, но: ты не инициализировал этот указатель, и в результате getchars пишет введённый текст в случайное место памяти (чаще всего в стеке). Поэтому программа падает.
Чтобы прочитать строку, тебе нужно выделить под неё буфер. Например, так: char s[MAXLINE]; или ты можешь использовать malloc().
спасибо!
Ты вконец охуел. Хотя бы вопрос сюда скопировал!
> Как узнать, сколько вордов занимает функция
Никак это не проделать в общем случае. Ты можешь пропарсить объектники или отладочную информацию, отсортировать и посчитать размеры но по ссылке совершенно справедливо пояснили за инлайн. Или можешь собирать без оптимизаций или с оптимизациями, но контролируя каждый билд дизассемблером и надеяться на то, что компилятор не меняет порядок функций. Но проще всего вынести всё необходимое тебе в .dll и посчитать хэш сразу всей кодовой секции.
Алсо, добавлю, что Visual Studio уже достаточно давно увлекается неполным склеиванием функций, превращая код в страшную лапшу, когда адрес конца функции меньше адреса её начала. Так что нужно очень внимательно смотреть за оптимизациями и прочим LTCG.
Книгу покажи. Алсо, по стандарту Си ты вообще не можешь никак читать код функций (нельзя конвертировать указатель на функцию в указатель на данные любого типа, даже в указатель на void и то нельзя).
А. Ну смотри, раз ты в это лезешь, ты должен быть готов мириться со всем этим говном.
В книге гцц, в гцц можно брать адреса меток lecture1.pdf, страница 31, например - разница между двумя адресами даст тебе приблизительный размер функции. Иногда, лол. Когда-нибудь ты будешь делать "правильно", а пока просто собирай с -O0
Есть задача. Программу написанную на Си нужно переписать на ассемблер. Есть .ехе и .с файлы. Программа небольшая. Анон, помоги.
можете привести пример рекурсивного вызова? (надо найти все позиции, которые создержат искомые бинарные данные)
просто когда я засовываю memmem в while() оно ловит segmentation fault, а если хоть 100 раз подряд написать без while - работает нормально.
А почему не хочешь, чтобы компилятор тебе ее на ассемблер переписал?
у GCC есть:
gcc -S hello.c
у других скорее всего аналогично.
> просто когда я засовываю memmem в while() оно ловит segmentation fault,
Покажи, как засовываешь.
Пиздец, нахуй тогда нужна такая защита, которая работает только иногда? Там еще дальше показывается, как шифруется секция кода от метки до метки, и выходит, что точно так же метки дадут только приблизительные границы шифруемого кода? Ебаное говно, нахуй это нужно вообще?
Если ты будешь делать в реальности что-то защищать, ты можешь, например, взять свой объектный файл с защищаемым кодом и посмотреть/посчитать в дизассемблере точную длину функции. Или пропарсить объектный файл, отсортировать символы и считать функцией все байты до следующего символа.
Если же ты шифруешь секцию целиком, ты можешь просто распарсить заголовки исполняемого файла, там будут точные размеры и офсеты секций - их загрузчик использует.
Ещё протекторы делают макросы для программиста с _emit (http://stackoverflow.com/questions/731428/what-is-the-equivalent-of-emit-on-linux) последовательностей магических байтов в нужных местах функции, протектор их ищет в бинарнике и заменяет эти последовательности и код между ними на шифрованный эквивалент. Например, https://www.google.com/search?q=макросы%20themida
Насколько сложно самому написать парсер объектных файлов и как это можно сделать? Ничего не нагуглил об этом.
Анончик, почему сишка - неортогональное говно?
Потому что переменные любого типа приводятся к int.
Есть ли сайт где можно сортировать списки кодов по просмотрам, фаворитам, дате?
Мне было бы интересно полюбоваться различными интересными кодами (с комментариями естественно), ну например код в котором все слова переводятся в верхний регистр (uppercase).
И кстати, может кто-нить подсказать, где все программеры тусуются? Ну на каком сайте/irc канале? русскоязычный/англоязычный
а то я только про канал #C на freenodes знаю
>А где можно посмотреть на различные коды написанные на C?
Скачай бубунту, там их дохуищща.
>Есть ли сайт где можно сортировать списки кодов по просмотрам, фаворитам, дате?
нет.
>И кстати, может кто-нить подсказать, где все программеры тусуются?
Да ты ебанулся, программеры не тусуются, это противоречит их естеству.
Что то мне кажется ты немножечко пиздишь. Хоть я и не пытался прочесть из оперативной памяти код программы, но точно знаю, что имея указатель, любые данные на которые он указывает, можно обрабатывать как данные того типа, в котором ты хочешь их видеть. В конце концов, стандарт Си распространяется скорее всего только на компилятор, что не мешает присвоить адрес функции указателю на данные так же легко, как присвоить значение переменной. Совсем другое дело, если ограничения ОС по работе с оперативной памятью будут мешать прочесть данные по указателю, но даже чисто теоретически - функция в одном процессе с программой, а значит должна быть в одном адресном пространстве и может быть как минимум прочтена, а как максимум скопирована куда нибудь и исполнена.
Я не знаю, как устроены ограничения по работе с оперативкой, однако если их нет по отношению к изучаемой функции, то есть уйма способов вытянуть адреса начала и конца функции и самый простой - найти сигнатуру соответствующую команде jmp на адрес команды исполняемой после вызывающей функции.
> Что то мне кажется ты немножечко пиздишь
Я говорил ПО СТАНДАРТУ (преобразование указателей на данные в указатели на функции упоминается в Common Extensions, но это не портабельно).
На x86 ты можешь читать код. Но не ограничивайся x86, ознакомься, например, с https://ru.wikipedia.org/wiki/Гарвардская_архитектура
>>556742
>найти сигнатуру соответствующую команде jmp
Существует как минимум три способа вернуть управление на x86 и ещё десяток других на других архитектурах. При этом они все могут применяться в одной и той же функции, т.к., return может быть несколько, да и компилятор может парочку своих воткнуть.
>При этом они все могут применяться в одной и той же функции, т.к., return может быть несколько, да и компилятор может парочку своих воткнуть.
ааа, внатуре
в потрохах бекэндов яп очевидно же
Ты опять выходишь на связь?
> мб кто подскажет почему
> заполняются одними и теми же элементам
Из куска кода непонятно, чего ты хочешь добиться, и что вообще здесь происходит.
1) В case 10 дублируется условие.
2) mass2[i - 5] будет писать вне массива при flag != 0 && i < 5. flag точно инициализируется 0?
3) В default не хватает break (не критично, пока ты еще case не добавишь в конец).
4) Если Inter() будет выдавать последовательность 1 1 1 1 1 10 2 2 2 2 2 12, ты заполнишь массивы разными элементами. Хуй знает, что тебе не нравится.
5) Перепиши это говно.
Допустим, юзер ввел 8, а программа должна найти следующее простое число (prime number) = 11.
https://ideone.com/uKcWmo
Кстати, как мне "дебугнуть" мой код? А то он чето не пашет сейчас. У меня есть встроенный lldb, который работает как gdb debugger.
Я ввел в него скомпилированный код test.out
а дальше попытался дебугнуть этот код, не получилось.
Ты документацию к lldb читал? Так иди читай.
http://lldb.llvm.org/tutorial.html
http://lldb.llvm.org/lldb-gdb.html
Файл ил консоли lldb грузится командой "file test.out".
У тебя в программе нет ни генератора простых чисел, ни проверки делимости (кроме 2 и 3).
Хочу очень во всем этом разобраться.
Мои контакты: golffstream@yandex.ru
Error: undefined reference to `sinf' (5555)
Какого хуя, а?
А, и компилятор GCC.
Покажи финальную командную строку линкера.
Помогите мне, пожалуйста, разобраться с самым простым.
Нужно разобраться, как работают циклы (особенно те, што считают суммы квадратов чисел, считают всякую тригонометрию) и массивы; и как, сопсно, обозначать и правильно использовать переменные, как подбирать нужные к ним действия.
Лучше по скайпику линк: "gnwoerk", штобы тут не засорять.
Надеюсь на доброту анона.
Приветствую вас. Ни у кого случайно не завалялась реализация фибонначиевых куч на си? Был бы ультра благодарен за подгон. lonelypath[at]yandex.ru если что. Всем счастья.
А што, собствинна, не так? Мммм?
До тысячных?
floor(2.982001*1000) / 1000, но имей в виду, что не все числа могут быть точно представлены в виде float или double.
Если тебе жизненно необходимо точное представление, изобрети свой fixed-point и храни тысячные в целочисленной переменной (т.е., например, не метры с плавающей точкой, а миллиметры без нее).
Ты можешь объяснить почему это так работает?
Я знаю что такое флор, но вот именно как ты сделал до тысячных, а если мне надо до 10000сячных?
floor округляет вниз (1.23 -> 1, 1.9 -> 1). Есть еще round, который округляет как в школе (1.23 -> 1, 1.9 -> 2) и ceil который округляет вверх (1.23 -> 2, 1.9 -> 2).
Тебе нужно оставить тысячные доли, а остальное отбросить. Ты умножаешь число на тысячу, "перемещая" эти нужные тебе разряды из дробной в целочисленную часть (2.982001*1000 -> 2982.001) и отбрасываешь оставшуюся дробную часть (floor(2982.001) -> 2982.0). После этого ты возвращаешь разряды обратно в дробную часть, разделив результат на 1000 (2982.0 / 1000 = 2.982).
> если мне надо до 10000сячных
Значит на 10000 и умножаешь/делишь. Это арифметика школьная, куда точку поставить.
Спасибо большое, так и думал
Объясните нубу как пользоваться pipe. Вот есть у меня легендарный процесс A и его дочерний популярный процесс B, я ввожу некие данные в A, но мне нужно передать их в B, обработать их там и вернуть результат в A, как это провернуть?
Методов на самом деле дохуя,
выбор зависит от задачи...
У тебя процессы, или так, потоки?
Если процессы, то они крутятся на одной машине, или могут быть на разных?
>>572109
>зрозумить
Одни хохлы, блядь. И под кроватью хохлы. Вы всегда были или набижали после скачек? Не замечал вас до 2013 года в русскоязычном сегменте интернета. Даже вконтакте вас особо заметно не было.
Скоро сам забалакаешь на ихней мове.
Ну я просто учусь пока, процессов 2 (про дочерний я напутал чутка): запускаю процесс (программу), ввожу туда пачку значений (пускай будет 2, не суть важно наверное), запускается второй процесс через execl, который по pipe должен получить эти значения, обсчитать и вывести результат. Находятся они на одной машине, до сетей пока еще не дошел.
>>572391
Мань, заспокойся, руssкий я, руssкий.
>#include <iostream>
>#include <sstream>
>#include <algorithm>
>#include <iterator>
>
>int main()
>{
> std::string str;
> std::getline(std::cin, str);
> std::istringstream ist(str);
> std::copy(std::istream_iterator<std::string>(ist),
> std::istream_iterator<std::string>(),
> std::ostream_iterator<std::string>(std::cout, " ") );
>}
Как этот кусок(удаляет лишние пробелы между словами) переписать на Си, посоны? Желательно объяснение для моего уровня дцп-кодера.
char input[100] = {"surprise mother fucker"};
char result[100];
// fgets(input, 100, stdin);
for (int i, j = 0; i < strlen(input); i++, j++) {
\tif (input == ' ') {
\t\twhile (input[++i] == ' ') {}
\t\tresult[j++] = ' ';
\t}
\tresult[j] = input;
}
printf("%s\n", result);
А если по одному символу вводить, то нет этой строки.
#include <stdlib.h>
int main()
{
int n=0, i=0, j, k=0, x=0;
FILE input, output;
if ((input = fopen("input.txt", "r")) == NULL)
printf("no file\n");
else
fscanf (input, "%d", &n);
output = fopen("output.txt", "wt");
while (k<=n)
{
k=0;
i++;
x=x+i;
for (j=1; j<n; j++)
{
if((x%j) == 0)
k++;
}
}
fprintf(output,"%d",x);
fclose(input);
fclose(output);
return 0;
}
помогите, какого хуя программа не завершается. просто запускается и нихуя не происходит. из дебага нихуя не понятно
#include <stdlib.h>
int main()
{
int n=0, i=0, j, k=0, x=0;
FILE input, output;
if ((input = fopen("input.txt", "r")) == NULL)
printf("no file\n");
else
fscanf (input, "%d", &n);
output = fopen("output.txt", "wt");
while (k<=n)
{
k=0;
i++;
x=x+i;
for (j=1; j<n; j++)
{
if((x%j) == 0)
k++;
}
}
fprintf(output,"%d",x);
fclose(input);
fclose(output);
return 0;
}
помогите, какого хуя программа не завершается. просто запускается и нихуя не происходит. из дебага нихуя не понятно
Сам разобрался.
Вы видите копию треда, сохраненную 26 ноября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.