Я могу печатать с 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 в некоторых других предложениях здесь.
Печать двоичного кода для любого типа данных
//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;
}
Вот быстрый хак, чтобы продемонстрировать методы, чтобы делать то, что вы хотите.
#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;
}
В glibc обычно нет спецификатора двоичного преобразования.
Можно добавить собственные типы конверсий в семейство функций printf() в glibc. Подробнее см. register_printf_function. Вы можете добавить пользовательское преобразование% b для собственного использования, если оно упростит код приложения, чтобы он был доступен.
Вот пример о том, как реализовать пользовательские форматы printf в glibc.
Вы можете использовать небольшую таблицу для повышения скорости 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 В основном я имею в виду встроенные приложения, в которых оптимизаторы не так агрессивны и разница в скорости видима.
Здесь версия функции, которая не страдает от проблем с повторной установкой или ограничений на размер/тип аргумента:
#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
- любое интегральное выражение.
На основе ответа @William Whyte это макрос, который предоставляет версии int8
, 16
, 32
и 64
, повторно используя макрос int8
, чтобы избежать повторения.
/* --- PRINTF_BYTE_TO_BINARY macro --- */
#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
Распечатайте младший бит и сдвиньте его справа. Выполняя это до тех пор, пока целое число не станет равным нулю, печатает двоичное представление без начальных нулей, но в обратном порядке. Используя рекурсию, порядок можно легко скорректировать.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Для меня это одно из самых чистых решений проблемы. Если вам нравится префикс 0b
и новый новый символ строки, я предлагаю обернуть функцию.
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;
}
Ни один из ранее опубликованных ответов не является тем, что я искал, поэтому я написал один. Очень просто использовать% 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);
}
Некоторые временные ряды поддерживают "% 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
В стандартной библиотеке C нет функции форматирования для вывода двоичного файла. Все операции с форматом, поддерживаемые семейством printf, относятся к читаемому человеку тексту.
Может быть, немного OT, но если вам нужно это только для отладки, чтобы понять или повторить некоторые бинарные операции, которые вы делаете, вы можете взглянуть на wcalc (простой консольный калькулятор). С параметрами -b вы получаете двоичный вывод.
например.
$ wcalc -b "(256 | 3) & 0xff" = 0b11
Я оптимизировал верхнее решение для размера и С++ - и нашел это решение:
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;
}
Может оказаться полезной следующая рекурсивная функция:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Есть ли конвертер 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
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');
}
}
Нет стандартного и портативного способа.
Некоторые реализации предоставляют itoa(), но это не будет в большинстве, и у него есть несколько crummy интерфейс. Но код находится за ссылкой и должен позволить вам легко реализовать свой собственный форматировщик.
Мне понравился код 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;
}
Мое решение:
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");
Этот подход имеет следующие атрибуты:
#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), чтобы заполнить таблицу со всеми байтами (как битовые строки) и печатать их на основе байта ввода/индекса. Это стоит взглянуть.
На основе предложения @ideaman42 в его ответе это макрос, который предоставляет версии int8
, 16
, 32
и 64
, повторно используя макрос int8
, чтобы избежать повторения.
/* --- PRINTF_BYTE_TO_BINARY macro --- */
#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
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);
}
}
должен работать - непроверенный.
#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();
}
/* Convert an int to it 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
Еще один подход к печати в двоичном формате: Преобразовать целое число сначала.
Чтобы напечатать 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
}
Я просто хочу опубликовать свое решение. Он использовал для получения нулей и единиц одного байта, но вызов этой функции несколько раз может быть использован для больших блоков данных. Я использую его для 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);
}