LINUX.ORG.RU

Написание свободной(Free as in Freedom) книги-самоучителя по программированию: планы, цели, задачи

 , , ,


17

9

Итак, я решил написать(или как вариант, собрать из кусочков) книгу-самоучилель по программированию, в которой бы не было глупых и нелепых ограничений на распространение. Однако копилефт я все же считаю приемлемым в данном случае. Общественным достоянием это не будет т.к. вполне могут найтись желающие использовать результат в своих проприетарных книгах, а проприетарные книги — плохо. Лицензия самого текста книги-учебника будет или Creative Commons Attribution-ShareAlike (что позволит без каких-либо проблем переиспользовать текст из википедии) или что-то вроде GNU Free Documentation License (без неизменяемых разделов естественно).

Лицензии всяких примитивных программок, написанных мной лично, будут вообще выложены под общественным достоянием, WTFPL или аналогичной лицензией т.к. являются тривиальными. Примерно вот так. Если я буду использовать чужие исходные тексты, они будут как включения, лицензируемые отдельно от всего остального. Проблем тут быть не должно.

Теперь к теме того, на кого книга ориентирована, какие начальные знания предполагаются, чему книга будет учить, какой первый ЯП взять и каков будет авторский самысел: С этим моментом я пока что не определился окончательно, и тут есть что обсудить. В частности, я не вижу особого смысла объяснять какие-то базовые понятия комбинаторики, об этом можно доступным языком прочитать из школьных учебников. Системы счисления(СС), перевод из одной СС в другую - вот это еще можно. One's и two's complement представления знаковых чисел — про это тоже можно написать. Если же человек не понимает комбинаторику, он ее быстро поймет на примере кода, который будет достаточно наглядно это показывать, и который всенепременно будет.
Пока что в качестве первого языка я склоняюсь к Си, и тому есть причины. Все прочие распространенные языки (кроме ассемблера, хотя его трудно назвать распространенным) не настолько близки к аппаратному уровню. Про нужность понимания на низком уровне написано тут http://russian.joelonsoftware.com/Articles/BacktoBasics.html https://habrahabr.ru/company/piter/blog/271347/ , не вижу смысла повторяться. Приведу лишь цитату:

«Просто плохой воркшоп попался», — скажете вы. Но на этом примере я хочу подчеркнуть более масштабную проблему: не изучив для начала C, программист оказывается лишен необходимых орудий, позволяющих понять, что именно происходит в используемой системе. Если вы — умный и пытливый питонщик, то вскоре докопаетесь до плотных пород языка C. Под этими горизонтами, скажут вам, «бойся драконов, костей и отладчиков». Соответственно, если вы не будете достаточно отважны и не проигнорируете предупреждений «да не берись ты за этот C», вы никогда не исследуете глубин, на которые можно забраться просто из любопытства.

Притом еще один важный момент: Си будет изучаться параллельно с ассемблером. Если речь идет об изучении ассемблера, необходимо четко зафиксировать то, на какой архитектуре это все происходит и в какой ОС. Так вот, ОС будет GNU/Linux а архитектура x86-64. Будут постоянно проводиться параллели между тем, что из себя представляет код на Си в текстовом виде, и тем, в какой текст на ассемблере его превращает компилятор. В связи с этим, первым делом будет рассказано о goto и конструкции if(условие) goto метка;. Про конструкции вида

if(условие)
{
  что-то_делаем;
}
else
{
  что-то_другое_делаем;
}
Будет рассказано немного позже, притом это будет рассказано и словами, и через написание эквивалентного кода через if(условие) goto метка;. Циклы, for(){} while{}, do{}while(), конструкция switch-case и break continue внутри них будут так же объясняться через все тот же if(условие) goto метка; притом будет делаться явный акцент на том, что намного лучше использовать нормальные циклы, чем лепить всюду этот условный goto. Кроме того, будет так же рассказано про Labels as Values. Почему так важна эта странная штука, if(условие) goto метка;? Потому что она имеет наипрямейшее отношение к тому, как работают ЭВМ, а всякие циклы СКРЫВАЮТ это. Рекурсия в Си будет объясняться только после того, как будет объяснено, что такое стекфрейм и соглашения вызова, будет сказано про оптимизацию хвостовой рекурсии, и о проблеме забивания стека, если такая оптимизация не происходит, притом это будет наглядно показано в ассемблере. Учиться отлаживать код надо будет тоже «с пеленок», притом отлаживать и ассемблер, и всякие там Си. Будет и про асм-вставки в Си, clobber list. В качестве ассемблера будет рассматриваться GAS, а никакой не NASM т.к. GCC умеет выплевывать ассемблер именно в GAS синтаксисе. Насчет выбора Intel или AT&T синтаксиса - тут я склонюсь пожалуй к тому, что надо ЗНАТЬ И УМЕТЬ ПОНИМАТЬ ОБА. Кроме того, GAS давно уже умеет в оба синтаксиса, так что проблем с этим не будет. Единственная проблема с GAS в том, что это однопроходной ассемблер, так что можно освоить и какой-нибудь NASM, YASM.

