Я могу напечатать с printf как шестнадцатеричное или восьмеричное число. Есть ли тег формата для печати в двоичном или произвольном виде?
Я бегу GCC.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Я могу напечатать с printf как шестнадцатеричное или восьмеричное число. Есть ли тег формата для печати в двоичном или произвольном виде?
Я бегу GCC.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Ответы:
Хаки но у меня работает
#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 в некоторых других предложениях здесь.
printf
те, у кого нет static
буферов.
%d
к %c
, потому что оно должно быть еще быстрее ( %d
должно выполнить digit-> обугленного преобразования, а %c
просто выводит аргумент
int
что в системе 32-битное значение, для печати одного 32-битного значения потребуется пространство для 32 * 4-байтовых значений; всего 128 байтов. Что, в зависимости от размера стека, может быть или не быть проблемой.
Печать двоичного кода для любого типа данных
//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;
}
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
.
Вот быстрый взлом, чтобы продемонстрировать методы, чтобы делать то, что вы хотите.
#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;
}
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 . Подобные методы полезны во встроенном мире, например, для инвертирования байта:
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]);
}
1 В основном я имею в виду встроенные приложения, в которых оптимизаторы не столь агрессивны и разница в скорости заметна.
Выведите наименее значимый бит и сдвиньте его справа. Делая это, пока целое число не станет равным нулю, печатается двоичное представление без начальных нулей, но в обратном порядке. Используя рекурсию, порядок можно исправить довольно легко.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Для меня это одно из самых чистых решений проблемы. Если вам нравится 0b
префикс и завершающий символ новой строки, я предлагаю обернуть функцию.
putc('0'+(number&1), stdout);
На основании ответа @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
PRINTF_BYTE_TO_BINARY_INT#
определений для необязательного использования.
Вот версия функции, которая не страдает от проблем повторного входа или ограничений размера / типа аргумента:
#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
любое интегральное выражение.
char *a = binary_fmt(x), *b = binary_fmt(y);
не будут работать так, как ожидалось. Принуждение вызывающей стороны к пропуску буфера приводит к требованию хранения; вызывающий, конечно, может свободно использовать статический буфер, если это действительно необходимо, и тогда повторное использование этого же буфера становится явным. Также обратите внимание, что в современных PIC ABI статические буферы обычно требуют больше кода для доступа, чем буферы в стеке.
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;
}
'1'
и '0'
вместо 49
и 48
в своей троичной. Кроме того, b
длина должна быть 9 символов, чтобы последний символ оставался нулевым терминатором.
static char b[9] = {0}
2. декларации выйти из цикла: int z,y;
3. Добавьте окончательный ноль: b[y] = 0
. Таким образом, реинитализация не требуется.
8
s должны быть заменены на CHAR_BIT
.
Быстрое и простое решение:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Работает для любого типа размера и для подписанных и беззнаковых целых. '& 1' необходим для обработки подписанных целых, поскольку сдвиг может расширять подпись.
Есть так много способов сделать это. Вот супер простой способ печати 32-битных или n-битных данных из 32-битного типа со знаком или без знака (не помещая отрицательный знак, если подписан, просто печатая фактические биты) и без возврата каретки. Обратите внимание, что я уменьшается до сдвига битов:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
Как насчет возврата строки с битами для хранения или печати позже? Вы можете либо выделить память и вернуть ее, и пользователь должен освободить ее, либо вы вернете статическую строку, но она будет засорена при повторном вызове или другим потоком. Оба метода показаны:
char *int_to_bitstring_alloc(int x, int count)
{
count = count<1 ? sizeof(x)*8 : count;
char *pstr = malloc(count+1);
for(int i = 0; i<count; i++)
pstr[i] = '0' | ((x>>(count-1-i))&1);
pstr[count]=0;
return pstr;
}
#define BITSIZEOF(x) (sizeof(x)*8)
char *int_to_bitstring_static(int x, int count)
{
static char bitbuf[BITSIZEOF(x)+1];
count = (count<1 || count>BITSIZEOF(x)) ? BITSIZEOF(x) : count;
for(int i = 0; i<count; i++)
bitbuf[i] = '0' | ((x>>(count-1-i))&1);
bitbuf[count]=0;
return bitbuf;
}
Звоните с:
// memory allocated string returned which needs to be freed
char *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 else
char *pstr2 = int_to_bitstring_static(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr2);
Ни один из ранее опубликованных ответов не был именно тем, что я искал, поэтому я написал один. Это очень просто использовать% 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);
}
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. Функция теста генерирует некоторые тестовые данные, а затем распечатывает их, используя функцию.
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
width
вместо этого!
Есть ли конвертер 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 beginning
return 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));
return 0;
}
Вывод
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
Может быть, немного OT, но если вам нужно это только для отладки, чтобы понять или пересмотреть некоторые бинарные операции, которые вы делаете, вы можете взглянуть на wcalc (простой консольный калькулятор). С опциями -b вы получаете двоичный вывод.
например
$ wcalc -b "(256 | 3) & 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)'
, dc
затем 2o
следуют 0x123p
и так далее.
В стандартной библиотеке C нет функции форматирования для вывода подобного двоичного файла. Все операции форматирования, поддерживаемые семейством printf, направлены на читабельный текст.
Следующая рекурсивная функция может быть полезна:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Я оптимизировал лучшее решение для размера и 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;
}
std::string
), вы можете также избавиться от static
массива. Простейшим способом было бы просто удалить static
спецификатор и сделать его b
локальным для функции.
((x>>z) & 0x01) + '0'
достаточно.
Этот подход имеет в качестве атрибутов:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define for_endian(size) for (int i = 0; i < size; ++i)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define for_endian(size) for (int i = size - 1; i >= 0; --i)
#else
#error "Endianness not detected"
#endif
#define printb(value) \
({ \
typeof(value) _v = value; \
__printb((typeof(_v) *) &_v, sizeof(_v)); \
})
void __printb(void *value, size_t size)
{
uint8_t byte;
size_t blen = sizeof(byte) * 8;
uint8_t bits[blen + 1];
bits[blen] = '\0';
for_endian(size) {
byte = ((uint8_t *) value)[i];
memset(bits, '0', blen);
for (int j = 0; byte && j < blen; ++j) {
if (byte & 0x80)
bits[j] = '1';
byte <<= 1;
}
printf("%s ", bits);
}
printf("\n");
}
int main(void)
{
uint8_t c1 = 0xff, c2 = 0x44;
uint8_t c3 = c1 + c2;
printb(c1);
printb((char) 0xff);
printb((short) 0xff);
printb(0xff);
printb(c2);
printb(0x44);
printb(0x4411ff01);
printb((uint16_t) c3);
printf("\n");
return 0;
}
$ ./printb
11111111
11111111
00000000 11111111
00000000 00000000 00000000 11111111
01000100
00000000 00000000 00000000 01000100
01000100 00010001 11111111 00000001
00000000 01000011
Я использовал другой подход ( bitprint.h ), чтобы заполнить таблицу всеми байтами (в виде битовых строк) и распечатать их на основе байта ввода / индекса. Стоит взглянуть.
void
print_binary(unsigned int n)
{
unsigned int 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');
}
}
Мне понравился код от 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;
}
count
достижении MAXCNT - 1
следующего приращения значение count
будет MAXCNT
равно нулю, что приведет к выходу за пределы массива. Вы должны были сделать count = (count + 1) % MAXCNT
.
MAXCNT + 1
вызовы этой функции в отдельности printf
. В общем, если вы хотите предоставить опцию для более чем 1 вещи, сделайте ее бесконечной. Числа, такие как 4, могут только вызвать проблему.
Одно утверждение универсальное преобразование любого целочисленного типа в двоичное строковое представление с использованием стандартной библиотеки:
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
Или просто: std::cout << std::bitset<sizeof(num) * 8>(num);
Мое решение:
long unsigned int i;
for(i = 0u; i < sizeof(integer) * CHAR_BIT; i++) {
if(integer & LONG_MIN)
printf("1");
else
printf("0");
integer <<= 1;
}
printf("\n");
На основе @ ideasman42 - х внушения в своем ответе, это макрос , который обеспечивает int8
, 16
, 32
& 64
версии, повторное использование в INT8
макрос , чтобы избежать повторения.
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_SEPARATOR
#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_SEPARATOR 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_SEPARATOR 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_SEPARATOR 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
Для удобства чтения вы можете изменить:#define PRINTF_BINARY_SEPARATOR
на #define PRINTF_BINARY_SEPARATOR ","
или#define PRINTF_BINARY_SEPARATOR " "
Это выведет:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
или
My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
Использование:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
Для получения дополнительной информации см. Как напечатать двоичное число через printf .
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);
}
}
должно работать - не проверено.
/* 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" */
Далее покажет вам макет памяти:
#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;
}
Вот небольшой вариант решения 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