C90 (gcc), 46 байтов
r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}
Ввод осуществляется через аргументы командной строки (одно целое число на аргумент), вывод через код завершения .
Попробуйте онлайн!
Как это устроено
r является глобальной переменной. Его тип по умолчанию равен int и, будучи глобальным, значение по умолчанию равно 0 .
Аргумент функции c по умолчанию также имеет значение int . Он будет содержать целое число n + 1 для массивов из n логических значений ; первым аргументом main всегда является путь к исполняемому файлу.
Аргумент функции v объявлен как int**
. Фактический тип v будет таким char**
, но поскольку мы будем проверять только младший значащий бит каждого аргумента, чтобы разделить символы 0 (кодовая точка 48 ) и 1 (кодовая точка 49 ), это не будет иметь значения для little-endian машины.
Цикл while уменьшает значение c и сравнивает его с 0 . Как только c достигнет 0 , мы вырвемся из цикла. Это необходимо только в том случае, если массив не содержит 0 .
Пока 0<--c
возвращается 1 , мы берем c- й аргумент командной строки ( v[c]
) и извлекаем его первый символ с помощью разыменования указателя ( *
). Мы берем побитовое AND логического 0<--c
и кодовую точку символа (и три мусорных байта, которые следуют за ним), поэтому условие вернет 0, как только встретится 0 , выходя из цикла.
В оставшемся случае, в то время как аргументы командной строки 1 , r++
приращения г на 1 , таким образом , подсчет количества завершающих 1 «с.
Наконец, c=r
сохраняет вычисленное значение r в c . С настройками по умолчанию компилятор оптимизирует и удаляет назначение; это фактически генерирует movl %eax, -4(%rbp)
инструкцию. Так как ret
возвращает значение регистра EAX, это генерирует желаемый результат.
Обратите внимание, что этот код не работает с C99, который возвращает 0 из основного, если достигнут конец основного .
01100
?