Перейти к содержанию
    

Скажите, а нужны скобки в этом коде?

 

 return (!x && y) || (x && !y);

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

 

в пользу моего подхода задайте вопрос любому своему знакомому: сколько будет два плюс два умножить на два? почти 99% с первой попытки отвечают 8, хотя правила арифметики знают даже двоечники...

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Затем Вам показали, что В УЧЕБНЫХ целях полезно ПОНЯТЬ, почему 5[a] эквивалентно a[5].

...

Такой код НУЖНО использовать при обучении, для демонстрации области дейстия автоматических переменных.

И... почему? Кто бы объяснил "на пальцах", как работает 5[a]. У классиков я такого не нашел. Про "зачем" не спрашиваю, считаю "незачем". :)

 

Насчет скобок - стараюсь не писать лишние. Мне интереснее в список приоритетов заглянуть. И писать лаконично, "красиво".

Но вот последний Keil в своем редакторе выдает предупреждающие знаки, когда из-за приоритета операций, возможно, получится не то, чего я желаю. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Вот смотрите до чего вы докатились. Вы уже говорите о знаниях как о бацилле. Приравняли ЗНАНИЯ к ЧУМЕ. Средневековье какое-то. Завтра вы начнете книгу K&R жечь на кострах.

 

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

 

Как вы и ваши ученики будут писать прототип функции с одним аргументом, получающей

1) указатель на массив типа int a[10][10];

2) указатель на массив типа int *a[10];

3) указатель на функцию, получающую в качестве аргумента указатель из первого вопроса, а возвращающую указатель из второго вопроса.

 

Надеюсь вы не считаете, что подобные функции никому не нужны?

 

И... почему? Кто бы объяснил "на пальцах", как работает 5[a]. У классиков я такого не нашел. Про "зачем" не спрашиваю, считаю "незачем". :)

Совсем на пальцах

a[5] эквивалентно *(a+5)

От перемены мест слагаемых...

Изменено пользователем igorle

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По поводу 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] - мы именно подчёркиваем, что выбираем конкретный элемент всех массивах, а не просто перебираем массивы с какой-то дальнейшей целью - выбор какого-то элемента, как в данном примере. Когда я вижу такую запись, я полагаю, что программист именно хотел сделать акцент этой особенности алгоритма. Мелочь, но к месту. Совершенно согласен, что профессиональный квалифицированный программист должен безо всякого напряжения и ломки воспринимать такого рода конструкции. Признаюсь, что на заре освоения С, когда столкнулся в первый раз с такой записью, испытал лёгкий культурный шок. :) Это мотивировало помедитировать над этой темой, через некоторое время всё встало на свои места.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Совсем на пальцах

a[5] эквивалентно *(a+5)

От перемены мест слагаемых...

... получаем *(5+a). А дальше? "Еще нежнее..."

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

 

... получаем *(5+a). А дальше? "Еще нежнее..."

 

Инкремент указателя сдвигает указатель на следующий элемент массива.

Написав a[5], мы говорим сложи a и 5, и верни нам значение, которое хранится в полученом адресе

Написав 5[a], мы говорим сложи 5 и a, и верни нам значение, которое хранится в полученом адресе

 

Поскольку 5+a и a+5 дают одинаковый результат, то и получается, что конструкции эквивалентны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Написав a[5], мы говорим сложи a и 5, и верни нам значение, которое хранится в полученом адресе

Написав 5[a], мы говорим сложи 5 и a, и верни нам значение, которое хранится в полученом адресе

Да, так понятно. И понятно, что так вычисляется при работе компилятора. Непонятно, почему это допускается, ради простоты реализации? Ведь a[] - это массив, а 5[] - бред. Можно задать массив a[5], но нельзя задать 5[a]. Это - что-то, именуемое "хаком".

Таким образом, задать 5[a] нельзя, а использовать можно. И где логика? :)

P.S. начинаю относиться к K & R, как к шарлатанам. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, так понятно. И понятно, что так вычисляется при работе компилятора. Непонятно, почему это допускается, ради простоты реализации? Ведь a[] - это массив, а 5[] - бред. Можно задать массив a[5], но нельзя задать 5[a]. Это - что-то, именуемое "хаком".

Таким образом, задать 5[a] нельзя, а использовать можно. И где логика? :)

P.S. начинаю относиться к K & R, как к шарлатанам. :)

Исходный код делится на "кирпичики". Оператор "[]" при использовании описывается где-то так:

операнды должны быть один - типа поинтер, другой - целое

Сложить операнды. (результатом будет поинтер)

выполнить опрацию разыменовывания.

 

Это логика, но отнюдь не шарлатанство. Объявление переменной и применение переменной - разные вещи.

Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста.

 

Кстати, недостаток логики повергает многих в задумчивость, когда просишь сказать чему равен (-11)%10. А у классиков здесь все четко и просто.

 

 

...Ведь a[] - это массив, а 5[] - бред...

Ээээ. Дело привычки.

Вспомнил, как давным давно (а я весьма стар), когда мы начинали изучать программирование, мой однокурсник возмущался, что нельзя писать x=x+10, потому что это бред и не может быть верным ни при каком значении x :biggrin:

Уже сегодня вечером вы, не задумываясь, будете думать

Ведь a[] - это массив, а 5[] - это шестой элемент массива.

Изменено пользователем igorle

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста.

Не смущало. Но, после прочтения данной темы, возникла мысль - а почему для взятия адреса не использовали, например, символ @. @a - красота.

 

Кстати, недостаток логики повергает многих в задумчивость, когда просишь сказать чему равен (-11)%10. А у классиков здесь все четко и просто.

