ARV 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Скажите, а нужны скобки в этом коде? return (!x && y) || (x && !y); формально - не нужны. боюсь, меня заплюют, как обычно, но я ставлю скобки везде, где они позволяют визуально выделить "полезные" части выражения, чтобы, как обычно, никто не напрягал лишний раз голову, вспоминая о приоритетах операций. в пользу моего подхода задайте вопрос любому своему знакомому: сколько будет два плюс два умножить на два? почти 99% с первой попытки отвечают 8, хотя правила арифметики знают даже двоечники... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Затем Вам показали, что В УЧЕБНЫХ целях полезно ПОНЯТЬ, почему 5[a] эквивалентно a[5]. ... Такой код НУЖНО использовать при обучении, для демонстрации области дейстия автоматических переменных. И... почему? Кто бы объяснил "на пальцах", как работает 5[a]. У классиков я такого не нашел. Про "зачем" не спрашиваю, считаю "незачем". :) Насчет скобок - стараюсь не писать лишние. Мне интереснее в список приоритетов заглянуть. И писать лаконично, "красиво". Но вот последний Keil в своем редакторе выдает предупреждающие знаки, когда из-за приоритета операций, возможно, получится не то, чего я желаю. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба никто на планете Земля не желает, чтобы бацилла чумы существовала наравне с человеком, хотя это естественный биологический вид, теоретически имеющий право на существование. бациллу чумы уничтожили - и все стали только счастливее. Вот смотрите до чего вы докатились. Вы уже говорите о знаниях как о бацилле. Приравняли ЗНАНИЯ к ЧУМЕ. Средневековье какое-то. Завтра вы начнете книгу K&R жечь на кострах. Интересно, а как вы, не обремененный лишними знаниями, будете писать несложные, но выходящие за рамки банальных знаний функции. Как вы и ваши ученики будут писать прототип функции с одним аргументом, получающей 1) указатель на массив типа int a[10][10]; 2) указатель на массив типа int *a[10]; 3) указатель на функцию, получающую в качестве аргумента указатель из первого вопроса, а возвращающую указатель из второго вопроса. Надеюсь вы не считаете, что подобные функции никому не нужны? И... почему? Кто бы объяснил "на пальцах", как работает 5[a]. У классиков я такого не нашел. Про "зачем" не спрашиваю, считаю "незачем". :) Совсем на пальцах a[5] эквивалентно *(a+5) От перемены мест слагаемых... Изменено 24 марта, 2013 пользователем igorle Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба По поводу a[5] vs 5[a] - зтого специально никто не добивался. Это всего лишь побочное следствие определения семантики языка. Очевидно использовать это в реальных программах смысла никакого нет. Согласился бы с более мягкой формулировкой: "...использовать это в реальных программах настоятельной необходимости нет". Потому что, иногда такая запись, имхо, лучше акцентирует замысел. Например, есть несколько массивов, и надо пройтись по энному - скажем, пятому - элементу всех массивов: #include <stdio.h> int A1[10] = { 1,2,3,4,5,6,7,8,9,0 }; int A2[10] = { 11,22,33,44,55,66,77,88,99,10 }; int A3[10] = { 111,222,333,444,555,666,777,888,999,100 }; int *p[] = { A1, A2, A3 }; int main() { for(int i = 0; i < sizeof(p)/sizeof(p[0]); ++i) { printf("%d\n", 5[p[i]]); printf("%d\n", p[i][5]); } return 0; } Вывод, очевидно, работает одинаково: 6 6 66 66 666 666 но запись 5[p], имхо, заметно выразительнее в данном контексте, чем p[5] - мы именно подчёркиваем, что выбираем конкретный элемент всех массивах, а не просто перебираем массивы с какой-то дальнейшей целью - выбор какого-то элемента, как в данном примере. Когда я вижу такую запись, я полагаю, что программист именно хотел сделать акцент этой особенности алгоритма. Мелочь, но к месту. Совершенно согласен, что профессиональный квалифицированный программист должен безо всякого напряжения и ломки воспринимать такого рода конструкции. Признаюсь, что на заре освоения С, когда столкнулся в первый раз с такой записью, испытал лёгкий культурный шок. :) Это мотивировало помедитировать над этой темой, через некоторое время всё встало на свои места. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Совсем на пальцах a[5] эквивалентно *(a+5) От перемены мест слагаемых... ... получаем *(5+a). А дальше? "Еще нежнее..." Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Согласился бы с более мягкой формулировкой: "...использовать это в реальных программах настоятельной необходимости нет". Потому что, иногда такая запись, имхо, лучше акцентирует замысел. Например, есть несколько массивов, и надо пройтись по энному - скажем, пятому - элементу всех массивов: Очень красивый пример. Действительно, такой код читабельнее. Как и в случае с ксором - взгляд сразу выхватывает суть. ... получаем *(5+a). А дальше? "Еще нежнее..." Инкремент указателя сдвигает указатель на следующий элемент массива. Написав a[5], мы говорим сложи a и 5, и верни нам значение, которое хранится в полученом адресе Написав 5[a], мы говорим сложи 5 и a, и верни нам значение, которое хранится в полученом адресе Поскольку 5+a и a+5 дают одинаковый результат, то и получается, что конструкции эквивалентны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Написав a[5], мы говорим сложи a и 5, и верни нам значение, которое хранится в полученом адресе Написав 5[a], мы говорим сложи 5 и a, и верни нам значение, которое хранится в полученом адресе Да, так понятно. И понятно, что так вычисляется при работе компилятора. Непонятно, почему это допускается, ради простоты реализации? Ведь a[] - это массив, а 5[] - бред. Можно задать массив a[5], но нельзя задать 5[a]. Это - что-то, именуемое "хаком". Таким образом, задать 5[a] нельзя, а использовать можно. И где логика? :) P.S. начинаю относиться к K & R, как к шарлатанам. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба Да, так понятно. И понятно, что так вычисляется при работе компилятора. Непонятно, почему это допускается, ради простоты реализации? Ведь a[] - это массив, а 5[] - бред. Можно задать массив a[5], но нельзя задать 5[a]. Это - что-то, именуемое "хаком". Таким образом, задать 5[a] нельзя, а использовать можно. И где логика? :) P.S. начинаю относиться к K & R, как к шарлатанам. :) Исходный код делится на "кирпичики". Оператор "[]" при использовании описывается где-то так: операнды должны быть один - типа поинтер, другой - целое Сложить операнды. (результатом будет поинтер) выполнить опрацию разыменовывания. Это логика, но отнюдь не шарлатанство. Объявление переменной и применение переменной - разные вещи. Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста. Кстати, недостаток логики повергает многих в задумчивость, когда просишь сказать чему равен (-11)%10. А у классиков здесь все четко и просто. ...Ведь a[] - это массив, а 5[] - бред... Ээээ. Дело привычки. Вспомнил, как давным давно (а я весьма стар), когда мы начинали изучать программирование, мой однокурсник возмущался, что нельзя писать x=x+10, потому что это бред и не может быть верным ни при каком значении x Уже сегодня вечером вы, не задумываясь, будете думать Ведь a[] - это массив, а 5[] - это шестой элемент массива. Изменено 24 марта, 2013 пользователем igorle Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста. Не смущало. Но, после прочтения данной темы, возникла мысль - а почему для взятия адреса не использовали, например, символ @. @a - красота. Кстати, недостаток логики повергает многих в задумчивость, когда просишь сказать чему равен (-11)%10. А у классиков здесь все четко и просто. Цитирую классиков K&R, 2-е издание, белая, с синей буквой C, стр. 55 Направление округления при операции / или знак результата при операции % для отрицательных аргументов зависят от системы... Так чему равен результат? :) Боюсь ошибиться, 1? -1? Уже сегодня вечером вы, не задумываясь, будете думать Ведь a[] - это массив, а 5[] - это шестой элемент массива. Прекращайте шутить, и без того все страньше и страньше. Хотя... смотря как считать, начиная с "нулевого" или с "первого". Здесь и классики иногда путаются в терминах. операнды должны быть один - типа поинтер, другой - целое Сложить операнды. (результатом будет поинтер) И чему равен поинтер на 5? :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igorle 0 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Цитирую классиков K&R, 2-е издание, белая, с синей буквой C, стр. 55 Вот видите как полезно читать классиков. Суть в том, что сумма результата деления умноженного на делитель и остатка от деления дают исходное число. Таким образом результат будет или -1, или 9. В зависимости от платформы. Кстати, мне пока не попадалась платформа, где округление для отрицательных чисел шло в минус. В смысле -11/10 может на рекоторых платформах давать -2. Тогда остаток от деления будет 9. Но на всех платформах, где я проверял, результат от деления был -1, соответственно остаток от деления - тоже -1. И чему равен поинтер на 5? :rolleyes: 5 - это не указатель. Это целое. Которое будет складываться с указателем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Вот смотрите до чего вы докатились. Вы уже говорите о знаниях как о бацилле. Приравняли ЗНАНИЯ к ЧУМЕ. Средневековье какое-то. Завтра вы начнете книгу K&R жечь на кострах.как раз наоборот, это вы дальше сказанного К&R не желаете категорически поглядеть, это вы современные инквизиторы, готовые ради догмы закопать кого угодно! я показал нонсенс, когда ЛОГИЧЕСКИЕ операции делаются АРИФМЕТИЧЕСКИМИ операторами, причем для этого используется еще и ЛОГИЧЕСКАЯ операция. получается каша, названная красивым подходом. это по ВАШЕЙ догме. я предложил не путать теплое с мягким, и в ЛОГИЧЕСКИХ ВЫРАЖЕНИЯХ пользоваться ЛОГИЧЕСКИМИ операторами - это хоть и не выходит за рамки канонов, но почему-то вас возмутило со страшной силой. спустя некоторое время появляются люди, которые ОБОСНОВЫВАЮТ лучшим отражением ИДЕИ использование странных записей, и их слова все воспринимают "положительно". вопрос знатокам: почему, когда я предлагаю записывать выражения так, чтобы они лучше отражали суть, все поднимают меня на вилы?! ответ один - догма есть догма, а кто не с нею, тот против всех. что касается всяких загадочных функций со странными указателями, то я поступил бы очень просто: для каждого нужного места ввел бы новый тип, и все свелось бы к объявлению простой функции с нормально читаемым видом. я ведь просил вас, знактоков, изобразить вашу оптимальную запись для подобного примера - и где она?! игнорировать слабое место в собственной догме - это очень похоже на борцов за чистоту веры! приведенный пример с массивами показывает только полное непонимание пользы продемонстрированного подхода. запись, которая совершенно ничем не лучше, выдается за таковую. то есть возможность есть, даже применить ее порой удается, но зачем - оставется в тумане. объявив обычный многомерный массив, вы не сделали ничего такого, что сделает запись a[n][5] менее понятной - взяли 5-й элемент n-го массива. гораздо больше пользы в понимании закладываемого смысла сыграло бы нормальное поименование массивов и т.п. я привел реальный пример, что стремление к извращениям в кодировании приводит к ухудшению результатов - почему никто не среагировал? может у кого есть возможность протестировать аналогичный пример для ARMов - это принесло бы больше пользы в поднятом вопросе, чем все эти бредни про 5[a]... Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста.меня смущает. я вижу в этом одно из самых слабых мест Си - контекстнозависимая неоднозначность символов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 25 марта, 2013 Опубликовано 25 марта, 2013 · Жалоба компилируем WinAVR 20100110Вы бы ещё чего пораритетнее нашли... WinAVR почил 3 года назад. Так и будете его всю жизнь в пример ставить? Покажите как это сейчас выглядит например на gcc-(4.7.2 ... 4.8.0). И если не понравится результат, так заполните баг репорт и хоть как-то помогите развитию продукта вместо пустого хая. Или страшно? Профессионал млин... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 25 марта, 2013 Опубликовано 25 марта, 2013 · Жалоба Вы бы ещё чего пораритетнее нашли... WinAVR почил 3 года назад. Так и будете его всю жизнь в пример ставить? Покажите как это сейчас выглядит (на gcc-(4.7.2 ... 4.8.0). почил или нет, а я пользуюсь, и пока не сожалею. у вас есть свежак - вот вы и покажите, как стало хорошо и оптимально компилироваться то, что противоречит логике, об этом я и попросил Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 25 марта, 2013 Опубликовано 25 марта, 2013 · Жалоба успехов вам в лаконизме! ;)Давайте возьмем другой проц, и уровень оптимизаций побольше typedef char boo; boo var1(boo x, boo y){ return (!x && y) || (x && !y); } boo var2(boo x, boo y){ return !x ^ !y; } Компилим gcc -O3 (версия gcc - gcc (GCC) 4.1.2 20070115 (SUSE Linux)) Платформа x64 - var1: .LFB2: testb %dil, %dil movl %edi, %edx movl %esi, %ecx jne .L2 testb %sil, %sil movl $1, %eax je .L2 rep; ret .p2align 4,,7 .L2: testb %dl, %dl setne %al testb %cl, %cl sete %dl andl %edx, %eax movzbl %al, %eax ret .LFE2: var2: .LFB3: testb %dil, %dil sete %al testb %sil, %sil sete %dl xorl %edx, %eax movsbl %al,%eax ret .LFE3: Разницу в количестве команд видите? Если собрать под 32 бита (в x86) - то получается то же самое var1: pushl %ebp movl %esp, %ebp movzbl 8(%ebp), %edx movzbl 12(%ebp), %ecx testb %dl, %dl jne .L2 testb %cl, %cl movl $1, %eax je .L2 popl %ebp ret .p2align 4,,7 .L2: testb %dl, %dl setne %al testb %cl, %cl sete %dl popl %ebp andl %edx, %eax movzbl %al, %eax ret var2: pushl %ebp movl %esp, %ebp cmpb $0, 8(%ebp) sete %al cmpb $0, 12(%ebp) popl %ebp sete %dl xorl %edx, %eax movsbl %al,%eax ret спустя некоторое время появляются люди, которые ОБОСНОВЫВАЮТ лучшим отражением ИДЕИ использование странных записей, и их слова все воспринимают "положительно". вопрос знатокам: почему, когда я предлагаю записывать выражения так, чтобы они лучше отражали суть, все поднимают меня на вилы?! ответ один - догма есть догма, а кто не с нею, тот против всех.Ответ неверный. 'лучше отражали суть' именно оригинал, а не ваш вариант. И 'странной записью' выглядит именно ваш вариант. А вы это упрямо игнорируете и с не меньшим упорством ищете заговор и догматиков. В общем как говорится 'на вкус и цвет товарищей нет'. У каждого может быть свой собственный взгляд на то, что наиболее естественно и правильно. Если хотите установить истину - сделайте опрос, какая версия этой конструкции покажется читателям более естественной :rolleyes: PS. Собрал ваш тест на 4.7.2 (64 бита) var1: .LFB0: .cfi_startproc testb %sil, %sil jne .L11 .L5: testb %sil, %sil sete %al testb %dil, %dil setne %dl andl %edx, %eax ret .p2align 4,,10 .p2align 3 .L11: testb %dil, %dil movl $1, %eax jne .L5 rep ret .cfi_endproc .LFE0: var2: .LFB1: .cfi_startproc testb %sil, %sil sete %al testb %dil, %dil sete %dl xorl %edx, %eax ret .cfi_endproc .LFE1: Код сильно потощал, но отношение размеров (не в пользу первого варианта) осталось Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 25 марта, 2013 Опубликовано 25 марта, 2013 · Жалоба XVR, вы, пожалуйста, сообщите ВЕСЬ размер кода, потому как даже под WinAVR в моем варианте ассемблерный листинг функций давал ВАШ результат, а вот общий размер, который включает в том числе подготовительные действия по вызову функций, оказался совсем иным. что касается взгляда на логику, то по-моему, двух мнений тут быть не может: операция ^ арифметическая битовая, операция ! -логическая. в одном выражении смешаны два вида операций. математика такого не допускает: логические выражения не смешиваются с арифметическими. в Си этот принцип может быть нарушен (по стандарту), и в этом я вижу нарушение логики. запись выражения для ЛОГИЧЕСКОГО XOR только при помощи исключительно ЛОГИЧЕСКИХ операторов мне кажется абсолютно логичной, и позволяет привести математическую логику в русло стандарта Си. мой вариант как раз и отражает суть булевой алгебры преобразования логических функций - помните это? в моем варианте записи все сделано как раз в строгом соответствии с этим, и ни один пункт стандарта Си не нарушен - два плюса против одного вашего :) я бы мог сделать опрос, но в своей формулировке: какая из этих конструкций более соответствует здравому смыслу? я ведь не о Си пекусь, а том, как писать программы в соответствии со здравым смыслом, т.е. так, чтобы ни один закон не нарушить и при этом программу смог бы понять любой человек, обладаюсщий этим самым здравым смыслом, а не только вызубривший стандарт конкретного языка. хотя судя по уже состоявшемуся обмену мнений, результат опроса прогнозируем по причине нелюбви к логике здравого смысла у очень многих :) P.S. а что этоу вас за опкод какой-то странный в первом листинге второго варианта - rep? вроде как это префикс-повторитель, и тут он как бы неуместен... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться