+162
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
// © Код Арсения
#include <stdio.h>
#include <conio.h>
#define N 100
int n,kol=1; //одекватен до 6!
void SAW(int *a,int *b)
{
*a-=*b;
*b+=*a;
*a=*b-*a;
kol=kol+1;
}
void deduction(int A[])
{
int i;
printf(" %5d : ",kol);
for (i=0;i<n;i++)
printf(" %d ",A[i]);
printf("\n");
if (kol%290==0)
getch();
}
void Shift(int A[], int k)
{
int i;
if(k<2)return;
for (i=0;i<k-1;i++)
{
Shift(A, k-1);
if (!(i>=2 && k%2==0))SAW(&A[k-1],&A[0]);
else SAW(&A[k-1],&A[i-1]);
deduction(A);
}
Shift(A, k-1);
}
void main()
{
int A[N],i;
printf("vvedite n\n");
scanf("%d",&n);
for (i=0;i<n;i++)
A[i]=i+1;
deduction(A);
Shift(A,n);
printf("\n %d \n",kol);
}
Классический вариант быдлокода в программе, которая печатает всевозможные комбинации перестановок цифр заданной длины. Для того чтобы поменять два значения местами используется отдельная функция SAW, которой передаются указатели на переменные (автор думает, что это круто), в самой же функции производится обмен значений, на которые указывают указатели без помощи дополнительной переменной (опять же автор считает, что это круто), причем, стоит обратить внимание, каким образом это делается (видимо операция XOR этому кодеру пока не известна). Далее классический стиль написания быдлокодера прослеживается буквально в каждой строчке, включая названия функций. Стоит также обратить внимание на оригинальную реализацию рекурсивной процедуры, проницательный читатель сразу же поймет смысл комментария в строке: int n,kol=1;//одекватен до 6!
Запостил:
jkoff,
25 Декабря 2010
Инкремент в функции SAW переменной, используемой при форматировании вывода, тоже круто.
> Инкремент в функции SAW переменной, используемой при форматировании вывода, тоже круто.
так это скорее всего и есть как бы основная часть алгоритма: каждый свап геренерит новую перестановку. считая количество свапов считается количество перестановок.
работает оно или нет ХЕЗ, но такого я уже насмотрелся вдоволь в универе.
На самом деле этот тот случай, когда передача по указателю нагляднее говорит о возможных проблемах, чем передача по ссылке - новички могут не знать, что ссылка это завуалированный указатель.
В Pacal/Delphi тоже можно так написать. Двум указателям на integer дать одинаковые адреса и оно обнулится. Теперь паскаль тоже опасный язык?
А ещё слово «лопата» и вставку картиночек с демотиваторов или с Лурочки.
В Си нет передачи по ссылке. Только в паскале. Паскаль опасен!
?
>Ололо риальне!
Вы правы. :)
Не соглашусь. Про наличии компилятора это очень даже умно. А с учётом того, что для дров нужна надёжность, как раз распространение Си в той сфере - глупость.
Познай же мир ретипизации.
Например, прямое обращение к пикселу изображения:
PColor(integer(Buf.Mem) + (X + Y shl Buf.OrdX) shl 2)^
Это под 32 бита.
>Это под 32 бита.
А если кросплатформенно захочу? 10 реализаций делать?
Ну это как писать. Если говнокодить, то да.
Вообще есть size_t и ptrdiff_t и прочие. Вот как эта проблема в си решается.
Если пишешь под конкретное устройство, то под него и пиши.
А итераторы — это грабли. Трудно понять, что делает выражение *p++.
Инкремент указателя, в зависимости от типа - это плюс. Или Вы не об этом?
Не хватает только задорной фуражки кепа. )
Как видите, я её не осуждаю.
DWORD MMBAR, *mmio;
//тут из пространства PCI устройства считывается MMBAR
mmio = (DWOR*)KernelMapPage(MMBAR, ...); //из самой библиотеки ядра
//......
mmio[0x100] = 0x00000F80; //вот это меня интересует как будет выглядеть на чистом паскале без библиотечныхх функций потому что нет ни каких гарантий, что они будут работать в режиме ядра
//.....
Кстати, это мне всегда казалось граблей.
DWORD* MMBAR, mmio;
И уже не верно... Получается часть типа к имени переменной переносится.
Щи и мухи должны быть отдельно.
и в путь.
Неудачная шутка.
Вообще иногда нужно постараться, что-бы придумать сотню другую типов в С++ для обычных указателей.
Впрочем, последняя строка очень даже надуманна, но классов в С++ может быть больше переменных в программе. Неужели для каждого придумывать свой тип указатель?
Придёться смириться или идти в комитет стандартизации на место "генерального секретаря".
static BYTE (*GetBootDevice)();
//...
GetBootDevice = ((void*)0xFA000100);
//...
BYTE dev = GetBootDevice();
а вот это?
var GetBootDevice: myfunc;
dev: byte;
//...
GetBootDevice := Ptr($FA000100);
//...
dev := GetBootDevice;
В случае же процедурного типа возникает неоднозначность, поэтому @ используется для предотвращения вызова функции. Если же надо взять адрес функции, используется (о, ужас!) @@. В FPC синтаксис немного иной.
Borland-style: FPC-style: Здесь собачка в правой части, потому что мы извлекаем адрес, а не вызываем функцию, что логично.
А если Вы хотите использовать 32-битные смещения в 16-битном компиляторе, то даже в Си без асма никак.
В защищённом режими для работы с BIOS можно использовать точки входа, специально для этого предназначенные. В частности они есть для работы с видеорежимами.
Если есть желание, то в ряде случаев можно переключится в реальный режим и пользоваться чем хочешь.
Не спорю. В контексте данной задачи Ваши аргументы неоспоримы.
Вообще легкосложно без ассемблера, но возможно.
Набил массивчик в сегменте кода опкодами любых инструкций ассемблера и передал туда управление. Конечно, стоит вопрос о записи в сегмент кода...
В паскале, правда, эта проблема не стоит:
В плане запрета использования ассемблера в языке Pascal встроен оператор inline. Там пиши любые опкоды и передавай им управление.
>а можно взять и на мониторе написать маркером "Hello world"
Не наш метод. Это предложили Вы.
Только разговор уже идет не по существу.
Зачем искать, если я это видел.
В любом случае заполнить массивчик и передать управление в него не будет так просто, как Вы говорите. Не всегда разрешено выполнение "сегмента данных". Это нужны будут дополнительные телодвижения.
На паскале проблем будет меньше, тк опкоды записанные в inline в любом случае будут в "сегменте кода".
*У меня понять сильные и слабые стороны инструмента.
Ну и заодно немного посмеяться. Не ходить же всё время унылым букой. :)
Наверное, бояться вопроса: "Где здеси Си?"
Граммар-наци негодует!
Чёрт! Кажется, последнего живого испугал.
Поднимаю бурю негодования Граммар-наци. А то все с говнокода пропали... Какая ошибка ещё более заметна, чем эта(и не похожа на опечатку)? Помоему нет такой.
КЭП, Кэп, кэп, Cap или Кеп?
«капитан Очевидность»?
НеНеНе. Длиннннно.
Загрузчик:
я загрузчик как раз писать не прошу. И хоть бы узнал вообще, что это такое.
char *TextVideoMem = (char*)0xB8000;
void PutStringTo(int X, int Y, char *string, char attr)
{
char *base = TextVideoMem + X + Y*160;
char c;
while(c = *string++)
{
*base++ = c;
*base++ = attr;
}
}
void KERNEL()
{
PutStringTo(30, 12, "Hello world from binary C code", 12);
for(;;);
}
это прямо тот .c файл что в архиве, где пример низкоуровневой моей программы на Си.
И потом код сравним...
Чистый код потом можно вытащить сторонними утилитами типа Exe2Com или Exe2Bin.
Ну ладно я с нетерпением жду.
(*) Также Striker (админ форума), и кажется (извиняюсь, если ошибся) inkanus-gray (пользовательский скрипт для борьбы с местным нарушителем правопорядка, под ником "Компренда").
ЩИТО?
Умельцы, если знаете, то говорите. Это вопрос защиты Паскаля...
В С++ это исправляется легко. Просто переопределяется maincrtstartup, вызывающая инициализацию стандартной библиотеки и в ней уже вызывают вышеназванную функцию KERNEL.
1. Переписываем модули System и SysUtils (см. ссылку TarasB).
2. Выводим obj-файл и используем внешний линкер. Этот вариант таит опасность неопределённых внешних ссылок, если код требует функции модуля System.
Это точно не сработает. Какая уж тут опасность...
Это ведь обращение ко мне? Возможно я там где-то описался, так что это естесвенно... :-[
Без цитат тежеловато понять к кому запрос, когда посты дошли до края экрана...
помнится, когда-то давно один чувак описанным выше способом сделал драйвер типа VXD под Win9x
type
TScreenSymbol = record
Symbol: char;
Color: byte;
end;
Screen: array [0 .. 49, 0 .. 79] of TScreenSymbol absolute $B800: $0000;
Статистика же. Граблей в языке много.
> вам все равно потребуется "лезть" напрямую в память
Я вспоминаю тему, где какая-то школота всем доказывала, что только си позволяет записать в нулевой адрес памяти.
Так не хорошо. Прирывания нужно запретить, прежде чем замещать. А тут без ассемблера не обойтись. Стандартная библиотека это не позволяет.
К тому же во время замены прерывания может произойти прерывание по таймеру и там произойдет деление на 0.
Прерывание деления на ноль может даже произойти на другом ядре, а обработаться на этом.
А я мало. Не хочу быть задротом, знающим все особенности архитектур всех платформ. Мне больше нравятся математические и алгоритмические задачки. :-[
Есть файл в нём лежат натуральные числа в произвольном порядке. Они не превосходят N, при этом их количество также не превосходит N. Нужно наискорейшим образом перенести эти числа в другой файл в невозрастающем порядке. Памяти произвольного доступа хватает, чтобы все числа в ней разместить.
(для головоломности можно попробовать покрутиться, если разместить в памяти можно M < N числе только)
Тоесть в памяти можно завести массив N чисел? Если так, то слишком просто.
>Нужно наискорейшим образом перенести эти числа в другой файл в
Так уж и скажите 2*О(N).
Хотите перевести тему разговора? :D
Это проверка.
Да можно.
:-)
А зачем? Это же простейшая задача.
1)Заводим массив-счётчик чисел (пока инициализируем нулями).
2)Первый О(N):
Читаем первый файл и встретив каждое число прибавляем в соответсвующей позиции массива-счётчика 1.
2)Второй O(N):
Записываем во второй файл все числа, подсчитанные в массиве-счётчике.
Думаю, не стоит отвлекаться от темы разговора. :)
Нужно сообразить, что в массиве, в отличие от списка, найти позицию с индексом стоит одну операцию.
А задача жизненная, приходилось такое писать. Там были действительные числа, но перемножением приводились к целым конечно же :-)
А вот ещё жизненная задача.
Есть граф направленный: в одну вершину может вести много рёбер, но выходит всегда одно.
Нужно выделить все циклы и отдельные цепочки.
То есть, из того, что раньше задавало граф неизвестный, построить ясное представление: какой элемент принадлежит какой цепочки или циклу.
> не стоит отвлекаться от темы разговора
P.S. Эта ваша тема Pascal vs. С такая скушная... Её нужно было обсуждать годах в 70х, когда Паскаль уже был и вдруг начинают писать Си, и вопрошать у лаборатории Белла: "Зачем вам Си, коль есть такой крутой Паскаль?" Тогда и получили бы ответ достойный.
Вот предо мной сидит HR манагер и мне вопросы задаёт про алгоритмы поиска и сортировки. А я с лептопа пощу их на говнокод. :-)
Блин, вот как всегда, оказалось, что воинствующие сишники вообще не знают про то, что на Паскале можно приводить указатели к целым.
PS: долго думал, что может означать SAW (вероятнее всего SWA)
Да вообще этот SAW - шедевр в каждой строчке. Хоть бы заинлайнил, смысла от именно такого написания данной функции было бы чуть больше. :)
Во-первых, все функции в языках С и С++ являются external по умолчанию. Т.е. именно к GCC это никакого отношения не имеет.
Во-вторых, является функция external или static не является никакого влияния на inlining не оказывает вообще. С чего бы это? Обычному компиялтору, чтобы выполнить inlining тела функции в точке вызова надо просто иметь возможность видеть это тело, т.е. inlining выполняется только там, где функция определена (а не просто объявлена). А продвинутые компиляторы, умеющие делать глобальные оптимизации, умеют делать inlining вообще везде.
В наше время попытки явного inlining функций - дейсвительно сомнительная и ненужная практика.
void f(int param)
{
//тут коротенькая процедура без циклов и всего того, из-за чего функция может не стать inline
}
//несколько раз вызывается в разных частях программы
берем дизасм, смотрим - конечно же ее код никуда не встроился.
inline void f(int param)
{
//все тоже самое
}
смотрим – чудеса (!), компилятор опять ее не встроил.
static inline void f(int param)
{
//все тоже самое
}
смотрим – ага, а вот сейчас как раз на месте где должен быть вызов этой процедуры находится ее код, значит встроилось
static void f(int param)
{
//все тоже самое
}
результат аналогичен предыдущему эксперименту
Я же ясно написал: в "традиционном" компиляторе код будет встраиваться только там, где комиплятору видно определение (т.е. тело) функции, т.е. именно и только в том объектнике, в котором функция определена. При этом встраиваемость кода никак не зависит от того, extern функция или static. Поэтому не надо было лазить дизассемблером "по разным частям программы" - никакого смысла в этом нет. Лазить надо было только по одному конкретному объектнику - тому, который содержит определение данной функции. И там было бы прекрасно видно, что функция встраивается независимо от того, extern она или static.
А вот чтобы она встраивалась по всей программе, нужен, во-первых, продвинутый, глобально оптимизирующий компилятор, и, во-вторых, набор соответствующих установок компиляции. Я навскидку не знаю, умеет ли gcc выполнять такое глобальное встраивание, но это уже вопрос отдельный.
P.S. Ого, капчу врубили.
и на J2ME писал
В этом мы поговорим о том, как получать байткод для JVM на Си.
Вы же портите студентов! Великое русское образование катится в...
Выпилено Сатаной?
shm> Есть те которые это усваивают и пересказав все, что усвоили перед преподом получают "отлично", а те кому пох. и учить ничего не охота как правило просто "уд.".
Вот вторых масса, первых единицы - стоит ли так распинаться перед всеми?
Может стоит увеличить акцент для первых, сведя объяснения для вторых к минимуму?..
вам всё равно где их окучивать, а мне приходится обязанности HR исполнять, потому что вашими стараниями диплом ничего не значит.
Если бы отсутствовала возможность репетиторства и/или некоей корыстной помощи обучающимся, что бы тогда стало? Был талант - нету таланта, а так он, во всяком случае, остаётся.
А то, что студент не хочет учится тому, чему его пытается обучить штат преподавателей - это целиком его вина. И то, что HR кроме диплома ни на что не смотрит, и ничего кроме не принимает - аналогично говорит о его (HR) компетенции...
Уж, если что, извиняюсь...
и вообще, почему бы не отпустить ступидента реализовываться в другой области?
Только это без толку...
На самом деле я в скором времени закругляюсь с этим делом (нашел подработку посерьезнее).
учитывая, что Вы первый затронули эту тему, почему бы Вам не заткнуться первым?
и да, качество работы преподавателей критики не выдерживает (у них есть ряд своих интересов), однако это вашу сферу деятельности никак не оправдывает, поскольку она по сути паразирует на халатности преподавателей.
О сообщение юбилейное - 256е.
Да надо бы оттрассировать рекурсивные вызовы Shift, потому что без этого не понять, как оно работает.
Отлучился, понимаешь, на пару дней статью писать...
А тут фигакс! И такое...
И почему-то сразу скучно стало :-(
В любом случае все проблемы языка связаны с отсутствием соответствующих компиляторов (или недостаточной известностью некоторых подходящих) .
Аргменты сионистов пока смахивают на "только язык Си позволяет писать в нулевой адрес, мне хакер Вася сказал из 9б, он знает!", сионисты просто не знают возможностей Паскаля и некоторых его компиляторов.
И ещё для особо упоротых: военные давно поняли то, о чём я говорю и изобрели язык Ада, который применяется и для встраиваемых систем.
Так что и для написания дров Паскаль, при наличии подходящего компилятора - самое то, но увы, распространению сей поспособствовала разновидность интеллектуального дрочерства - ведь круче же писать на непонятном языке, состоящем из закорючек, чем на легко читаемом простым человеком. Круто же, когда непосвящённые тебя не понимают, сразу таким волшебником себя чувствуешь, да?
Верю, но для порядка приведите пруф.
Не понимаю о чём Вы. Что там нечитаемого? Многие функциональные языки много более нечитаемые для неподготовленных людей.
В любом случае удобство чтения зависит от человека, написавшего код, например можно, если уж совсем невтерпёж, использовать конструкцию:
И так можно улучшать "читаемость" и дальше, в прочем мне это кажется менее читаемым.
Вообще для мня грамотно(!) написанный код на Си ( или на языках основанных на его синтаксисе) намного более читабельные Паскаля с его бегинами и эндами. Главный фактор - краткость, которая позволяет более быстро набивать код (хотя это это не самый важный плюс, т.к. эта скорость съедается разработкой оптимального алгоритма и отладкой) и конечно ввизуально намного проще воспринимаются сложные ветвления в циклах; в паскале такой же код пестрит теми же самыми бегинами и эндами которые затрудняют его восприятие (пок райней мере для меня). К тому же операторы вроде div и mod мне тоже кажутся излишеством затрудняющим чтение. В Си намного удобнее в этом плане есть оператор "/", и компилятор сам решает как его использовать для целых чисел или с плавающие запятой при необходимости (которая возникает не особо часто) можно сделать приведение типов.
На языках с функциональной парадигмой ещё меньше печатать. :)
>бегинами и эндами которые затрудняют его восприятие
Именно так... (только для меня, конечно)
>div и mod
Конечно лучше:
& | >> %
a-=b; a<<=b;
a-=b; a<<=b;
И чего в этом нечитабельного!? Все кратко и очень даже читабельно.
Единственное не люблю когда в одну строчку начинают лепить:
a+=b; b-=c; //вот это уже трудно воспринимется
Я как бы это и сказал. Очень даже читабильно. Для меня чем короче, тем читабильнее... Не знаю почему...
Строение мышления?
Почему?
∈, ⊆, ∃, ∪, ⋂, а также ℕ, ℤ, ℚ, ℝ, ℂ
и ∞ - как тип infinity
ввели
документированная
Что касается инкремента типизированных указателей -- это же логично и очевидно. С расслаблением запрета на арифметические действия с нетипизированными указателями есть предистория: до введения двухбайтного generic символьного типа арифметика была разрешена только для типизированных символьных указателей и этим пользовались также для работы с байтовыми данными, после введения операторы потеряли смысл, и была введена локальная директива $POINTERMATH.
Паскалисты, если переходят на си, то только ради компилятора.