Цитирую классиков K&R, 2-е издание, белая, с синей буквой C, стр. 55

Направление округления при операции / или знак результата при операции % для отрицательных аргументов зависят от системы...

Так чему равен результат? :) Боюсь ошибиться, 1? -1?

 

Уже сегодня вечером вы, не задумываясь, будете думать

Ведь a[] - это массив, а 5[] - это шестой элемент массива.

Прекращайте шутить, и без того все страньше и страньше. Хотя... смотря как считать, начиная с "нулевого" или с "первого". Здесь и классики иногда путаются в терминах.

 

операнды должны быть один - типа поинтер, другой - целое

Сложить операнды. (результатом будет поинтер)

И чему равен поинтер на 5? :rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитирую классиков K&R, 2-е издание, белая, с синей буквой C, стр. 55

Вот видите как полезно читать классиков. Суть в том, что сумма результата деления умноженного на делитель и остатка от деления дают исходное число. Таким образом результат будет или -1, или 9. В зависимости от платформы. Кстати, мне пока не попадалась платформа, где округление для отрицательных чисел шло в минус. В смысле -11/10 может на рекоторых платформах давать -2. Тогда остаток от деления будет 9. Но на всех платформах, где я проверял, результат от деления был -1, соответственно остаток от деления - тоже -1.

 

И чему равен поинтер на 5? :rolleyes:

5 - это не указатель. Это целое. Которое будет складываться с указателем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот смотрите до чего вы докатились. Вы уже говорите о знаниях как о бацилле. Приравняли ЗНАНИЯ к ЧУМЕ. Средневековье какое-то. Завтра вы начнете книгу K&R жечь на кострах.
как раз наоборот, это вы дальше сказанного К&R не желаете категорически поглядеть, это вы современные инквизиторы, готовые ради догмы закопать кого угодно!

 

я показал нонсенс, когда ЛОГИЧЕСКИЕ операции делаются АРИФМЕТИЧЕСКИМИ операторами, причем для этого используется еще и ЛОГИЧЕСКАЯ операция. получается каша, названная красивым подходом. это по ВАШЕЙ догме. я предложил не путать теплое с мягким, и в ЛОГИЧЕСКИХ ВЫРАЖЕНИЯХ пользоваться ЛОГИЧЕСКИМИ операторами - это хоть и не выходит за рамки канонов, но почему-то вас возмутило со страшной силой.

 

 

спустя некоторое время появляются люди, которые ОБОСНОВЫВАЮТ лучшим отражением ИДЕИ использование странных записей, и их слова все воспринимают "положительно". вопрос знатокам: почему, когда я предлагаю записывать выражения так, чтобы они лучше отражали суть, все поднимают меня на вилы?! ответ один - догма есть догма, а кто не с нею, тот против всех.

 

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

 

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

 

объявив обычный многомерный массив, вы не сделали ничего такого, что сделает запись a[n][5] менее понятной - взяли 5-й элемент n-го массива. гораздо больше пользы в понимании закладываемого смысла сыграло бы нормальное поименование массивов и т.п.

 

я привел реальный пример, что стремление к извращениям в кодировании приводит к ухудшению результатов - почему никто не среагировал? может у кого есть возможность протестировать аналогичный пример для ARMов - это принесло бы больше пользы в поднятом вопросе, чем все эти бредни про 5[a]...

 

Вас не смущает, что звездочка может означать и умножение, и указатель, и разыменовывание в зависимости от контекста.
меня смущает. я вижу в этом одно из самых слабых мест Си - контекстнозависимая неоднозначность символов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

компилируем WinAVR 20100110
Вы бы ещё чего пораритетнее нашли...

WinAVR почил 3 года назад. Так и будете его всю жизнь в пример ставить?

Покажите как это сейчас выглядит например на gcc-(4.7.2 ... 4.8.0).

И если не понравится результат, так заполните баг репорт и хоть как-то помогите развитию продукта вместо пустого хая.

Или страшно? Профессионал млин...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы бы ещё чего пораритетнее нашли...

WinAVR почил 3 года назад. Так и будете его всю жизнь в пример ставить? Покажите как это сейчас выглядит (на gcc-(4.7.2 ... 4.8.0).

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

успехов вам в лаконизме! ;)
Давайте возьмем другой проц, и уровень оптимизаций побольше

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:

Код сильно потощал, но отношение размеров (не в пользу первого варианта) осталось :biggrin:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

XVR, вы, пожалуйста, сообщите ВЕСЬ размер кода, потому как даже под WinAVR в моем варианте ассемблерный листинг функций давал ВАШ результат, а вот общий размер, который включает в том числе подготовительные действия по вызову функций, оказался совсем иным.

 

что касается взгляда на логику, то по-моему, двух мнений тут быть не может: операция ^ арифметическая битовая, операция ! -логическая. в одном выражении смешаны два вида операций. математика такого не допускает: логические выражения не смешиваются с арифметическими. в Си этот принцип может быть нарушен (по стандарту), и в этом я вижу нарушение логики. запись выражения для ЛОГИЧЕСКОГО XOR только при помощи исключительно ЛОГИЧЕСКИХ операторов мне кажется абсолютно логичной, и позволяет привести математическую логику в русло стандарта Си. мой вариант как раз и отражает суть булевой алгебры преобразования логических функций - помните это? в моем варианте записи все сделано как раз в строгом соответствии с этим, и ни один пункт стандарта Си не нарушен - два плюса против одного вашего :)

 

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

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

 

P.S. а что этоу вас за опкод какой-то странный в первом листинге второго варианта - rep? вроде как это префикс-повторитель, и тут он как бы неуместен...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...