Первые хеллоуворды будут написаны вообще в особом стиле, без использования printf() и вообще без библиотеки Си; Будут использованы куски на ассемблере, которые делают системный вызов write и read, и с ними можно(нужно) будет линковаться, чтоб что-то вывести на экран. Будет рассказано и про printf естественно, но только когда будет совершенно четко ясно, что такое вообще va_list. Будет куча отсылок к драфту стандарта Си (недрафт почему-то платный). Будет так же рассказано про устройство ОС. В конце скорее всего будет дано задание сделать свою игрушечную ОС так что предполагается что человек к тому моменту должен уже отлично понимать всякие там связные списки, графы, очереди, спинлоки-аллокаторы свои уметь делать на асме при желании. Алгоритмы сортировки, обхода графов, хеш-таблицы, все это будет объяснено на языке Си, и плюсов вообще касаться я не буду.

Насчет графики: работу с протоколом иксов тоже можно будет рассказать, обработку нажатий клавиши. Правда там надо дофига писать про кучу всего, например что есть сокеты, есть AF_LOCAL... Тогда это можно еще и сетевому программированию учить на каких-нибудь беркли-сокетах.

Кроме того, после моей книги предполагается, что человек должен уметь заниматься такими ненужными (в GNU/Linux) на первый взгляд вещами, как крякинг, реверсинг, исправление ошибок в бинарниках, не обладая исходным текстом. Восстановление логики работы программы по дизасму. Ну и программирование в машинных кодах (без ассемблера, одним HEX редактором).

Как-то уж слишком дофига, не находите? Может быть не надо так глубоко во все это нырять? Жду предложений и критики по поводу того, что нужно, а чего не нужно писать. Возможно что я слишком много хочу.

cast ASM be_nt_all mister_VA

UPD: Программирование и отладка на C/ASM - Первые программы. Знакомство с C и ассемблером. Компиляция, линковка, код возврата. Вывод текста.

★★★★★

Последнее исправление: CYB3R (всего исправлений: 6)

Ответ на: комментарий от registrant27492

Ну во-первых синтаксис си слишком сложен

Что? После подобных утверждений я снова внёс вас в ignore list, так что можете на предыдущее сообщение не отвечать, вряд ли увижу

be_nt_all ★★
()
Ответ на: комментарий от registrant27492

Ну во-первых синтаксис си слишком сложен и 99% адептов его не понимают.

Читается в мануале.

Внутри самой сишки - это работа с памятью и пониманием самой памяти.

Курс по архитектуре компьютера. Сишка не нужна.

Как и понимание кода - что и как работает в общих чертах.

Курс по алгоритмам. Сишка не нужна.

Про сараи это уже к психиатрам.

anonymous
()
Ответ на: комментарий от be_nt_all

Да ничем принципиально Си от Паскаля по выразительной силе не отличаются.

Эта та деградация о которой я и говорил, когда людям кажется, что «не отличаются» - не потому, что реально не отличаются, а потому, что их представление закончилось уровнем паскаля.

Си не заканчивается тем, что было описано к&р, либо тем, что под ним понимаю иные, мало осилившие адепты. Си - это возможности. Кодовой базы, конпеляторов, синтаксиса, диалектов, понимая и прочее.

Или вы развитие в стиле hacker's delight имеете в виду?

Дак это и есть развитие. Развитие для сишника и есть понимание и его эксплуатация, в противном случае - нахрена сишник нужен? Для простого ваяния вне темы - есть иные языки, которые для этого подходят больше.

Это иллюстрация того, как можно эксплуатируя понимание получать профит, а возможности си позволяет его выразить и использовать. Именно этим он и отличается от паскаля - это просто иной мир. И даже если попытаться все эти возможности добавить в паскаль, как это частично пытались многие делать - это ничего не даст. Ибо будет хуже, а даже если будет так же(что не может быть, иначе это будет не паскаль) - никому не нужно, ибо уже есть.

registrant27492
()
Ответ на: комментарий от anonymous

Читается в мануале.

Не читается. Ещё раз - все твои утверждения разбиваются о реальный мир. 99% новых языков было придумано по той причине, что «синтаксис си слишком сложен».

Если читается - почему не ты, ни кто-либо иной его не знают?

Курс по архитектуре компьютера. Сишка не нужна.

Это не курс, а дерьмо. К архитектуре этот курс не имеет никакого отношения. Сам по себе курс, даже если предположить, что он будет иметь отношение - невозможен без практики. Ибо курс архитектуры даётся для того, чтобы этой архитектурой пользоваться, а использовать позволяет только сишка.

Курс по алгоритмам. Сишка не нужна.

Алгоритмы не имеют никакого отношения к реальному миру - это мусор, фикция реальных знаний и понимания.

Каждый адепт случает курс по алгоритмов, включая тебя, но что смог ты, либо иной адепт в реальности? Ничего. Лутать еду ваяя дерьмо, используя готовое.

Про сараи это уже к психиатрам.

Да не - я не понимаю зачем ты пытаешься спорить утверждениями, которые тебе влили в пустую башку за партой. До тебя уже давно должно было дойти, что я сильнее, а значит все твои потуги я разобью в любом случае.

Поэтому что-то писать мне надо обдуманно и качественно, ибо в противном это не имеет смысла.

registrant27492
()
Ответ на: комментарий от be_nt_all

Когда сказать нечего - обделайся и заигнорь. Ведь игнор - единственное, что есть у балаболов. Тем более толку мне с твоего игнора, если ты ничего из себя не представляешь? Игноришь меня ты итак.

В целом констатировать можно только одно - прочитал - жопа загорелось, а ответить-то нечего. А раз ответить нечего и надо как-то раздражитель убрать - надо заигнорить. При этом героически об этом сообщив.

registrant27492
()
Ответ на: комментарий от registrant27492

Не читается. Ещё раз - все твои утверждения разбиваются о реальный мир.

Сам забиваешь еще один гвоздь в гроб сишки.

Сам по себе курс, даже если предположить, что он будет иметь отношение - невозможен без практики.

Лол, там есть практика.

Ибо курс архитектуры даётся для того, чтобы этой архитектурой пользоваться, а использовать позволяет только сишка.

Ой-ло-ло, царь то деревенский! Про ассемблер не знает!

Алгоритмы не имеют никакого отношения к реальному миру - это мусор, фикция реальных знаний и понимания.

Туда же, есть практика.

anonymous
()
Ответ на: комментарий от be_nt_all
MODULE TestHello;
	IMPORT Log, Math;


	PROCEDURE Start*;
		VAR
	BEGIN
		Log.String('Привет, мир!');
		Log.Ln
	END Start;

BEGIN
END TestHello.

Ты сишник? Это только «Здравствуй мир!»! Сиди и кури!

anonymous
()
Ответ на: комментарий от anonymous

архитектура современных компов - самая непостоянная информация в современном мире. если раньше издавались монументальные справочники по архитектурам, то сейчас всё меняется настолько быстро, что не то, что для нубов, а даже для профессионалов едва успевает выходить минимальная документация на железо в даташитах. причём меняется как само железо, так и протоколы работы с ним. в целом, нубу тут точно ловить нечего, а книга по архитектуре морально устареет ещё до того, как будет написана до конца.
алгоритмы - да. паттерны - да. но от описания железа (равно как и от специфики осей) нужно абстрагироваться. можно отдельный вводный курс системного программирования замутить, но это точно не для начинающих и востребованность его будет мала (процент системщиков среди общего количества программистов крайне мал).

Iron_Bug ★★★★★
()

я не читала весь тред, но выбор GAS удивляет. у него крайне неприятный синтаксис, он облеплен процентами чуть более, чем полностью. NASM ему сто очков вперёд даст по читабельности. а насчёт встраиваемого ассемблера: -masm=intel и никаких проблем.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

Для нубов все это говно и не нужно. Есть MMIX.

anonymous
()
Ответ на: комментарий от anonymous

Ты сишник? Это только «Здравствуй мир!»! Сиди и кури!

Я не сишник (далеко не только сишник). Код абсолютно понятный. Разве что прикол со звёздочкой может потребовать какого-то объяснения, но я то знаю, что ей в Обероне отмечают экспортируемые имена.

be_nt_all ★★
()
Ответ на: комментарий от be_nt_all

я не читала весь тред, но выбор GAS удивляет.

Детка это традиция. В Линукс асма по умолчанию это gas.

у него крайне неприятный синтаксис

