Здравствуйте, Павел Кузнецов, Вы писали:
>>> А вот насчет массивов, это вы загнули. >> >> В С их как таковых нет — есть только синтаксический сахар над указателями.
ПК>Распространенная точка зрения, не вполне согласующаяся с реальностью, данной нам в ощущениях: ПК>
ПК>int a[5] = { 0, 1, 2, 3, 4 };
ПК>
ПК>как преобразовать данную конструкцию в эквивалент на указателях?
ИМХО, это аргумент не по существу дела.
Главная проблема с массивами Си в том, что информация об их "массивовости" теряется при выходе из соответствующей области видимости (scope)).
Рассмотрим пример (в который раз? ).
void foo(int *p)
{
/* сначала немного любимой адресной арифметики */
p[-1] = 666; /* раз */
5[p] = 666; /* два */
/* да, и, кстати, как же здесь отличить массив от указателя? :xz: */
free(p); /* три */
}
void bar()
{
static int a[5] = { 0, 1, 2, 3, 4 };
foo(a);
}
Так что же неверного в утверждении, что массив в Си (вне области видимости его объявления) неотличим от указателя?
ИМХО, приведенный Вами, Павел, пример и есть не что иное, как syntactic sugar: так, прилепили фичу к указателю.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC wrote:
> Главная проблема с массивами Си в том, что информация об их > "массивовости" теряется при выходе из соответствующей области > видимости (scope)).
mormat wrote:
> C>А на чем еще писать ОСы? > http://bluebottle.ethz.ch/ > Чем не ОС на Active Oberon. Ведет проект один человек. Я был приятно > удивлен увиденным. Думаю, если бы эту ось на постоянной основе > продвигало хоть на порядок больше народу, и если бы еще ктото-чтото > писали софт и игры для неё, и несколько раньше (лет на 10 ) — ситуация > на рынке ОС могла бы сложится несколько иная.
Уже до тошноты тут ее обсуждали (у нее нет защиты памяти, например). Еще
в этой ОСи не получится нормально запускать программы на С или Haskell,
например.
Это, кстати, касается и Владовского примера ОСи на С#.
--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0 beta
Sapienti sat!
Re[11]: Лекция Вирта в политехническом - впечатления
VladD2 wrote:
> C>Синтаксических сложностей в С не так много, и они никаких проблем не > C>доставляют (после того, как на них раз наткнешься). Сложности возникают > C>из-за низкоуровневого программирования (ручное управление памяти и > т.п.). > Агащазблин. С напичкан граблями. Их в нем так много, что на С++ с > головой хватило. А в начале он был вообще ужасным. Это сейчас многое > компилятором проверяется.
А раньше проверялся lint'ом.
--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0 beta
Sapienti sat!
Re[12]: Лекция Вирта в политехническом - впечатления
Здравствуйте, eao197, Вы писали:
E>hint: размещать константу слева от знака равенства. Тогда выражение if( 10 = a ) просто не скомпилируется.
блин, я же написал, что больше 10 лет уже программирую на си. Ну неужели ты думаешь, что я этого правила не знаю? В том фрагменте кода я сравнивал две переменные величины. И это правило, естественно, не работало. Алгоритм был довольно сложный, поэтому отладка заняла много времени.
Но, принципиально здесь ничего не меняется. Во-первых, графическое выражение операции стравнения, так же как и присваивания, противоречит математической интуиции. Исмвол "=" значит в математике именно сравнение, а не какую-либо операцию. Во-вторых, использование "=" и "==" ведет к вышеупомянутым ошибкам независмо от математической традиции. Ясно одно: это синтаксичесая неудача языка.
E>Наблюдение из собственного опыта: после того, как я стал следовать этому правилу, я ни разу не ошибся с присваиванием в if (даже если в сравнении использовались два lvalue), т.к. приходилось задумываться о том, есть ли в выражении константа, которую можно написать слева. Из-за этого на выражении в if() внимание концентрировалось и ошибок в написании == просто не происходило.
Уже писал об этом. Придумывать костыли для синтаксического свойства языка указывает только на одно: это свойство неудачно.
Пацак wrote:
> C>Это не проблема — это достоинство > Скорее просто фича. А уж чем она оборачивается — проблемами или > достоинствами — это от конкретного случая зависит.
Я собственно это и хотел сказать. Адресная арифметика — просто
незаменимое средство для низкоуровневого программирования, но у нее свои
недостатки.
--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0 beta
Sapienti sat!
Re[12]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Cyberax, Вы писали:
C>В языке С почти отсутствуют искусственные для низкоуровневого C>программирования понятия.
Честно говоря, я склоняюсь к тому, что Си — высокоуровневый язык, из семейства так называемых процедурных языков. Низкоуровневые свойства, конечно, есть, но они синтаксически непродуманы. Маппирование памяти на типизированный объекты путем введения указателей введено ИМХО неудачно. Гораздо лкчше было-бы ввести специальный оператор для такой операции. Существующая арифметика указателей ведет к ошибкам. В общем, по моему мнению, указатели — неудачное решение.
C>Например, массив в Паскале — это "черный ящик" — мы о нем знаем только C>то, что к нему можно обращаться по индексу. Формат хранения данных в нем C>нам неизвестен. В языке С массив представлен в виде указателя — мы точно C>знаем его структуру и свойства.
Ну так ведь принцип здесь один: в процедурный язык вводятся понятия, связанные с Фон-Неймановской машиной. Т.е. средства для работы с плоской адресацией с произвольным доступом. Реализовать его можно различными способами. Как я уже писал, по моему мнению, гораздо лучшим решением было-бы ввести специальный оператор маппирования на память с произвольным доступом. При этом удобно было-бы вести работу с различными типами памяти, для встроенных ОС. Сейчас в Си это делается с помощью довольно уродливых расширений компилятора — модификаторов типа.
C>Это такая фигня — ошибка того же класса, что и and вместо or.
Не понимаю, как можно об этом спорить??? Пропустить случайно один символ "=" это ведь не тоже самое, что написать "<" вместо ">"? Или "||" вместо "&&"?
C>Что могу сказать.... Тренироваться надо! Я уже не вспомню, когда в C>последний раз я искал подобную ошибку больше 5 минут.
В сложном алгоритме такую ошибку трудно найти. И вообще, эта твоя фраза выше высокомерием отдает, не находишь?
C>А с какой стати оно должно стоять в другом месте?
с такой, что в Си объявление типа строится по схеме: имя_типа имя_переменной. Почему в объявлении массива имя_переменной залезло в середину имени_типа? Это уход от единой схемы объявления. И кто-нибудь может мне объяснить, какая у этого ухода была цель???
C>В низкоуровневом программировании без этого — никуда.
Писал об этом выше. Работу с памятью с произвольным доступом можно организовать совсем по другому, без всяких уродств, связанных с указателями.
>> C>Нет. Потому, что интерфейс С настолько БАЗОВЫЙ, что дальше уже некуда. >> Не понимаю, что значит "базовый интерфейс"?
C>1. Сишные функции и переменные экспортируются по имени, в C>экспортированой сигнатуре отсутствует информация о типах (т.е. нет C>проблем с несовместимым ABI). C>2. Сишные структуры можно располагать в памяти с точностью до _бита_ C>(битовые поля, однако). C>3. Никакого GC и исключений (нет проблем с ABI). C>4. Есть примитивы для вызова функций по указателю и т.п. C>5. Арифметика указателей (основное Cшное тождество: a[i]==*(a+i)==i[a]).
Если номер один я могу отнести к интерфейсу, то каким боком туда остальные пункты попали? Номер один же является скорее недостатком, нежели преимуществом. В результате, при неверном импорте, приложения зачастую падают и ошибку такую диагностировать очень трудно.
C>Тем не менее, даже сейчас нечем полностью заменить С. Даже у С++ C>уже есть определнные недостатки по сравнению с С.
Вот с этим согласен, заменить нечем. Традиция. Но это снова не говорит о том, что низкоуровневые свойства языка можно было бы организовать по другому.
C>-- C>С уважением, C> Alex Besogonov (alexy@izh.com)
Re[12]: Лекция Вирта в политехническом - впечатления
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, mefrill, Вы писали:
VD>Согласен, что С ужасен во многих аспектах, но надо давать скидку на времена и понимать что заменял С и какие были в те времена у него пользователи. Что же касается присвоения, то ту дело не в синтаксисе. В C#, например, синтаксис тот же, но подобную ошибку допустить невозможно. Разница между языками заключается в том, что C# типобезопасный язык, а С нет. Ведь так все просто "a = b" должно возвращать значение того же типа, что и "a". Оператор if же должен принимать выражение типа bool. Никакие присвоения кроме присвоения булевых переменных такой тип не дают, так что компилятор сразу выявляет ошибку. Ну, а сравнивать булевы переменные просто глупо, так что грабли в этом случае скорее гипотетические. Те кто на них наравлся должны просто сменить проыессию.
Ну не знаю. Что такое операция присваивания? Это, на самом деле, две поледовательных операции:
1. Прочитать данные из участка памяти, на который ссылается выражение справа.
2. Записать прочитанные данные в участок памяти, на который ссылается выражение слева.
Инчае говоря, данная операция составная, обозначающая две атомарных, и имеющая направление. Естественно было бы обозначать ее стрелкой или там, как в Паскале ":=", здесь есть ассиметричность, а значит, есть и направление. Но обозначать эту операцию символом "=" — это значит, во-первых, убрать из обозначения операции направление и, во-вторых, противоречить математической интуиции. Далее, обозначив сравнение неестественным "==" вставили в язык источных ошибок при написании. Т.е. ИМХО это все-же проблема синтаксиса, а не семантики. Ну стали бы обозначать присваивание через |-|, какая разница? Человек бы все-равно привык рано или поздно, а вот изучать труднее. Конечно, создатели языка имели какие-то причины ,когда выбирали эти обозначения. Хотелось бы с ними ознакомиться.
M>> Или пресловутые указатели. Чтобы человек понял их премудрость необходимо столько же времени, а иногда и больше, чем на изучение всего Си перед этим. VD>Полностью согласен. Однако в этом минусе есть свой плюс. Познание указателей открывает человеку некое внутреннее понимание работы компьютера. Я заметил, что если человек не в силах понять указатели и научиться с ними работать, что ему вообще лучше завязать с программированием. Ну, не для него оно. Так что С и С++ замечательные развивалки для мозгов. Но первыми языками их лучше не делать. Хотя я лично начинал именно с С. Проблемой это не стало. Но как сейчас помню как не просто далось его изучение.
Ну вот о чем я и писал уже выше. Прямую работу с памятью можно было бы реализовать по другому, может быть более полно отразив понятия Фон-Неймановсткой машины.
Re[13]: Лекция Вирта в политехническом - впечатления
mefrill wrote:
> C>В языке С почти отсутствуют искусственные для низкоуровневого > C>программирования понятия. > Честно говоря, я склоняюсь к тому, что Си — высокоуровневый язык, из > семейства так называемых процедурных языков.
Это одновременно высокоуровневый и низкоуровневый язык. Именно
это и является его основным достоинством и причиной популярности.
> Низкоуровневые свойства, конечно, есть, но они синтаксически > непродуманы. Маппирование памяти на типизированный объекты путем > введения указателей введено ИМХО неудачно. Гораздо лкчше было-бы > ввести специальный оператор для такой операции.
Угу, и получится то же самое "вид сбоку".
> Существующая арифметика указателей ведет к ошибкам. В общем, по моему > мнению, указатели — неудачное решение.
Предложите что-то лучше. Только учитите, оверхед по сравнению с обычными
указателями должен быть равен 0.
> Ну так ведь принцип здесь один: в процедурный язык вводятся понятия, > связанные с Фон-Неймановской машиной. Т.е. средства для работы с > плоской адресацией с произвольным доступом. Реализовать его можно > различными способами. Как я уже писал, по моему мнению, гораздо лучшим > решением было-бы ввести специальный оператор маппирования на память с > произвольным доступом.
Чем какой нибудь:
[code]
void func(mem_address adr)
{
var int num=project(adr); //Как, кстати, указатели обзначать будем?
}
[code]
будет лучше:
void func(void *obj)
{
int *num=(int*)obj;
}
?
> При этом удобно было-бы вести работу с различными типами памяти, для > встроенных ОС. Сейчас в Си это делается с помощью довольно уродливых > расширений компилятора — модификаторов типа.
Пусть лучше модификаторы типов остаются.
> C>Это такая фигня — ошибка того же класса, что и and вместо or. > Не понимаю, как можно об этом спорить??? Пропустить случайно один > символ "=" это ведь не тоже самое, что написать "<" вместо ">"?
Для меня, например, то же самое.
> C>Что могу сказать.... Тренироваться надо! Я уже не вспомню, когда в > C>последний раз я искал подобную ошибку больше 5 минут. > В сложном алгоритме такую ошибку трудно найти. И вообще, эта твоя > фраза выше высокомерием отдает, не находишь?
Ну что сделать Факт остается — ни для меня, ни для моих коллег ошибка
с заменой == на = не является сколь-либо заметной проблемой.
> C>А с какой стати оно должно стоять в другом месте? > с такой, что в Си объявление типа строится по схеме: имя_типа > имя_переменной. Почему в объявлении массива имя_переменной залезло в > середину имени_типа? Это уход от единой схемы объявления. И кто-нибудь > может мне объяснить, какая у этого ухода была цель???
Просто авторы посчитали, что лучше сделать схему "имя_типа
имя_переменной модификатор_массива"
Честно говоря, есть намного большая проблема с объявлением типов в С:
char* ptr=NULL,ptr2=NULL; //А ptr2 - это не указатель!
> C>В низкоуровневом программировании без этого — никуда. > Писал об этом выше. Работу с памятью с произвольным доступом можно > организовать совсем по другому, без всяких уродств, связанных с > указателями.
Они будут отличаться только по синтаксису, а не в семантике. Кроме того,
_реальная_ память — это вовсе не абстрактное "устройство с произвольным
доступом". Например, в ядерном режиме приходится иметь дело со
страничной организацией памяти, сегментами, привиллегиями доступа и т.п.
> C>1. Сишные функции и переменные экспортируются по имени, в > C>экспортированой сигнатуре отсутствует информация о типах (т.е. нет > C>проблем с несовместимым ABI). > C>2. Сишные структуры можно располагать в памяти с точностью до _бита_ > C>(битовые поля, однако). > C>3. Никакого GC и исключений (нет проблем с ABI). > C>4. Есть примитивы для вызова функций по указателю и т.п. > C>5. Арифметика указателей (основное Cшное тождество: a[i]==*(a+i)==i[a]). > Если номер один я могу отнести к интерфейсу, то каким боком туда > остальные пункты попали?
Назовите, пожалуйста, язык в котором остальные пункты выполняются. Язык
D в пример не приводить.
> Номер один же является скорее недостатком, нежели преимуществом. В > результате, при неверном импорте, приложения зачастую падают и ошибку > такую диагностировать очень трудно.
Кроме стандартных проблем с разными рантаймами в Винде, я не помню,
чтобы у меня падало именно из-за проблем с голыми именами.
> C>Тем не менее, даже *сейчас* нечем полностью заменить С. Даже у С++ > C>уже есть определнные недостатки по сравнению с С. > Вот с этим согласен, заменить нечем. Традиция. Но это снова не говорит > о том, что низкоуровневые свойства языка можно было бы организовать по > другому.
Да не традиция это! Попробуйте реально написать программу на Паскале для
режима ядра — тогда поймете все достоинства С.
Здравствуйте, Cyberax, Вы писали:
C>Я собственно это и хотел сказать. Адресная арифметика — просто C>незаменимое средство для низкоуровневого программирования, но у нее свои C>недостатки.
ИМХО, тот факт, что низкоуровневые средства языка Си не требуют специального "знака" (вроде IMPORT SYSTEM в Модуле-2 и Обероне), является недостатком языка.
Впрочем, нет желания затевать очередной ((N+1)-й) "языковой" флейм.
P.S.
Что касается самого форума (лекция Вирта), то многие посты выглядят так:
"Мнение Вирта о языках программирования (функциональном программировании и т.д. и т.п.) не совпадает с моим.
Значит, Вирт в этом не разбирается."
Это забавно.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Хоар
Re[13]: Лекция Вирта в политехническом - впечатления
mefrill wrote:
> Ну не знаю. Что такое операция присваивания? Это, на самом деле, две > поледовательных операции: > 1. Прочитать данные из участка памяти, на который ссылается выражение > справа. > 2. Записать прочитанные данные в участок памяти, на который ссылается > выражение слева.
А вот и нет. Скорее всего, присваиваемое число будет уже лежать в
регистре, так что присваивание может быть простым mov'ом из регистра в
память.
А если присваивание идет в цикле, то можно использовать и инструкции
типа "память-в-память" (movsd и т.п.).
А еще в случае с плавучкой — числа могут лежать на стеке математического
сопроцессора.
А еще есть SSE/MMX/Altivec.
А скоро будут cell-процессоры со своими заморочками.
И т.д.
То есть если уж хочется чего-то, более соответствующего реальной
архитектуре компьютера, то ничего простого не получится.
> Ну вот о чем я и писал уже выше. Прямую работу с памятью можно было бы > реализовать по другому, может быть более полно отразив понятия > Фон-Неймановсткой машины.
Современные компьютеры оооочень сильно отличаются от классической
архитектуры Фон-Неймана.
Cyberax,
>> int a[5] = { 0, 1, 2, 3, 4 }; >> как преобразовать данную конструкцию в эквивалент на указателях?
>
> int *a=(int*)alloca(5*sizeof(int));
> int f;
> for (f=0;f<5;f++) a[f]=f;
>
А теперь то же самое в global scope...
> Нет, я знаю, что int a[5] ведет себя не совсем как простой указатель, но > это объяснять мне здесь не хотелось.
Главное что реализованы массивы не через указатели, только индексируются через них.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
AVC,
> Главная проблема с массивами Си в том, что информация об их "массивовости" теряется при выходе из соответствующей области видимости (scope)).
Это другая (валидная) проблема.
> Так что же неверного в утверждении, что массив в Си (вне области видимости его объявления) неотличим от указателя?
То что это не совсем так. Массив "неотличим" только при условии получения и работы с указателем на его первый элемент. Если этого не делать, то отличия останутся. Например, можно оперировать указателем на массив.
> ИМХО, приведенный Вами, Павел, пример и есть не что иное, как syntactic sugar: так, прилепили фичу к указателю.
В таком случае, выразите, пожалуйста, тот пример через указатели.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[14]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Пацак, Вы писали:
П>Да тут дело даже не столько в ошибке..
П>
П>// ... some code
П>while (a=foo()) {
П> boo(a);
П>}
П>// ... some code
П>
П>Глядя на вышеприведенный кусок кода — ты можешь "на глаз" определить, что в нем нет ошибки, и он должен делать именно то, что делает, а не то, что приведено ниже?
Имкнно!
И конечно опытные программисты такие ошибки делают редко. Но достигается это обычно ценой того, что они всячески избегают присвоений во вложенных выражениях и тем, что используют трюки вроде постановки константы первым операндом. Но, к сожалению, это приходит только с годами, и приводит к более длинному и менее читабельному коду, хотя цель создателей языка была ровно противоположная.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Лекция Вирта в политехническом - впечатления
Да, более чем! Я читаю смысл кода, а не как компилятор. И я хочу читать "значение равно десяти", а не "десяти равно значения". Мне вообще не нравится как говорит Ёда.
А ты просто привык к эому убожеству. Кстати, а почему в твоих листингах на Руби я подобного не встречал? Или я просто не обращал внимания?
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Лекция Вирта в политехническом - впечатления
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Альтернатива: включить в своем компиляторе соответствующие предупреждения.
Паш, хорошо что сегодня в твоем компиляторе есть такая возможность.
Вот только в моем ее небыло. Я конечно привык, но хорошем такое не назовешь. Так зачем уродская конструкция которую нужно запрещать вообще попала в язык?
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Лекция Вирта в политехническом - впечатления
M>Во-первых, графическое выражение операции стравнения, так же как и присваивания, противоречит математической интуиции. Исмвол "=" значит в математике именно сравнение, а не какую-либо операцию.
Это спорный вопрос. Во-первых, никого сам оператор не нарягает. Во-вторых, в математике просто нет понятия модификации переменных, так что выражение:
x = 1
можно трактовать как присвоение значения новой переменной, а можно и как утверждение, то "x == 1".
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Лекция Вирта в политехническом - впечатления
Здравствуйте, mefrill, Вы писали:
M>Уже писал об этом. Придумывать костыли для синтаксического свойства языка указывает только на одно: это свойство неудачно.
Однако, как я уже говорил, просто приведение типизации в норму на раз устраняет эту проблему.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.