Есть ли конвертер printf для печати в двоичном формате?

Я могу напечатать с printf как шестнадцатеричное или восьмеричное число. Есть ли тег формата для печати в двоичном или произвольном виде?

Я бегу GCC.

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
21.09.2008 20:04:58
Вы не можете сделать это, насколько я знаю, используя printf. Очевидно, вы могли бы написать вспомогательный метод для достижения этой цели, но это не похоже на направление, в котором вы хотите идти.
Ian P 21.09.2008 20:09:18
Для этого не существует предопределенного формата. Вам необходимо преобразовать его в строку, а затем распечатать строку.
rslite 21.09.2008 20:10:22
Быстрый поиск в Google дал эту страницу с некоторой информацией, которая может быть полезна: forums.macrumors.com/archive/index.php/t-165959.html
Ian P 21.09.2008 20:10:58
Не входит в стандартную библиотеку ANSI C - если вы пишете переносимый код, самый безопасный способ - это создать свой собственный.
tomlogic 8.07.2010 16:00:35
Одно утверждение стандартное и универсальное (для любого типа Integral любой длины) решение преобразования в двоичную строку на C ++: stackoverflow.com/a/31660310/1814353
luart 27.07.2015 18:31:40
30 ОТВЕТОВ

В стандартной библиотеке C нет функции форматирования для вывода двоичного кода, подобного этому. Все операции форматирования, поддерживаемые семейством printf, направлены на читабельный текст.

6
25.12.2017 21:06:39

Некоторые среды выполнения поддерживают «% b», хотя это не стандарт.

Также смотрите здесь для интересного обсуждения:

http://bytes.com/forum/thread591027.html

НТН

8
22.09.2008 02:56:00
На самом деле это свойство библиотеки времени выполнения C, а не компилятора.
cjm 21.09.2008 20:18:06

Нет стандартного и портативного способа.

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

3
26.02.2014 02:08:00

Обычно в glibc нет спецификатора двоичного преобразования.

Можно добавить пользовательские типы преобразования в семейство функций printf () в glibc. Смотрите register_printf_function для подробностей. Вы можете добавить пользовательское преобразование% b для собственного использования, если оно упрощает код приложения, чтобы сделать его доступным.

Вот пример того, как реализовать пользовательские форматы printf в glibc.

83
16.04.2009 23:19:19
Я всегда писал свой собственный v [snf] printf () для ограниченных случаев, когда мне нужны были разные радиксы: я так рад, что просмотрел это.
Jamie 25.07.2015 01:14:23
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]Существует новая функция , чтобы сделать то же самое, но: register_printf_specifier(). Пример нового использования можно найти здесь: codereview.stackexchange.com/q/219994/200418
Cacahuete Frito 9.05.2019 17:03:20

Вот быстрый взлом, чтобы продемонстрировать методы, чтобы делать то, что вы хотите.

#include <stdio.h>      /* printf */
#include <string.h>     /* strcat */
#include <stdlib.h>     /* strtol */

const char *byte_to_binary(int x)
{
    static char 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));
    }

    return 0;
}
151
17.10.2012 01:14:11
Это, безусловно, менее «странно», чем обычная запись escape-перегрузки для printf. Это также легко понять для разработчика, не знакомого с кодом.
Furious Coder 16.04.2009 23:23:45
Несколько изменений: strcatэто неэффективный метод добавления одного символа в строку на каждом проходе цикла. Вместо этого добавьте char *p = b;и замените внутренний цикл на *p++ = (x & z) ? '1' : '0'. zдолжен начинаться с 128 (2 ^ 7) вместо 256 (2 ^ 8). Рассмотрите возможность обновления, чтобы получить указатель на используемый буфер (для безопасности потока), аналогично inet_ntoa().
tomlogic 8.07.2010 15:59:15
@EvilTeach: Вы сами используете троичный оператор в качестве параметра для strcat()! Я согласен, что strcatэто, вероятно, легче понять, чем постинкрементный разыменованный указатель для назначения, но даже начинающим нужно знать, как правильно использовать стандартную библиотеку. Возможно, использование индексированного массива для присваивания было бы хорошей демонстрацией (и на самом деле будет работать, так bкак не сбрасывается на все нули при каждом вызове функции).
tomlogic 10.08.2010 17:24:24
Случайный: двоичный буфер char является статическим и очищается от всех нулей в назначении. Это очистит его только при первом запуске, а после этого не очистит, а вместо этого использует последнее значение.
markwatson 18.08.2010 22:10:06
Кроме того , это должно документально подтвердить , что предыдущий результат будет недействительным после повторного вызова функции, поэтому абоненты не должны пытаться использовать его как это: printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4)).
Paŭlo Ebermann 30.07.2011 23:08:20