Дело привычки. Гасовцу синтаксис Интела тоже может показаться убогим.

anonymous
()
Ответ на: комментарий от anonymous

А что означает строка Math;

Импорт математических функций? Нигде не используется, скорее всего просто остался при копипасте.

deadskif
()
Ответ на: комментарий от Iron_Bug

я не читала весь тред, но выбор GAS удивляет. у него крайне неприятный синтаксис, он облеплен процентами чуть более, чем полностью.

ну так тот самый .intel_syntax noprefix решает эту проблему. А вообще, приятный/неприятный это вкусовщина. Я например не испытываю проблем с чтением at&t синтаксиса, не считая разве что случаев всяких lea и косвенной адресации (которая в intel синтаксисе записывается через [])

Выбор в пользу gas сделан был во-первых по причине того, что те компиляторы, с которыми придется иметь дело(clang, gcc) выдают код под gas, во-вторых сам по себе gas поддерживает множество архитектур, не только x86 и производные, и например gas для ARM поддерживает многие директивы, которые он поддерживает и для x86 (там конечно есть некие специфичные для конкретных архитектур директивы https://sourceware.org/binutils/docs/as/ARM-Directives.html, но их не так много) - таким образом, если человек захочет писать под ARM на ассемблере, ему не придется с нуля выучивать какой-то другой ассемблер(например ассемблер из Keil http://www.keil.com/support/man/docs/armasm/, специфичные для него директивы)

SZT ★★★★★
() автор топика
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от registrant27492

Хоть Вы, уважаемый, тут всех бесите, я пожалуй снизойду и специально ещё раз объясню для Вас, так, как понял бы каждый дебил.

Как и syscall - это обёртка для syscall вызова. Толку с этого? Это не имеет смысла.

В нашем случае syscall, это наитупейшая обёртка, объяснить которую на основе дизассемблированного кода элементарно. Write выглядит мягко сказать посложнее.

static inline

Не имеет смысла в твоём случае.

Раздувать кол-во инструкций, не имеет смысла. Как и Ваш комментарий про «смешно».

ASM ★★
()
Ответ на: комментарий от ASM

В нашем случае syscall, это наитупейшая обёртка,

Как и write. Чем от syscall отличается write? write реализуется так же как и syscall, а то, что в данном случая она реализована через обёртку - из этого ничего не следует.

Write выглядит мягко сказать посложнее.

И чем же? movq 1, %rax;syscall;ret? Это ещё проще, чем syscall, ибо даже сдвигать аргументы не надо.

Раздувать кол-во инструкций, не имеет смысла.

Количество инструкций каких? Как я и написал - static в твоём случае не имеет смысла. Нормального пацана это путает, ибо статик с инлайном указывает на то, что от инлайна требуется тело, которого у инлайн функции нет. Т.е. от инлайн функции взять адрес нельзя.

Как и Ваш комментарий про «смешно».

typedef int ssize_t;//
typedef int size_t;//т.е. это не смешно? Мало того, что int, так ещё и int, дак ещё и тайпдеф мимикрующий под стандартный тип.
//если у тебя он есть, то зачем ты его сюда написал, а если нет - зачем ты написал это "смешно"?
registrant27492
()
Ответ на: комментарий от registrant27492

Ну с write, допустим соглашусь. На всякий мусор cmpl $0x0,0x2acb19(%rip) можно закрыть глаза. С syscall результат мне всё равно показался чище.

Как я и написал - static в твоём случае не имеет смысла. Нормального пацана это путает, ибо статик с инлайном указывает на то, что от инлайна требуется тело, которого у инлайн функции нет. Т.е. от инлайн функции взять адрес нельзя.

В данном случае статик сообщает, что функция является локальной, 6.2.2/3 N1570 :

If the declaration of a file scope identifier for an object or a function contains the storage-
class specifier static, the identifier has internal linkage.
Т.е. мы даём явно понять, что кроме как в этом файле, она больше нигде вызываться не будет.

При указании просто inline больше чем наверняка компилятор выдаст:

inlining failed in call to 'write': call is unlikely and code size would grow [-Winline]

Именно потому, что посчитает, что функцию write могут захотеть дёрнуть из другого модуля.

Что касается обязательного адреса у статический функции, этого я в стандарте найти не смог, прошу пруфы, может я и не прав.

size_t и ssize_t

В этом случае надо было, конечно, делать int mywrite(int, void*, int). Соглашусь вводить size_t и ssize_t, а потом подменять его int-ом для «простоты» может быть и зря. Странно, что никто не забросал меня какашками из-за того что самописная функция write вместо кол-ва скопированных символов вовращает 0 или -1, это явная ошибка.

Что касается конкретно size_t, в стандарте явно указано SIZE_MAX 65535, минимальная разрядность int это 2 байта, так что ничего в этом криминального нет.

ASM ★★
()

Только появился веселый тред про математику, и перенесли в толксы. Пошел-ка нахер это мракобесный лор.

anonymous
()
Ответ на: комментарий от ASM

Т.е. мы даём явно понять, что кроме как в этом файле, она больше нигде вызываться не будет.

Инлайн это итак предполагает.

При указании просто inline больше чем наверняка компилятор выдаст:

Он не может выдать это, ибо на инлайн не может быть ссылки - она инлайн. Т.е. отсутствие встраивания инлайна - это вольность компилятора - нестандартное поведение. По стандарту инлайн предполагает встраивание - всегда.

Что касается обязательного адреса у статический функции, этого я в стандарте найти не смог, прошу пруфы, может я и не прав.

Я не так писал - я писал, что адрес инлайна взять нельзя. Можешь взять и проверить. Убери статик - присвой к указателю - вызови, собрав с O0. Ах да - это с99+, ибо раньше инлайна не было. Может ты смотришь протухшие стандарты, где инлайн не стандарт.

Поэтому статик-инлайн - это инлайн с возможностью взятия адреса. Т.е. с инлайном рекурсии не напишешь, адрес не возьмёшь и прочее, ибо самой функции нет.

Any function with internal linkage can be an inline function. For a function with external
linkage, the following restrictions apply: If a function is declared with an inline
function specifier, then it shall also be defined in the same translation unit. If all of the
file scope declarations for a function in a translation unit include the inline function
specifier without extern, then the definition in that translation unit is an inline
definition. An inline definition does not provide an external definition for the function,
and does not forbid an external definition in another translation unit. An inline definition
provides an alternative to an external definition, which a translator may use to implement
any call to the function in the same translation unit. It is unspecified whether a call to the
function uses the inline definition or the external definition.140)


138) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
139) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration.
140) Since an inline definition is distinct from the corresponding external definition and from any other
corresponding inline definitions in other translation units, all corresponding objects with static storage
duration are also distinct in each of the definitions.

Что касается конкретно size_t, в стандарте явно указано SIZE_MAX 65535, минимальная разрядность int это 2 байта, так что ничего в этом криминального нет.

Там написаны значения от балды. Там есть пояснения:

Each instance of these macros shall be replaced by a constant expression suitable for use

registrant27492
()
Ответ на: комментарий от anonymous

Только появился веселый тред про математику, и перенесли в толксы. Пошел-ка нахер это мракобесный лор

Иди в гости к Столярову, он тебя накачает математическим анальным.

anonymous
()
Ответ на: комментарий от registrant27492

Инлайн это итак предполагает.

Вы сами читали что процитировали? Первые два предложения из вашей цитаты говорят обратное:

Any function with internal linkage can be an inline function. For a function with external linkage, the following: <blablabla> restrictions apply

Означают ровно то, что указав inline функция может быть либо internal либо external linkage. В свою очередь, как я уже цитировал:

If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

Следовательно, чтобы функцию была встроена в код другой функции проще и правильнее всего (в моём пример) указать static inline.

Он не может выдать это, ибо на инлайн не может быть ссылки - она инлайн.

Ну включите флаг -Winline в компиляторе gcc и откроете для себя много нового.

Что касается обязательного адреса у статический функции, этого я в стандарте найти не смог, прошу пруфы, может я и не прав.

Я не так писал - я писал, что адрес инлайна взять нельзя.
Поэтому статик-инлайн - это инлайн с возможностью взятия адреса.

Т.е. получается:

  • Если у функции указан только inline, без static она не имеет адреса (уточните, как по вашему, в любом случае?),
  • Если у функции указан static, вы отнекиваетесь, соберитесь, тряпка, уж и дайте явный ответ либо: «Да, обязана иметь адрес» или «Нет, не обязана»,
  • Если у функции указан static inline, по вашему это значит, что она не имеет адреса и в ту-же очередь обязана иметь адрес, т.е. полный бред.

На основании ваши утверждений можно сделать вывод, что в стандарте где-то явно должно быть указано про конкретный случай «static inline» для функции, вот и прошу это процитировать.

ASM ★★
()
Ответ на: комментарий от registrant27492

Там написаны значения от балды. Там есть пояснения:

Тем более, если это действительно так, то и я выставил значения от балды, что в этом смешного? Единственную за что действительно можно зацепится, это, то что size_t должно быть unsigned.

