Вы не можете сделать это, насколько я знаю, используя printf. Очевидно, вы могли бы написать вспомогательный метод для достижения этой цели, но это не похоже на направление, в котором вы хотите идти.
Ян Р
Для этого не существует предопределенного формата. Вам необходимо преобразовать его в строку, а затем распечатать строку.
Не входит в стандартную библиотеку ANSI C - если вы пишете переносимый код, самый безопасный способ - это создать свой собственный.
Tomlogic
Одно утверждение стандартное и универсальное (для любого типа Integral любой длины) решение преобразования в двоичную строку на C ++: stackoverflow.com/a/31660310/1814353
Вам нужны все лишние цитаты, к сожалению. Этот подход несет риски эффективности макросов (не передавайте функцию в качестве аргумента BYTE_TO_BINARY), но избегает проблем с памятью и множественных вызовов strcat в некоторых других предложениях здесь.
И имеет преимущество также в том, что его можно вызывать несколько раз, а printfте, у кого нет staticбуферов.
Патрик Шлютер
4
Я взял на себя смелость изменить %dк %c, потому что оно должно быть еще быстрее ( %dдолжно выполнить digit-> обугленного преобразования, а %cпросто выводит аргумент
Обратите внимание, что этот подход не является дружественным к стеку. Предполагая, intчто в системе 32-битное значение, для печати одного 32-битного значения потребуется пространство для 32 * 4-байтовых значений; всего 128 байтов. Что, в зависимости от размера стека, может быть или не быть проблемой.
user694733
1
важно добавить скобки вокруг байта в макросе, иначе вы можете столкнуться с проблемами при отправке операции BYTE_TO_BINARY (a | b) -> a | b & 0x01! = (a | b) & 0x01
Иван Гофман
203
Печать двоичного кода для любого типа данных
//assumes little endianvoid printBits(size_tconst size,voidconst*const ptr){unsignedchar*b =(unsignedchar*) ptr;unsignedchar byte;int i, j;for(i=size-1;i>=0;i--){for(j=7;j>=0;j--){
byte =(b[i]>> j)&1;
printf("%u", byte);}}
puts("");}
тестовое задание
int main(int argv,char* argc[]){int i =23;uint ui = UINT_MAX;float f =23.45f;
printBits(sizeof(i),&i);
printBits(sizeof(ui),&ui);
printBits(sizeof(f),&f);return0;}
Может ли кто-нибудь рассказать о логике этого кода?
JII
2
Возьмите каждый байт ptr(внешний цикл); затем для каждого бита текущий байт (внутренний цикл) маскирует байт текущим битом ( 1 << j). Сдвиньте это вправо, получив в результате байт, содержащий 0 ( 0000 0000b) или 1 ( 0000 0001b). Распечатать полученный байт printf с форматом %u. НТН.
Nielsbot
1
@ ZX9 Обратите внимание, что предлагаемый код используется >с вашим комментарием, size_tа не с ним, >=чтобы определить, когда завершить цикл.
chux - Восстановить Монику
3
@ ZX9 Тем не менее полезный оригинальный комментарий ваших , как кодерам действительно нужно быть осторожными , принимая во внимание случая использования Края >и >=с беззнаковыми типами. 0это случай без знака и обычно встречается, в отличие от математики со знаком и менее распространенным INT_MAX/INT_MIN.
chux - Восстановить Монику
151
Вот быстрый взлом, чтобы продемонстрировать методы, чтобы делать то, что вы хотите.
#include<stdio.h>/* printf */#include<string.h>/* strcat */#include<stdlib.h>/* strtol */constchar*byte_to_binary
(int x
){staticchar b[9];
b[0]='\0';int z;for(z =128; z >0; z >>=1){
strcat(b,((x & z)== z)?"1":"0");}return b;}int main
(void){{/* binary string to int */char*tmp;char*b ="0101";
printf("%d\n", strtol(b,&tmp,2));}{/* byte to binary string */
printf("%s\n", byte_to_binary(5));}return0;}
Это, безусловно, менее «странно», чем обычная запись escape-перегрузки для printf. Это также легко понять для разработчика, не знакомого с кодом.
Furious Coder
43
Несколько изменений: strcatэто неэффективный метод добавления одного символа в строку на каждом проходе цикла. Вместо этого добавьте char *p = b;и замените внутренний цикл на *p++ = (x & z) ? '1' : '0'. zдолжен начинаться с 128 (2 ^ 7) вместо 256 (2 ^ 8). Рассмотрите возможность обновления, чтобы получить указатель на используемый буфер (для безопасности потока), аналогично inet_ntoa().
Tomlogic
3
@EvilTeach: Вы сами используете троичный оператор в качестве параметра strcat()! Я согласен, что strcatэто, вероятно, легче понять, чем постинкрементный разыменованный указатель для назначения, но даже начинающим нужно знать, как правильно использовать стандартную библиотеку. Возможно, использование индексированного массива для присваивания было бы хорошей демонстрацией (и на самом деле будет работать, так bкак не сбрасывается на все нули при каждом вызове функции).
Tomlogic
3
Случайный: двоичный буфер char является статическим и очищается от всех нулей в назначении. Это очистит его только при первом запуске, а после этого не очистит, а вместо этого использует последнее значение.
markwatson
8
Кроме того , это должно документально подтвердить , что предыдущий результат будет недействительным после повторного вызова функции, поэтому абоненты не должны пытаться использовать его как это: printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4)).
Пауло Эберманн
84
Обычно в glibc нет спецификатора двоичного преобразования.
Можно добавить пользовательские типы преобразования в семейство функций printf () в glibc. Смотрите register_printf_function для подробностей. Вы можете добавить пользовательское преобразование% b для собственного использования, если оно упрощает код приложения, чтобы сделать его доступным.
Вот пример того, как реализовать пользовательские форматы printf в glibc.
Я всегда писал свой собственный v [snf] printf () для ограниченных случаев, когда мне нужны были разные радиксы: я так рад, что просмотрел это.
Джейми
3
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]Существует новая функция , чтобы сделать то же самое, но: register_printf_specifier(). Пример нового использования можно найти здесь: codereview.stackexchange.com/q/219994/200418
Cacahuete Frito
47
Вы можете использовать небольшой стол, чтобы улучшить скорость 1 . Подобные методы полезны во встроенном мире, например, для инвертирования байта:
Выведите наименее значимый бит и сдвиньте его справа. Делая это, пока целое число не станет равным нулю, печатается двоичное представление без начальных нулей, но в обратном порядке. Используя рекурсию, порядок можно исправить довольно легко.
ошибка: слишком мало аргументов для вызова функции, ожидается 2, есть 1 putc ((число & 1)? '1': '0');
Корай Тугай
@KorayTugay Спасибо за указание на это. Я исправил вызов функции и добавил демо.
Данияр
6
Вы также должны использовать целое число без знака, потому что когда заданное число отрицательно, функция входит в бесконечный рекурсивный вызов.
Puffy
Более эффективный подход, поскольку в ASCII '0' + 1 = '1':putc('0'+(number&1), stdout);
Роджер Дуек
22
На основании ответа @William Уайта, это макрос , который обеспечивает int8, 16, 32& 64версии, повторное использование в INT8макрос , чтобы избежать повторения.
Да, вы можете сделать это. Но это действительно плохой дизайн. Даже если у вас нет потоков или повторного входа, вызывающая сторона должна знать, что статический буфер используется повторно, и такие вещи char *a = binary_fmt(x), *b = binary_fmt(y);не будут работать так, как ожидалось. Принуждение вызывающей стороны к пропуску буфера приводит к требованию хранения; вызывающий, конечно, может свободно использовать статический буфер, если это действительно необходимо, и тогда повторное использование этого же буфера становится явным. Также обратите внимание, что в современных PIC ABI статические буферы обычно требуют больше кода для доступа, чем буферы в стеке.
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ICE
8
Это все еще плохой дизайн. Это требует дополнительного шага копирования в этих случаях, и это не менее дорого, чем предоставление вызывающей стороне буфера даже в тех случаях, когда копирование не требуется. Использование статического хранилища - просто плохая идиома.
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ICE
3
Необходимость загрязнения пространства имен препроцессора или таблицы переменных символов ненужным дополнительным именем, которое необходимо использовать для правильного определения размера хранилища, которое должно быть выделено каждым вызывающим абонентом, и принуждение каждого вызывающего абонента знать это значение и выделять необходимое количество хранилище - плохой дизайн, когда более простое решение для локального хранения функций будет достаточным для большинства целей и задач, и когда простой вызов strdup () покрывает 99% остального использования.
Грег А. Вудс
5
Здесь мы собираемся не согласиться. Я не вижу, как добавление одного ненавязчивого символа препроцессора может привести к серьезному ограничению вариантов использования, созданию интерфейса с ошибками, резервированию постоянного хранилища на время программы для временного значения и созданию худшего кода для большинства современные платформы.
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ICE
5
Я не защищаю микрооптимизацию без причины (например, измерения). Но я думаю, что производительность, даже если она находится в масштабе микро-усиления, стоит упомянуть, когда она идет в качестве бонуса наряду с принципиально превосходным дизайном.
Понятнее, если вы используете '1'и '0'вместо 49и 48в своей троичной. Кроме того, bдлина должна быть 9 символов, чтобы последний символ оставался нулевым терминатором.
Tomlogic
Также B необходимо каждый раз инициализировать.
EvilTeach
2
Нет , если вы изменить некоторые из них : 1. добавить пространства для окончательной нулевого: static char b[9] = {0}2. декларации выйти из цикла: int z,y;3. Добавьте окончательный ноль: b[y] = 0. Таким образом, реинитализация не требуется.
Kobor42
1
Хорошее решение. Я бы изменил кое-что. Т.е. возвращаясь в строку назад, чтобы ввод любого размера мог быть обработан правильно.
Работает для любого типа размера и для подписанных и беззнаковых целых. '& 1' необходим для обработки подписанных целых, поскольку сдвиг может расширять подпись.
Есть так много способов сделать это. Вот супер простой способ печати 32-битных или n-битных данных из 32-битного типа со знаком или без знака (не помещая отрицательный знак, если подписан, просто печатая фактические биты) и без возврата каретки. Обратите внимание, что я уменьшается до сдвига битов:
Как насчет возврата строки с битами для хранения или печати позже? Вы можете либо выделить память и вернуть ее, и пользователь должен освободить ее, либо вы вернете статическую строку, но она будет засорена при повторном вызове или другим потоком. Оба метода показаны:
// memory allocated string returned which needs to be freedchar*pstr = int_to_bitstring_alloc(0x97e50ae6,17);
printf("bits = 0b%s\n", pstr);
free(pstr);// no free needed but you need to copy the string to save it somewhere elsechar*pstr2 = int_to_bitstring_static(0x97e50ae6,17);
printf("bits = 0b%s\n", pstr2);
@JanusTroelsen, или намного чище, меньше, ремонтопригоден:char *buffer = malloc(sizeof(*buffer) * 50);
Шахбаз
Почему "% B" будет отличаться от "% b" в этом отношении? В предыдущих ответах говорилось что-то вроде: «В стандартной библиотеке C нет функции форматирования для вывода подобного двоичного файла». и " Некоторые среды выполнения поддерживают"% b ", хотя это не стандарт." ,
Питер Мортенсен
8
Некоторые среды выполнения поддерживают «% b», хотя это не стандарт.
На самом деле это свойство библиотеки времени выполнения C, а не компилятора.
Cjm
7
Этот код должен обрабатывать ваши потребности до 64 бит. Я создал 2 функции pBin & pBinFill. Оба делают одно и то же, но pBinFill заполняет лидирующие пробелы с помощью fillChar. Функция теста генерирует некоторые тестовые данные, а затем распечатывает их, используя функцию.
char* pBinFill(longint x,char*so,char fillChar);// version with fillchar* pBin(longint x,char*so);// version without fill#define kDisplayWidth 64char* pBin(longint x,char*so){char s[kDisplayWidth+1];int i=kDisplayWidth;
s[i--]=0x00;// terminate stringdo{// fill in array from right to left
s[i--]=(x &1)?'1':'0';// determine bit
x>>=1;// shift right 1 bit}while( x >0);
i++;// point to last valid character
sprintf(so,"%s",s+i);// stick it in the temp string stringreturn so;}
char* pBinFill(longint x,char*so,char fillChar){// fill in array from right to leftchar s[kDisplayWidth+1];int i=kDisplayWidth;
s[i--]=0x00;// terminate stringdo{// fill in array from right to left
s[i--]=(x &1)?'1':'0';
x>>=1;// shift right 1 bit}while( x >0);while(i>=0) s[i--]=fillChar;// fill with fillChar
sprintf(so,"%s",s);return so;}
void test(){char so[kDisplayWidth+1];// working buffer for pBinlongint val=1;do{
printf("%ld =\t\t%#lx =\t\t0b%s\n",val,val,pBinFill(val,so,'0'));
val*=11;// generate test data}while(val <100000000);}Output:00000001=0x000001=0b0000000000000000000000000000000100000011=0x00000b=0b0000000000000000000000000000101100000121=0x000079=0b0000000000000000000000000111100100001331=0x000533=0b0000000000000000000001010011001100014641=0x003931=0b0000000000000000001110010011000100161051=0x02751b=0b0000000000000010011101010001101101771561=0x1b0829=0b0000000000011011000010000010100119487171=0x12959c3=0b00000001001010010101100111000011
«#define width 64» конфликтует с stream.h из log4cxx. Пожалуйста, используйте условно случайные определения имен :)
kagali-san
5
@mhambra: вы должны отключить log4cxx за использование такого общего имени, как widthвместо этого!
u0b34a0f6ae
7
Есть ли конвертер printf для печати в двоичном формате?
printf()Семья только в состоянии печатать в базе 8, 10 и 16 с использованием стандартных спецификаторов непосредственно. Я предлагаю создать функцию, которая преобразует число в строку для конкретных потребностей кода.
Для печати на любой базе [2-36]
Все остальные ответы до сих пор имеют по крайней мере одно из этих ограничений.
Используйте статическую память для буфера возврата. Это ограничивает количество раз, которое функция может использоваться в качестве аргумента printf().
Выделите память, требующую кода вызова, чтобы освободить указатели.
Требовать код вызова, чтобы явно предоставить подходящий буфер.
Звоните printf()напрямую. Это обязывает новую функцию к fprintf(), sprintf(), vsprintf()и т.д.
Используйте уменьшенный диапазон целых чисел.
Следующее не имеет ни одного из вышеуказанных ограничений . Это требует C99 или позже и использования "%s". Он использует составной литерал для предоставления буферного пространства. У него нет проблем с несколькими вызовами в printf().
#include<assert.h>#include<limits.h>#define TO_BASE_N (sizeof(unsigned)*CHAR_BIT +1)// v. compound literal .v#define TO_BASE(x, b) my_to_base((char[TO_BASE_N]){""},(x),(b))// Tailor the details of the conversion function as needed// This one does not display unneeded leading zeros// Use return value, not `buf`char*my_to_base(char*buf,unsigned i,int base){
assert(base >=2&& base <=36);char*s =&buf[TO_BASE_N -1];*s ='\0';do{
s--;*s ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % base];
i /= base;}while(i);// Could employ memmove here to move the used buffer to the beginningreturn s;}#include<stdio.h>int main(void){int ip1 =0x01020304;int ip2 =0x05060708;
printf("%s %s\n", TO_BASE(ip1,16), TO_BASE(ip2,16));
printf("%s %s\n", TO_BASE(ip1,2), TO_BASE(ip2,2));
puts(TO_BASE(ip1,8));
puts(TO_BASE(ip1,36));return0;}
Это очень полезно. Вы знаете, как использовать его в C ++? При компиляции выдается ошибка «Код серьезности Описание Ошибка состояния строки файла проекта C4576, заключенный в скобки тип, за которым следует список инициализатора, представляет собой нестандартный синтаксис явного преобразования типа hello C: \ my_projects \ hello \ hello \ main.cpp 39 "
Просто ученик
1
@Justalearner Это генерирует C ++, потому что если использует составной литерал компонента C, который не является частью C ++. Возможно, опубликуйте свою реализацию C ++, которая пытается сделать то же самое - даже если она не завершена, я уверен, что вы получите помощь - до тех пор, пока вы сначала продемонстрируете свою попытку.
chux - Восстановить Монику
6
Может быть, немного OT, но если вам нужно это только для отладки, чтобы понять или пересмотреть некоторые бинарные операции, которые вы делаете, вы можете взглянуть на wcalc (простой консольный калькулятор). С опциями -b вы получаете двоичный вывод.
на этом фронте тоже есть несколько других вариантов ruby -e 'printf("%b\n", 0xabc)', dcзатем 2oследуют 0x123pи так далее.
Линдес
6
В стандартной библиотеке C нет функции форматирования для вывода подобного двоичного файла. Все операции форматирования, поддерживаемые семейством printf, направлены на читабельный текст.
Если вы хотите использовать динамическую память (сквозную std::string), вы можете также избавиться от staticмассива. Простейшим способом было бы просто удалить staticспецификатор и сделать его bлокальным для функции.
Шахбаз
((x>>z) & 0x01) + '0'достаточно.
Джейсон C
4
Печатайте биты любого типа, используя меньше кода и ресурсов
Этот подход имеет в качестве атрибутов:
Работает с переменными и литералами.
Не повторяет все биты, когда это не нужно.
Вызывайте printf только после завершения байта (не обязательно для всех битов).
Работает для любого типа.
Работает с небольшим и большим порядком байтов (для проверки использует GCC #defines).
Использует typeof (), который не является стандартом C, но в значительной степени определяется.
Я использовал другой подход ( bitprint.h ), чтобы заполнить таблицу всеми байтами (в виде битовых строк) и распечатать их на основе байта ввода / индекса. Стоит взглянуть.
void
print_binary(unsignedint n){unsignedint mask =0;/* this grotesque hack creates a bit pattern 1000... *//* regardless of the size of an unsigned int */
mask =~mask ^(~mask >>1);for(; mask !=0; mask >>=1){
putchar((n & mask)?'1':'0');}}
Или добавьте 0 или 1 к символьному значению '0';) Троицы не нужны.
Сова
3
Мне понравился код от paniq, статический буфер - хорошая идея. Однако это не удастся, если вам нужно несколько двоичных форматов в одном printf (), потому что он всегда возвращает один и тот же указатель и перезаписывает массив.
Вот вставка в стиле C, которая вращает указатель на разделенный буфер.
char*
format_binary(unsignedint x){#define MAXLEN 8// width of output format#define MAXCNT 4// count per printf statementstaticchar fmtbuf[(MAXLEN+1)*MAXCNT];staticint count =0;char*b;
count = count % MAXCNT +1;
b =&fmtbuf[(MAXLEN+1)*count];
b[MAXLEN]='\0';for(int z =0; z < MAXLEN; z++){ b[MAXLEN-1-z]=((x>>z)&0x1)?'1':'0';}return b;}
При countдостижении MAXCNT - 1следующего приращения значение countбудет MAXCNTравно нулю, что приведет к выходу за пределы массива. Вы должны были сделать count = (count + 1) % MAXCNT.
Шахбаз
1
Кстати, это станет неожиданностью для разработчика, который использует MAXCNT + 1вызовы этой функции в отдельности printf. В общем, если вы хотите предоставить опцию для более чем 1 вещи, сделайте ее бесконечной. Числа, такие как 4, могут только вызвать проблему.
Шахбаз
3
Нет стандартного и портативного способа.
Некоторые реализации предоставляют itoa () , но в большинстве случаев этого не произойдет, и он имеет несколько вялый интерфейс. Но код находится за ссылкой и должен позволить вам довольно легко реализовать свой собственный форматтер.
На основе @ ideasman42 - х внушения в своем ответе, это макрос , который обеспечивает int8, 16, 32& 64версии, повторное использование в INT8макрос , чтобы избежать повторения.
/* Convert an int to it's binary representation */char*int2bin(int num,int pad){char*str = malloc(sizeof(char)*(pad+1));if(str){
str[pad]='\0';while(--pad>=0){
str[pad]= num &1?'1':'0';
num >>=1;}}else{return"";}return str;}/* example usage */
printf("The number 5 in binary is %s", int2bin(5,4));/* "The number 5 in binary is 0101" */
Ответы:
Хаки но у меня работает
Для многобайтовых типов
Вам нужны все лишние цитаты, к сожалению. Этот подход несет риски эффективности макросов (не передавайте функцию в качестве аргумента
BYTE_TO_BINARY
), но избегает проблем с памятью и множественных вызовов strcat в некоторых других предложениях здесь.источник
printf
те, у кого нетstatic
буферов.%d
к%c
, потому что оно должно быть еще быстрее (%d
должно выполнить digit-> обугленного преобразования, а%c
просто выводит аргументint
что в системе 32-битное значение, для печати одного 32-битного значения потребуется пространство для 32 * 4-байтовых значений; всего 128 байтов. Что, в зависимости от размера стека, может быть или не быть проблемой.Печать двоичного кода для любого типа данных
тестовое задание
источник
size_t i; for (i=size; i-- > 0; )
избежатьsize_t
противint
несовпадения.ptr
(внешний цикл); затем для каждого бита текущий байт (внутренний цикл) маскирует байт текущим битом (1 << j
). Сдвиньте это вправо, получив в результате байт, содержащий 0 (0000 0000b
) или 1 (0000 0001b
). Распечатать полученный байт printf с форматом%u
. НТН.>
с вашим комментарием,size_t
а не с ним,>=
чтобы определить, когда завершить цикл.>
и>=
с беззнаковыми типами.0
это случай без знака и обычно встречается, в отличие от математики со знаком и менее распространеннымINT_MAX/INT_MIN
.Вот быстрый взлом, чтобы продемонстрировать методы, чтобы делать то, что вы хотите.
источник
strcat
это неэффективный метод добавления одного символа в строку на каждом проходе цикла. Вместо этого добавьтеchar *p = b;
и замените внутренний цикл на*p++ = (x & z) ? '1' : '0'
.z
должен начинаться с 128 (2 ^ 7) вместо 256 (2 ^ 8). Рассмотрите возможность обновления, чтобы получить указатель на используемый буфер (для безопасности потока), аналогичноinet_ntoa()
.strcat()
! Я согласен, чтоstrcat
это, вероятно, легче понять, чем постинкрементный разыменованный указатель для назначения, но даже начинающим нужно знать, как правильно использовать стандартную библиотеку. Возможно, использование индексированного массива для присваивания было бы хорошей демонстрацией (и на самом деле будет работать, такb
как не сбрасывается на все нули при каждом вызове функции).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.Обычно в glibc нет спецификатора двоичного преобразования.
Можно добавить пользовательские типы преобразования в семейство функций printf () в glibc. Смотрите register_printf_function для подробностей. Вы можете добавить пользовательское преобразование% b для собственного использования, если оно упрощает код приложения, чтобы сделать его доступным.
Вот пример того, как реализовать пользовательские форматы printf в glibc.
источник
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Существует новая функция , чтобы сделать то же самое, но:register_printf_specifier()
. Пример нового использования можно найти здесь: codereview.stackexchange.com/q/219994/200418Вы можете использовать небольшой стол, чтобы улучшить скорость 1 . Подобные методы полезны во встроенном мире, например, для инвертирования байта:
1 В основном я имею в виду встроенные приложения, в которых оптимизаторы не столь агрессивны и разница в скорости заметна.
источник
Выведите наименее значимый бит и сдвиньте его справа. Делая это, пока целое число не станет равным нулю, печатается двоичное представление без начальных нулей, но в обратном порядке. Используя рекурсию, порядок можно исправить довольно легко.
Для меня это одно из самых чистых решений проблемы. Если вам нравится
0b
префикс и завершающий символ новой строки, я предлагаю обернуть функцию.Онлайн демо
источник
putc('0'+(number&1), stdout);
На основании ответа @William Уайта, это макрос , который обеспечивает
int8
,16
,32
&64
версии, повторное использование вINT8
макрос , чтобы избежать повторения.Это выводит:
Для удобства чтения вы можете добавить разделитель, например:
источник
PRINTF_BYTE_TO_BINARY_INT#
определений для необязательного использования.Вот версия функции, которая не страдает от проблем повторного входа или ограничений размера / типа аргумента:
Обратите внимание, что этот код будет работать так же хорошо для любой базы от 2 до 10, если вы просто замените 2 на желаемую базу. Использование это:
Где
x
любое интегральное выражение.источник
char *a = binary_fmt(x), *b = binary_fmt(y);
не будут работать так, как ожидалось. Принуждение вызывающей стороны к пропуску буфера приводит к требованию хранения; вызывающий, конечно, может свободно использовать статический буфер, если это действительно необходимо, и тогда повторное использование этого же буфера становится явным. Также обратите внимание, что в современных PIC ABI статические буферы обычно требуют больше кода для доступа, чем буферы в стеке.источник
'1'
и'0'
вместо49
и48
в своей троичной. Кроме того,b
длина должна быть 9 символов, чтобы последний символ оставался нулевым терминатором.static char b[9] = {0}
2. декларации выйти из цикла:int z,y;
3. Добавьте окончательный ноль:b[y] = 0
. Таким образом, реинитализация не требуется.8
s должны быть заменены наCHAR_BIT
.Быстрое и простое решение:
Работает для любого типа размера и для подписанных и беззнаковых целых. '& 1' необходим для обработки подписанных целых, поскольку сдвиг может расширять подпись.
Есть так много способов сделать это. Вот супер простой способ печати 32-битных или n-битных данных из 32-битного типа со знаком или без знака (не помещая отрицательный знак, если подписан, просто печатая фактические биты) и без возврата каретки. Обратите внимание, что я уменьшается до сдвига битов:
Как насчет возврата строки с битами для хранения или печати позже? Вы можете либо выделить память и вернуть ее, и пользователь должен освободить ее, либо вы вернете статическую строку, но она будет засорена при повторном вызове или другим потоком. Оба метода показаны:
Звоните с:
источник
Ни один из ранее опубликованных ответов не был именно тем, что я искал, поэтому я написал один. Это очень просто использовать% B с
printf
!источник
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Некоторые среды выполнения поддерживают «% b», хотя это не стандарт.
Также смотрите здесь для интересного обсуждения:
http://bytes.com/forum/thread591027.html
НТН
источник
Этот код должен обрабатывать ваши потребности до 64 бит. Я создал 2 функции pBin & pBinFill. Оба делают одно и то же, но pBinFill заполняет лидирующие пробелы с помощью fillChar. Функция теста генерирует некоторые тестовые данные, а затем распечатывает их, используя функцию.
источник
width
вместо этого!printf()
Семья только в состоянии печатать в базе 8, 10 и 16 с использованием стандартных спецификаторов непосредственно. Я предлагаю создать функцию, которая преобразует число в строку для конкретных потребностей кода.Для печати на любой базе [2-36]
Все остальные ответы до сих пор имеют по крайней мере одно из этих ограничений.
Используйте статическую память для буфера возврата. Это ограничивает количество раз, которое функция может использоваться в качестве аргумента
printf()
.Выделите память, требующую кода вызова, чтобы освободить указатели.
Требовать код вызова, чтобы явно предоставить подходящий буфер.
Звоните
printf()
напрямую. Это обязывает новую функцию кfprintf()
,sprintf()
,vsprintf()
и т.д.Используйте уменьшенный диапазон целых чисел.
Следующее не имеет ни одного из вышеуказанных ограничений . Это требует C99 или позже и использования
"%s"
. Он использует составной литерал для предоставления буферного пространства. У него нет проблем с несколькими вызовами вprintf()
.Вывод
источник
Может быть, немного OT, но если вам нужно это только для отладки, чтобы понять или пересмотреть некоторые бинарные операции, которые вы делаете, вы можете взглянуть на wcalc (простой консольный калькулятор). С опциями -b вы получаете двоичный вывод.
например
источник
ruby -e 'printf("%b\n", 0xabc)'
,dc
затем2o
следуют0x123p
и так далее.В стандартной библиотеке C нет функции форматирования для вывода подобного двоичного файла. Все операции форматирования, поддерживаемые семейством printf, направлены на читабельный текст.
источник
Следующая рекурсивная функция может быть полезна:
источник
Я оптимизировал лучшее решение для размера и C ++ и получил следующее решение:
источник
std::string
), вы можете также избавиться отstatic
массива. Простейшим способом было бы просто удалитьstatic
спецификатор и сделать егоb
локальным для функции.((x>>z) & 0x01) + '0'
достаточно.Печатайте биты любого типа, используя меньше кода и ресурсов
Этот подход имеет в качестве атрибутов:
Вывод
Я использовал другой подход ( bitprint.h ), чтобы заполнить таблицу всеми байтами (в виде битовых строк) и распечатать их на основе байта ввода / индекса. Стоит взглянуть.
источник
источник
Мне понравился код от paniq, статический буфер - хорошая идея. Однако это не удастся, если вам нужно несколько двоичных форматов в одном printf (), потому что он всегда возвращает один и тот же указатель и перезаписывает массив.
Вот вставка в стиле C, которая вращает указатель на разделенный буфер.
источник
count
достиженииMAXCNT - 1
следующего приращения значениеcount
будетMAXCNT
равно нулю, что приведет к выходу за пределы массива. Вы должны были сделатьcount = (count + 1) % MAXCNT
.MAXCNT + 1
вызовы этой функции в отдельностиprintf
. В общем, если вы хотите предоставить опцию для более чем 1 вещи, сделайте ее бесконечной. Числа, такие как 4, могут только вызвать проблему.Нет стандартного и портативного способа.
Некоторые реализации предоставляют itoa () , но в большинстве случаев этого не произойдет, и он имеет несколько вялый интерфейс. Но код находится за ссылкой и должен позволить вам довольно легко реализовать свой собственный форматтер.
источник
Одно утверждение универсальное преобразование любого целочисленного типа в двоичное строковое представление с использованием стандартной библиотеки:
Или просто:
std::cout << std::bitset<sizeof(num) * 8>(num);
источник
Мое решение:
источник
На основе @ ideasman42 - х внушения в своем ответе, это макрос , который обеспечивает
int8
,16
,32
&64
версии, повторное использование вINT8
макрос , чтобы избежать повторения.Это выводит:
Для удобства чтения вы можете изменить:
#define PRINTF_BINARY_SEPARATOR
на#define PRINTF_BINARY_SEPARATOR ","
или#define PRINTF_BINARY_SEPARATOR " "
Это выведет:
или
источник
Использование:
Для получения дополнительной информации см. Как напечатать двоичное число через printf .
источник
должно работать - не проверено.
источник
источник
Далее покажет вам макет памяти:
источник
Вот небольшой вариант решения paniq , использующего шаблоны для печати 32- и 64-битных целых чисел:
И может быть использован как:
Вот результат:
источник