Может быть, немного OT, но если вам нужно это только для отладки, чтобы понять или пересмотреть некоторые бинарные операции, которые вы делаете, вы можете взглянуть на wcalc (простой консольный калькулятор). С опциями -b вы получаете двоичный вывод.

например

$ wcalc -b "(256 | 3) & 0xff"
 = 0b11
6
22.09.2008 08:25:57
на этом фронте также есть несколько других вариантов ... ruby -e 'printf("%b\n", 0xabc)', dcзатем 2oследуют 0x123pи так далее.
lindes 13.10.2013 07:06:42
const char* byte_to_binary( int x )
{
    static char b[sizeof(int)*8+1] = {0};
    int y;
    long long z;
    for (z=1LL<<sizeof(int)*8-1,y=0; z>0; z>>=1,y++)
    {
        b[y] = ( ((x & z) == z) ? '1' : '0');
    }

    b[y] = 0;

    return b;
}
13
9.10.2012 21:14:06
Понятнее, если вы используете '1'и '0'вместо 49и 48в своей троичной. Кроме того, bдлина должна быть 9 символов, чтобы последний символ оставался нулевым терминатором.
tomlogic 8.07.2010 15:54:28
Также B необходимо каждый раз инициализировать.
EvilTeach 10.06.2012 12:31:45
Нет , если вы изменить некоторые из них : 1. добавить пространства для окончательной нулевого: static char b[9] = {0}2. декларации выйти из цикла: int z,y;3. Добавьте окончательный ноль: b[y] = 0. Таким образом, реинитализация не требуется.
Kobor42 6.09.2012 14:13:14
Хорошее решение. Я бы изменил кое-что. Т.е. возвращаясь в строку назад, чтобы ввод любого размера мог быть обработан правильно.
Kobor42 6.09.2012 14:18:25
Все эти 8s должны быть заменены на CHAR_BIT.
alk 5.06.2016 14:58:56

Даже для динамических библиотек, которые поддерживают% b, кажется, что это только для целочисленных значений.

Если вы хотите печатать значения с плавающей точкой в ​​двоичном виде, я написал код, который вы можете найти по адресу http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/ .

0
6.05.2009 14:54:32

Этот код должен обрабатывать ваши потребности до 64 бит. Я создал 2 функции pBin & pBinFill. Оба делают одно и то же, но pBinFill заполняет ведущие пробелы с помощью fillChar. Функция теста генерирует некоторые тестовые данные, а затем распечатывает их, используя функцию.



char* pBinFill(long int x,char *so, char fillChar); // version with fill
char* pBin(long int x, char *so);                   // version without fill
#define kDisplayWidth 64

char* pBin(long int x,char *so)
{
 char s[kDisplayWidth+1];
 int  i=kDisplayWidth;
 s[i--]=0x00;   // terminate string
 do
 { // 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 string
 return so;
}

char* pBinFill(long int x,char *so, char fillChar)
{ // fill in array from right to left
 char s[kDisplayWidth+1];
 int  i=kDisplayWidth;
 s[i--]=0x00;   // terminate string
 do
 { // 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 pBin
 long int 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 =  0b00000000000000000000000000000001
00000011 =  0x00000b =  0b00000000000000000000000000001011
00000121 =  0x000079 =  0b00000000000000000000000001111001
00001331 =  0x000533 =  0b00000000000000000000010100110011
00014641 =  0x003931 =  0b00000000000000000011100100110001
00161051 =  0x02751b =  0b00000000000000100111010100011011
01771561 =  0x1b0829 =  0b00000000000110110000100000101001
19487171 = 0x12959c3 =  0b00000001001010010101100111000011
7
22.04.2011 22:45:29
«#define width 64» конфликтует с stream.h из log4cxx. Пожалуйста, используйте условно случайные определения имен :)
kagali-san 30.01.2011 14:50:45
@mhambra: вы должны отключить log4cxx за использование такого общего имени, как widthвместо этого!
u0b34a0f6ae 17.11.2011 09:10:32

Хаки но у меня работает

#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte)  \
  (byte & 0x80 ? '1' : '0'), \
  (byte & 0x40 ? '1' : '0'), \
  (byte & 0x20 ? '1' : '0'), \
  (byte & 0x10 ? '1' : '0'), \
  (byte & 0x08 ? '1' : '0'), \
  (byte & 0x04 ? '1' : '0'), \
  (byte & 0x02 ? '1' : '0'), \
  (byte & 0x01 ? '1' : '0') 
printf("Leading text "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));

Для многобайтовых типов

printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
  BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

Вам нужны все лишние цитаты, к сожалению. Этот подход несет риски эффективности макросов (не передавайте функцию в качестве аргумента BYTE_TO_BINARY), но избегает проблем с памятью и множественных вызовов strcat в некоторых других предложениях здесь.

260
27.05.2016 17:29:50
И имеет преимущество также в том, что его можно вызывать несколько раз, а printfте, у кого нет staticбуферов.
Patrick Schlüter 24.10.2010 10:28:35
Я взял на себя смелость изменить его %dна %c, потому что он должен быть еще быстрее ( %dдолжен выполнять преобразование цифр -> символов, при этом %cпросто выводит аргумент
user719662 27.05.2016 15:20:20
Опубликована расширенная версия этого макроса с поддержкой 16, 32, 64 битных int: stackoverflow.com/a/25108449/432509
ideasman42 21.06.2017 19:57:45
Обратите внимание, что этот подход не подходит для стека. Предполагая, intчто в системе 32-битное значение, для печати одного 32-битного значения потребуется пространство для 32 * 4-байтовых значений; всего 128 байтов. Что, в зависимости от размера стека, может быть или не быть проблемой.
user694733 12.10.2017 06:47:31
важно добавить скобки вокруг байта в макросе, иначе вы можете столкнуться с проблемами при отправке операции BYTE_TO_BINARY (a | b) -> a | b & 0x01! = (a | b) & 0x01
Ivan Hoffmann 21.06.2019 15:21:39
void print_ulong_bin(const unsigned long * const var, int bits) {
        int i;

        #if defined(__LP64__) || defined(_LP64)
                if( (bits > 64) || (bits <= 0) )
        #else
                if( (bits > 32) || (bits <= 0) )
        #endif
                return;

        for(i = 0; i < bits; i++) { 
                printf("%lu", (*var >> (bits - 1 - i)) & 0x01);
        }
}

должно работать - не проверено.

2
30.09.2010 19:05:07

Печать двоичного кода для любого типа данных

//assumes little endian
void printBits(size_t const size, void const * const ptr)
{
    unsigned char *b = (unsigned char*) ptr;
    unsigned char 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);
        return 0;
}
201
5.05.2016 14:09:14
Предложите size_t i; for (i=size; i-- > 0; )избежать size_tпротив intнесоответствия.
chux - Reinstate Monica 12.11.2013 19:25:23
Может ли кто-нибудь рассказать о логике этого кода?
jII 13.01.2014 05:39:50
Возьмите каждый байт ptr(внешний цикл); затем для каждого бита текущий байт (внутренний цикл) маскирует байт текущим битом ( 1 << j). Сдвиньте это право, получив в результате байт, содержащий 0 ( 0000 0000b) или 1 ( 0000 0001b). Распечатать полученный байт printf с форматом %u. НТН.
nielsbot 17.02.2016 08:29:07
@ ZX9 Обратите внимание, что предлагаемый код используется >с вашим комментарием, size_tа не с ним, >=чтобы определить, когда завершить цикл.
chux - Reinstate Monica 9.09.2016 14:24:22
@ ZX9 Тем не менее полезный оригинальный комментарий ваших , как кодерам действительно нужно быть осторожными , принимая во внимание случая использования Края >и >=с беззнаковыми типами. 0это случай без знака и обычно встречается, в отличие от математики со знаком и менее распространенным INT_MAX/INT_MIN.
chux - Reinstate Monica 9.09.2016 17:28:18
void PrintBinary( int Value, int Places, char* TargetString)
{
    int Mask;

    Mask = 1 << Places;

    while( Places--) {
        Mask >>= 1; /* Preshift, because we did one too many above */
        *TargetString++ = (Value & Mask)?'1':'0';
    }
    *TargetString = 0; /* Null terminator for C string */
}

Вызывающая функция "владеет" строкой ...:

char BinaryString[17];
...
PrintBinary( Value, 16, BinaryString);
printf( "yadda yadda %s yadda...\n", BinaryString);

В зависимости от вашего процессора, большинство операций в PrintBinary выполняется с одной или несколькими машинными инструкциями.

0
21.10.2010 16:54:08
Это имеет больше смысла, если вы используете do { ... } while ( ... );префикс смещения и вместо смещения.
Alexsander Akers 7.12.2010 03:56:21
#include <stdio.h>
#include <conio.h>

void main()
{
    clrscr();
    printf("Welcome\n\n\n");
    unsigned char x='A';
    char ch_array[8];
    for(int i=0; x!=0; i++)
    {
        ch_array[i] = x & 1;
        x = x >>1;
    }
    for(--i; i>=0; i--)
        printf("%d", ch_array[i]);

    getch();
}
2
25.12.2017 21:19:17

Вот версия функции, которая не страдает от проблем повторного входа или ограничений на размер / тип аргумента:

#define FMT_BUF_SIZE (CHAR_BIT*sizeof(uintmax_t)+1)
char *binary_fmt(uintmax_t x, char buf[static FMT_BUF_SIZE])
{
    char *s = buf + FMT_BUF_SIZE;
    *--s = 0;
    if (!x) *--s = '0';
    for(; x; x/=2) *--s = '0' + x%2;
    return s;
}

Обратите внимание, что этот код будет работать так же хорошо для любой базы от 2 до 10, если вы просто замените 2 на желаемую базу. Использование это:

char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));

Где xлюбое интегральное выражение.

16
29.01.2011 21:34:05
Да, вы можете сделать это. Но это действительно плохой дизайн. Даже если у вас нет потоков или повторного входа, вызывающая сторона должна знать, что статический буфер используется повторно, и такие вещи char *a = binary_fmt(x), *b = binary_fmt(y);не будут работать так, как ожидалось. Принуждение вызывающей стороны к пропуску буфера приводит к требованию хранения; вызывающий, конечно, может свободно использовать статический буфер, если это действительно необходимо, и тогда повторное использование этого же буфера становится явным. Также обратите внимание, что в современных PIC ABI статические буферы обычно обходятся дороже кода, чем буферы в стеке.
R.. GitHub STOP HELPING ICE 26.11.2012 20:55:23
Это все еще плохой дизайн. Это требует дополнительного шага копирования в этих случаях, и это не менее дорого, чем предоставление вызывающей стороне буфера даже в тех случаях, когда копирование не требуется. Использование статического хранилища - просто плохая идиома.
R.. GitHub STOP HELPING ICE 27.11.2012 01:46:54
Необходимость загрязнения пространства имен препроцессора или таблицы переменных символов ненужным дополнительным именем, которое необходимо использовать для правильного определения размера хранилища, которое должно быть выделено каждым вызывающим абонентом, и принуждение каждого вызывающего абонента знать это значение и выделять необходимое количество хранилище - плохой дизайн, когда более простое решение для локального хранения функций будет достаточным для большинства целей и задач, и когда простой вызов strdup () покрывает 99% остального использования.
Greg A. Woods 27.11.2012 01:50:16
Здесь мы собираемся не согласиться. Я не вижу, как добавление одного ненавязчивого символа препроцессора может привести к серьезному ограничению вариантов использования, созданию уязвимости интерфейса, резервированию постоянного хранилища на время действия программы для временного значения и созданию худшего кода в большинстве случаев. современные платформы.
R.. GitHub STOP HELPING ICE 27.11.2012 01:53:44
Я не поддерживаю микрооптимизацию без причины (например, измерения). Но я думаю, что производительность, даже если она находится в масштабе микро-усиления, стоит упомянуть, когда она идет в качестве бонуса наряду с принципиально превосходным дизайном.
R.. GitHub STOP HELPING ICE 27.11.2012 02:39:49
/* 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" */
2
1.07.2011 15:26:25
Оплата стоимости неправильного размещения повредит производительности. Передача ответственности за уничтожение буфера вызывающей стороне недобросовестна.
EvilTeach 17.07.2011 17:53:15