ASM ★★
()
Ответ на: комментарий от ASM

У меня конечно жопу разорвало от твоих потуг врать и юлить, но ладно - раз я социализируюсь, да и хочу чтобы вы хоть что-то в этом мире понимали - я постараюсь тебе объяснить нормально.

Есть, как ты писал external и internal linkage. internal - это статик, а external у функций по умолчанию. Ну можно написать - это ничего не даст.

Ну дак в тех пастах, что я тебе выклал написано, что:

Any function with internal linkage can be an inline function. 
Что функция с «internal linkage» может быть инлайном, но не написано, что она и есть инлайн. И для всех функция это так, ибо по умолчанию экстерн.

Но для инлайн сказано, что:

For a function with external
linkage, the following restrictions apply:  If a function is declared with an inline
function specifier, then it shall also be defined in the same translation unit. If all of the
file scope declarations for a function in a translation unit include the inline function
specifier without extern, then the definition in that translation unit is an inline
definition. An inline definition does not provide an external definition for the function,
and does not forbid an external definition in another translation unit.

An inline definition
provides an alternative to an external definition, which a translator may use to implement
any call to the function in the same translation unit.

Тут сказано, что того, чтобы инлайн был external linkage - его надо определить как extern, иначе он не екстерн.

Т.е. по умолчанию инлайн вообще не linkage, а linkage к нему добавляют либо static, либо extern.

Почему тут ничего не написано про статик - написано - я выше это спастил:

Any function with internal linkage can be an inline function. 

internal linkage и есть static относительно функций.

Давай ещё раз, inline может быть external и internal linkage. Про internal здесь ничего не написано(кроме того, что она возможно), ибо это стандартной свойство функции. А вот про external написано по той причине, что не инлайн функции по умолчанию external и именно потому что инлайн по умолчанию НЕ external тут и написано как добиться external.

Далее в этом очень просто убедиться - для этого надо взять конпелятор:

inline void foo(void) {}
extern inline void foo1(void) {}
static inline void foo2(void) {}
int main(void) {
  {
    void(*f)(void) = foo;
    f();
  }
  {
    void(*f)(void) = foo1;
    f();
  }
  {
    void(*f)(void) = foo2;
    f();
  }
}

$ clang main.c -std=c11 -O0 -Winline -pedantic
/tmp/main-cc3087.o: In function `main':
main.c:(.text+0x1a): undefined reference to `foo'
x86_64-pc-linux-gnu-clang-3.9: error: linker command failed with exit code 1 (use -v to see invocation)

$ gcc main.c -std=c11 -O0 -Winline -pedantic
/tmp/ccWHSDZn.o: In function `main':
main.c:(.text+0x1a): undefined reference to `foo'
collect2: ошибка: выполнение ld завершилось с кодом возврата 1

Или подлые конпеляторы тоже сговорились с царём?

registrant27492
()
Ответ на: комментарий от ASM

если это действительно так

Это не если - это действительно так.

то и я выставил значения от балды

Но там написано, что они устанавливаются в имплементациях языка, но ты то к ней отношения не имеешь.

Поэтому ты должен использовать то, что определила та имплементация, которую ты используешь, ибо можно ей, но не можно тебе.

Единственную за что действительно можно зацепится, это, то что size_t должно быть unsigned.

Зацепиться можно за всё то за что зацепился я.

registrant27492
()
Ответ на: комментарий от registrant27492

я постараюсь тебе объяснить нормально.

Очень познавательно, спасибо. Действительно я даже не задумывался о том, что функция может быть не linkage.

Объясните, пожалуйста, ещё вот это:

$ cat main.c                                   
inline void foo(void) {}
int main(void) {
	foo();
	return 0;
}

$ clang main.c -std=c11 -O0 -Winline -pedantic
/tmp/main-c4c40e.o: In function `main':
main.c:(.text+0x10): undefined reference to `foo'
clang: error: linker command failed with exit code 1 (use -v to see invocation)                                                                                        
$ gcc main.c -std=c11 -O0 -Winline -pedantic   
/tmp/ccyjeP4Y.o: In function `main':
main.c:(.text+0x5): undefined reference to `foo'
collect2: error: ld returned 1 exit status         

Казалось бы, функция определена как inline и должна была бы заинлайнится в main, почему этого не происходит?

ASM ★★
()
Ответ на: комментарий от ASM

Объясните, пожалуйста, ещё вот это:

Ну в стандарте так же написано, что:

For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration.