Я оптимизировал лучшее решение для размера и C ++ и получил это решение:

inline std::string format_binary(unsigned int x)
{
    static char b[33];
    b[32] = '\0';

    for (int z = 0; z < 32; z++) {
        b[31-z] = ((x>>z) & 0x1) ? '1' : '0';
    }

    return b;
}
4
17.07.2011 13:19:49
Если вы хотите использовать динамическую память (сквозную std::string), вы можете также избавиться от staticмассива. Простейшим способом было бы просто удалить staticспецификатор и сделать его bлокальным для функции.
Shahbaz 24.09.2013 14:23:30
((x>>z) & 0x01) + '0'достаточно.
Jason C 3.11.2013 18:11:03

Есть ли конвертер printf для печати в двоичном формате?

Нет стандартного спецификатора формата printf для выполнения «двоичного» вывода. Вот альтернатива, которую я разработал, когда мне это было нужно.

Мой работает для любой базы от 2 до 36. Он разветвляет цифры в вызывающие фреймы рекурсивных вызовов, пока не достигнет цифры, меньшей базы. Затем он «перемещается» назад, заполняя буфер вперед и возвращаясь. Возвращаемое значение - используемый размер или -1, если буфер недостаточно велик для хранения строки.

int conv_rad (int num, int rad, char *s, int n) {
    char *vec = "0123456789" "ABCDEFGHIJKLM" "NOPQRSTUVWXYZ";
    int off;
    if (n == 0) return 0;
    if (num < rad) { *s = vec[num]; return 1; }
    off = conv_rad(num/rad, rad, s, n);
    if ((off == n) || (off == -1)) return -1;
    s[off] = vec[num%rad];
    return off+1;
}

Одно большое предостережение: эта функция была разработана для использования со строками в стиле «Паскаль», которые имеют свою длину. Следовательно conv_rad, как написано, буфер не обнуляется. Для более общего использования C, возможно, потребуется простой обертка для завершения. Или для печати просто измените назначения на putchar()s.

0
22.10.2015 07:37:59

Мне понравился код от paniq, статический буфер - хорошая идея. Однако это не удастся, если вам нужно несколько двоичных форматов в одном printf (), потому что он всегда возвращает один и тот же указатель и перезаписывает массив.

Вот вставка в стиле C, которая вращает указатель на разделенный буфер.

char *
format_binary(unsigned int x)
{
    #define MAXLEN 8 // width of output format
    #define MAXCNT 4 // count per printf statement
    static char fmtbuf[(MAXLEN+1)*MAXCNT];
    static int 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;
}
3
21.08.2011 13:57:21
При countдостижении MAXCNT - 1следующего приращения значение countбудет MAXCNTравно нулю, что приведет к выходу за пределы массива. Вы должны были сделать count = (count + 1) % MAXCNT.
Shahbaz 24.09.2013 14:26:17
Кстати, это станет неожиданностью для разработчика, который использует MAXCNT + 1вызовы этой функции в отдельности printf. В общем, если вы хотите предоставить опцию для более чем 1 вещи, сделайте ее бесконечной. Числа, такие как 4, могут только вызвать проблему.
Shahbaz 24.09.2013 14:27:55

Далее покажет вам макет памяти:

#include <limits>
#include <iostream>
#include <string>

using namespace std;

template<class T> string binary_text(T dec, string byte_separator = " ") {
    char* pch = (char*)&dec;
    string res;
    for (int i = 0; i < sizeof(T); i++) {
        for (int j = 1; j < 8; j++) {
            res.append(pch[i] & 1 ? "1" : "0");
            pch[i] /= 2;
        }
        res.append(byte_separator);
    }
    return res;
}

int main() {
    cout << binary_text(5) << endl;
    cout << binary_text(.1) << endl;

    return 0;
}
2
15.01.2012 10:57:58
Что вы подразумеваете под "Далее покажет вам макет памяти" ?
Peter Mortensen 25.12.2017 21:00:32

Ни один из ранее опубликованных ответов не был именно тем, что я искал, поэтому я написал один. Это очень просто использовать% B с printf!

    /*
     * File:   main.c
     * Author: Techplex.Engineer
     *
     * Created on February 14, 2012, 9:16 PM
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <printf.h>
    #include <math.h>
    #include <string.h>


    static int printf_arginfo_M(const struct printf_info *info, size_t n, int *argtypes) {
        /* "%M" always takes one argument, a pointer to uint8_t[6]. */
        if (n > 0) {
            argtypes[0] = PA_POINTER;
        }
        return 1;
    } /* printf_arginfo_M */

    static int printf_output_M(FILE *stream, const struct printf_info *info, const void *const *args) {
        int value = 0;
        int len;

        value = *(int **) (args[0]);

        //Beginning of my code ------------------------------------------------------------
        char buffer [50] = ""; //Is this bad?
        char buffer2 [50] = ""; //Is this bad?
        int bits = info->width;
        if (bits <= 0)
            bits = 8; // Default to 8 bits

        int mask = pow(2, bits - 1);
        while (mask > 0) {
            sprintf(buffer, "%s", (((value & mask) > 0) ? "1" : "0"));
            strcat(buffer2, buffer);
            mask >>= 1;
        }
        strcat(buffer2, "\n");
        // End of my code --------------------------------------------------------------
        len = fprintf(stream, "%s", buffer2);
        return len;
    } /* printf_output_M */

    int main(int argc, char** argv) {

        register_printf_specifier('B', printf_output_M, printf_arginfo_M);

        printf("%4B\n", 65);

        return (EXIT_SUCCESS);
    }
10
25.12.2017 21:01:35
будет ли это переполнение более чем с 50 битами?
Janus Troelsen 18.03.2012 00:06:26
Хороший вызов, да, это будет ... Мне сказали, что мне нужно использовать malloc, когда-нибудь, понимаешь?
TechplexEngineer 22.03.2012 02:48:42
Ну конечно; естественно. супер просто:char* buffer = (char*) malloc(sizeof(char) * 50);
Janus Troelsen 22.03.2012 10:25:49
@JanusTroelsen, или намного чище, меньше, ремонтопригоден:char *buffer = malloc(sizeof(*buffer) * 50);
Shahbaz 24.09.2013 14:21:35
Почему "% B" будет отличаться от "% b" в этом отношении? В предыдущих ответах говорилось что-то вроде: «В стандартной библиотеке C нет функции форматирования для вывода двоичного кода подобного». и " Некоторые среды выполнения поддерживают"% b ", хотя это не стандарт." ,
Peter Mortensen 25.12.2017 21:09:58