Типа может и не заинлайнить. Пацаны наверное по этой причине не заморачивались этим и оставили инлайн как был раньше - оптимизацией.

Шланг(с оптимизацией) вообще вываливается, когда не может инлайнить. У меня была с этим когда-то проблема.

#include <stdint.h>
#include <malloc.h>


#define way_repeat_2(op) op;op
#define way_repeat_4(op) way_repeat_2(way_repeat_2(op))
#define way_repeat_8(op) way_repeat_4(way_repeat_2(op))
#define way_repeat_64(op) way_repeat_8(way_repeat_8(op))
#define way_repeat_100500(op) way_repeat_64(way_repeat_64(op))

inline void foo(volatile char * str) {
  uint64_t i = 0;
  way_repeat_100500({*str = i++;*str = i++;*str = i++;*str = i++;})
}


int main(void) {
  foo(malloc(100500));
}

Что-то похожее было - только по 16раз и много. Шланг отваливается. гцц инлайнит. Но в тех случаях у меня гцц то же не инлайнил, но функцию создавал - хотя я собираю всегда с gnu11.

registrant27492
()
Ответ на: комментарий от registrant27492

В итоге мы выяснили, что в static как и external inline ничего криминального нет. Аналогично как и определение size_t как int.

Осталось понять, с хрена какого gcc 4.6.4 считает inline функцию как external linkage. Собственно именно на этом компиляторе я собирал тест, из-за чего пришлось добавить static.

ASM ★★
()
Ответ на: комментарий от ASM

В итоге мы выяснили, что в static как и external inline ничего криминального нет.

Есть. Это предполагает её linkage. Т.е. когда я, да и любой пацан, вижу static inline - я предполагаю linkage, которого нет, а раз его нет - зачем оно нужно?

Осталось понять, с хрена какого gcc 4.6.4 считает inline функцию как external linkage

Значит он не умеет в с99/11 и воспринимает инлайн как в с89, где его нет, а инлайн - фича конпелятора. Собственно точно так же его воспринимает гцц6 с с89/gnu89.

registrant27492
()

Брейк!

Теперь подводим итоги раунда. Пользователь registrant27492 победил пользователя ASM, со счётом 12:9.

Бокс!

anonymous
()

Когда будет 1 глава? Хотелось бы почитать.

mul4 ★★★★★
()

Как-то уж слишком дофига, не находите? Может быть не надо так глубоко во все это нырять?

Ныряй, лично мне нужен подробный учебник по Си и gas. Чтобы завтра утром я написал драйвер для ARM микроконтроллера.

anonymous
()

По-моему, давно про лисп ничего не было. Пропиарю здесь (не охота создавать новую тему). Перевёл книгу «Let Over Lambda» Дага Хойта. Бесплатно, без смс можно взять здесь: http://rghost.net/8wLcRB5zV

anonymous
()
Ответ на: комментарий от anonymous

ничёси

Пропиарю здесь (не охота создавать новую тему).

люди ради такого целые сайты заводят

Bad_ptr ★★★★★
()
Ответ на: комментарий от anonymous

По-моему, давно про лисп ничего не было. Пропиарю здесь (не охота создавать новую тему). Перевёл книгу «Let Over Lambda» Дага Хойта.

Уважуха тебе за перевод. Лично Я, ознакомился и честно удалил этот файл. Но, зачем Лисп? Он жив?

anonymous
()
Ответ на: комментарий от anonymous

Но, зачем Лисп?

Просто по-приколу. Just for fun, так сказать.

Он жив?

Не знаю. Сам лиспом редко пользуюсь.

anonymous
()
Ответ на: комментарий от registrant27492

Ты жалок, неосилятор. Иди мыть полы. Твои знания - вот уж действительно фикция. Твоя работа - служить другим в качестве раба, это лучшее на что ты сгодишься.

anonymous
()
Ответ на: комментарий от anonymous

Ты жалок, неосилятор.

Поподробней - что конкретно я не осилил? Мыть полы?

Иди мыть полы.

Зачем, если призвание это твоё?

Твои знания - вот уж действительно фикция.

Поэтому ты срёшь мне из-под анонима и обделываешься в каждой потуге продемонстрировать свои «знания»? Ну да.

Даже смешно. Зачем пацану, который уверен, что мои знания фикция - значит у него-то знания есть - кукарекать из-под анонимуса мне, причём не разоблачая моё не знания, а просто? Как озлобленный школьник.

Твоя работа - служить другим в качестве раба, это лучшее на что ты сгодишься.

Ну естественно - работа таких людей как я - это позволять жить таким(опустим определение) как ты. Но меня это не касается - так что не угадал.