Использование:

char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);

Для получения дополнительной информации см. Как напечатать двоичное число через printf .

3
25.12.2017 21:11:01
В предыдущем ответе говорилось: «Некоторые реализации предоставляют itoa (), но в большинстве случаев этого не будет» ?
Peter Mortensen 25.12.2017 21:12:20

Вот небольшой вариант решения paniq , использующего шаблоны для печати 32- и 64-битных целых чисел:

template<class T>
inline std::string format_binary(T x)
{
    char b[sizeof(T)*8+1] = {0};

    for (size_t z = 0; z < sizeof(T)*8; z++)
        b[sizeof(T)*8-1-z] = ((x>>z) & 0x1) ? '1' : '0';

    return std::string(b);
}

И может быть использован как:

unsigned int value32 = 0x1e127ad;
printf( "  0x%x: %s\n", value32, format_binary(value32).c_str() );

unsigned long long value64 = 0x2e0b04ce0;
printf( "0x%llx: %s\n", value64, format_binary(value64).c_str() );

Вот результат:

  0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000
2
4.12.2013 05:22:50

Это может быть не очень эффективно, но довольно просто. Попробуй это:

tmp1 = 1;
while(inint/tmp1 > 1) {
    tmp1 <<= 1;
}
do {
    printf("%d", tmp2=inint/tmp1);
    inint -= tmp1*tmp2;
} while((tmp1 >>= 1) > 0);
printf(" ");
0
29.06.2013 14:11:49

Вот очень простой:

int print_char_to_binary(char ch)
{
    int i;
    for (i=7; i>=0; i--)
        printf("%hd ", ((ch & (1<<i))>>i));
    printf("\n");
    return 0;
}
0
25.12.2017 21:14:07
Примечание: как "h"здесь полезно? Выглядит одинаково хорошо без него.
chux - Reinstate Monica 12.11.2013 19:41:49
@ chux, это не совсем полезно на самом деле. Аргумент продвинут в intлюбом случае , так как %dи %hdдолжен был бы принять один intиз varargs.
Shahbaz 13.11.2013 13:29:03
Почему круглые скобки (ch & (1<<i))>>i?
Peter Mortensen 25.12.2017 21:14:50

Вы могли бы использовать небольшой стол, чтобы улучшить скорость 1 . Подобные методы полезны во встроенном мире, например, для инвертирования байта:

const char *bit_rep[16] = {
    [ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011",
    [ 4] = "0100", [ 5] = "0101", [ 6] = "0110", [ 7] = "0111",
    [ 8] = "1000", [ 9] = "1001", [10] = "1010", [11] = "1011",
    [12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
};

void print_byte(uint8_t byte)
{
    printf("%s%s", bit_rep[byte >> 4], bit_rep[byte & 0x0F]);
}

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

46
25.12.2017 21:16:00

Еще один подход к печати в двоичном формате: сначала преобразуйте целое число .

Чтобы распечатать 6в двоичном формате, измените 6на 110, затем распечатайте "110".

Обходит char buf[]проблемы.
printf()Спецификаторы формата, флаги и поля, как "%08lu", по- "%*lX"прежнему легко использовать.
Не только двоичный (основание 2), этот метод расширяется до других оснований вплоть до 16.
Ограничивается маленькими целочисленными значениями.

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

unsigned long char_to_bin10(char ch) {
  unsigned char uch = ch;
  unsigned long sum = 0;
  unsigned long power = 1;
  while (uch) {
    if (uch & 1) {
      sum += power;
      }
   power *= 10;
   uch /= 2;
  }
  return sum;
}

uint64_t uint16_to_bin16(uint16_t u) {
  uint64_t sum = 0;
  uint64_t power = 1;
  while (u) {
    if (u & 1) {
      sum += power;
      }
    power *= 16;
    u /= 2;
  }
  return sum;
}

void test(void) {
  printf("%lu\n", char_to_bin10(0xF1));
  // 11110001
  printf("%" PRIX64 "\n", uint16_to_bin16(0xF731));
  // 1111011100110001
}
2
17.07.2015 20:55:55

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

void print_binary(unsigned char c)
{
 unsigned char i1 = (1 << (sizeof(c)*8-1));
 for(; i1; i1 >>= 1)
      printf("%d",(c&i1)!=0);
}

void get_binary(unsigned char c, unsigned char bin[])
{
 unsigned char i1 = (1 << (sizeof(c)*8-1)), i2=0;
 for(; i1; i1>>=1, i2++)
      bin[i2] = ((c&i1)!=0);
}
2
19.03.2014 15:52:27

На основании ответа @William Уайта, это макрос , который обеспечивает int8, 16, 32& 64версии, повторное использование в INT8макрос , чтобы избежать повторения.

/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i)    \
    (((i) & 0x80ll) ? '1' : '0'), \
    (((i) & 0x40ll) ? '1' : '0'), \
    (((i) & 0x20ll) ? '1' : '0'), \
    (((i) & 0x10ll) ? '1' : '0'), \
    (((i) & 0x08ll) ? '1' : '0'), \
    (((i) & 0x04ll) ? '1' : '0'), \
    (((i) & 0x02ll) ? '1' : '0'), \
    (((i) & 0x01ll) ? '1' : '0')

#define PRINTF_BINARY_PATTERN_INT16 \
    PRINTF_BINARY_PATTERN_INT8              PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
    PRINTF_BYTE_TO_BINARY_INT8((i) >> 8),   PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
    PRINTF_BINARY_PATTERN_INT16             PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
    PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64    \
    PRINTF_BINARY_PATTERN_INT32             PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
    PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */

#include <stdio.h>
int main() {
    long long int flag = 1648646756487983144ll;
    printf("My Flag "
           PRINTF_BINARY_PATTERN_INT64 "\n",
           PRINTF_BYTE_TO_BINARY_INT64(flag));
    return 0;
}

Это выводит:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

Для удобства чтения вы можете добавить разделитель, например:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
21
21.06.2017 19:56:31
Это отлично. Есть ли особая причина для печати битов, начинающихся с наименее значимых бит?
gaganso 21.06.2017 15:12:32
@SilentMonk спасибо, исправлено, также добавлен 64-битный макрос.
ideasman42 21.06.2017 19:33:32
Как бы вы порекомендовали добавить запятую?
nmz787 21.11.2017 21:58:34
Добавил бы сгруппированную версию PRINTF_BYTE_TO_BINARY_INT#определений для необязательного использования.
ideasman42 22.11.2017 01:41:56

Вот как я это сделал для неподписанного int

void printb(unsigned int v) {
    unsigned int i, s = 1<<((sizeof(v)<<3)-1); // s = only most significant bit at 1
    for (i = s; i; i>>=1) printf("%d", v & i || 0 );
}
2
26.08.2014 10:56:38
Просто заметил, что это очень похоже на решение
andre.barata 26.08.2014 09:41:51
Есть ли способ ограничить размер вывода на выходе?
Remian8985 28.11.2014 01:59:45
@ Remian8985 да, переменная s содержит номер бита, который будет выведен. «(sizeof (v) << 3)» - это в основном размер входной переменной в байтах (4 в случае целого числа), тогда «<< 3» совпадает с умножением на 8, чтобы получить количество бит для печати
andre.barata 28.11.2014 17:17:35