В конечном итоге - разоблачай - вперёд. Показывай свои знания - показывай моё незнание. Пиши под учёткой. А пока ты крыса, а крысятничество - последний довод, причём самый малоэффективный. А значит что? Только одно - другого ничего не можешь.

В целом мне не ясно - уже наверное самый тупой школьник не ведётся на эту херню - из какой деревни ты вылез?

registrant27492
()
Ответ на: комментарий от anonymous

Лучше бы что-то полезное переводил. Этих школолиспов, пхп, всей этой херни как дерьма - зачем ещё больше? А вот чего-то посложнее уже нет.

registrant27492
()
Ответ на: комментарий от registrant27492

Лучше бы что-то полезное переводил.

Предлагайте. Рассмотрю. Если заинтересует - переведу.

anonymous
()
Ответ на: комментарий от anonymous

Да любая книга не про пхп. Про лоулевел, про вменяемые языки, которые можно использовать С/С++ - там вообще литературы нет.

Или вон пацан в соседней теме пытался написать парсер/лексер/интерпритатор - то же ничего, кроме убогой и протухшей книги с драконом нет. Ничего нового во всех сложных темах с реальными подходами к реализации - нет.

Есть академическая мура, которая является переизданием из 70-х - уже протухла 25раз. А всё, что новое, но не про то, что так яро хайпят(вебчик, недоязычки, новые куллязычки, либы/фреймворки на этих куллязычках).

Вон я пару дней назад пытался загуглить что-то про machine learning на родном - одно дерьмо. Ориентация чисто на школьника, которому надо сдать зачётку - ничего конкретного, да и на не родном то же самое.

Т.е. в любую тему капнуть чуть глубже зачётки с родным не прокатывает, а уж в темы по сложнее - даже на уровне зачётки не копнёшь.

А так я не особый поклонник макулатуры - мне лениво тратить своё время на чтение того, где 99% воды. Да и переводы это такое. Всё равно книги пишутся убогим языком, с убогими подходами из расчёта на студента-дауна и их нереально читать.

Я вот глянул на это:

Но в Лиспе самый очевидный путь обозначения желаемой единицы

И ниже хоть какие-то потуги автора выкатить код «не как в си», но переводчик выкатил пасту с си:

(defmacro sleep-units (value unit)
`(sleep
(* ,value
,(case unit
((s) 1)
((m) 60)
((h) 3600)
((d) 86400)
((ms) 1/1000)
((us) 1/1000000)))))
//вот нахрена мне это убожество может понадобиться? Это ещё большее днище, чем в сишке.

Отличная идея. А теперь смотрим * (unit-of-time 1 d) 86400

Отличная идея. Просто мусор - на сишке это делается так:

enum { day = 86400};

1 * day;

Но всё это мусор, ибо в языке, который заточен на интерфейсы - это 24h. Но это такое.

Самый главный вопрос, на который должна отвечать книга по лиспу - это «нахрена он нужен». Сишка нужна, чтобы писать качественный код с т.з. получаемого результата компиляции. Кресты нужны, когда надо ваять интерфейсы, либо какое-либо говно на готовом говне, но с оглядкой на качество результирующего кода. Остальные недоязычки - это ваять дерьмо и насрать на всё. Там уровень недоязычка зависит от уровня отсутствия квалификации у адепта.

А нахрена нужен лисп? Я всё мечтаю о том дне, когда хоть кто-то осилит написать книгу и объяснить - нахрена нужен лисп. Может хоть ты объяснишь мне.

registrant27492
()
Ответ на: комментарий от anonymous

узнаешь по плодам их

когда в одной культуре рассказ тот был написан и даже опубликован в той о которой ты всё ещё было рабство и конечностевредительство как форма регламентированного наказания .

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

Но, зачем Лисп? Он жив?

В QuickLisp-е за тысячу библиотек. И к этому еще с горкой на github-е. 5-ок живых открытых реализаций для разных сегментов. И пара платных навороченых. В Clusp-е рапортуют о разделямых библиотеках и компиляции в LLVM-овский байткод.

antares0 ★★★★
()
Последнее исправление: antares0 (всего исправлений: 1)
Ответ на: комментарий от registrant27492

Ладно, вот Вам пример, писали толковые ребята из intel:

http://dpdk.org/browse/dpdk/plain/lib/librte_ring/rte_ring.h

static inline int __attribute__((always_inline))
__rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
		 unsigned n, enum rte_ring_queue_behavior behavior)

На фига это всё, если достаточно одного inline?

ASM ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.