Я могу вывести с помощью 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. См. <а href="и http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html"&ГТ; зарегистрироваться _function_printf\&ЛТ;/а&ГТ; для деталей. Можно добавить пользовательское %конверсии B для собственного использования, если это упрощает код приложения, чтобы иметь доступ к ней.
Вот в <а href="и http://codingrelic.geekhold.com/2008/12/printf-acular.html" и GT;пример&ЛТ;/а&ГТ; как реализовать пользовательские функции printf форматов в glibc.
Вы можете использовать маленький столик, чтобы улучшить скорость&ЛТ;суп&ГТ;1&ЛТ;/суп&ГТ;. Подобные методы являются полезными в embedded мире, например, инвертирование байта:
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&ЛТ;/с SUP> Я'м, ссылаясь на встраиваемые приложения, где оптимизаторы не так агрессивно, и разница в скорости видна.
Печать наименьшего значащего бита и сдвиг на право. Делаем это до тех пор, пока число не станет равным нулю печатает двоичное представление числа без ведущих нулей, но в обратном порядке. Используя рекурсию, заказ может быть исправлено довольно легко.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Для меня это одна из самых чистых решений проблемы. Если вам нравится 0В
префикс и завершающий символ новой строки, я предлагаю оборачивать функцию.
На основе @Уильям Уайт'ы ответьте, это макрос, который обеспечивает 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
Здесь'ы на версию функции, которая не страдает от реентерабельность проблемы или ограничения на размер/тип аргумента:
#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's на нужные базы. Использование:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
Где X
- любое целостное выражение.
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 С Е
!
/*
* 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
HTH
Есть ли конвертер функции printf для печати в двоичном формате?
В функции printf()
семья может только распечатать в основание 8, 10 и 16 с помощью стандартных описателей напрямую. Я предлагаю создать функцию, которая преобразует число в строку в код'с особыми нуждами.
Распечатать в любое основание [2-36]
Все остальные ответы до сих пор имеют по крайней мере одно из этих ограничений.
Использование статической памяти для возвращения буфера. Это ограничивает количество раз, когда функция может быть использована в качестве аргумента для функции printf()`.
Выделить память, требующему код на бесплатную указатели.
Требуют вызывающий код, чтобы явно предоставить соответствующий буфер.
Называть функции printf () напрямую. Это обязывает новую функцию для fprintf()
, функции sprintf()
, vsprintf ()
и т. д.
Использовать уменьшенный диапазон целых чисел.
Следующий имеет ни один из перечисленных выше ограничений. Это требует С99 или поздно и использование в "%Ы" и
. Он использует literal_ _compound для обеспечения буферного пространства. Он не имеет никаких проблем с нескольких вызовов в функции 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
Этот код должен обрабатывать ваши потребности до 64 бит. Я создал 2 функции pBin &амп; pBinFill. Оба делают то же самое, но pBinFill заполняет пробелы с fillChar. Функция тестирования генерирует тестовые данные, затем печатает его, используя функцию.
в <предварительно&ГТ;&ЛТ;код&ГТ;
типа char pBinFill(длинный тип int х,шар поэтому, голец fillChar); // вариант с заливкой типа char pBin(длинный тип int х, типа char так); // версия без заполнения на #определять kDisplayWidth 64
голец pBin(длинный тип int х,символ так) { чар ы[kDisplayWidth+1]; int я=kDisplayWidth; с[я -]=0х00; // завершить строку делать { // заполняем массив справа налево с[Я -]=(х &амп; 1) ? '1':'0'; // определить бит х&амп;ГТ;&амп;ГТ;=1; // сдвиг вправо на 1 бит } а( х &амп;ГТ 0); я++; // точка в последний допустимый символ функции sprintf(так, на"%Ы" В,С+я); // вставить его в temp строка строка возвращение так; } &ЛТ;/код&ГТ;&ЛТ;/пре&ГТ;
в <предварительно&ГТ;&ЛТ;код&ГТ; голец pBinFill(длинный тип int х,символ так, чар fillChar) { // заполняем массив справа налево чар ы[kDisplayWidth+1]; int я=kDisplayWidth; с[я -]=0х00; // завершить строку делать { // заполняем массив справа налево с[Я -]=(х &амп; 1) ? '1':'0'; х&амп;ГТ;&амп;ГТ;=1; // сдвиг вправо на 1 бит } а( х &амп;ГТ; 0); пока(я&амп;ГТ;=0) С[я -]=fillChar; // заполнить fillChar функции sprintf(так, на"%Ы" и,ы); возвращение так; } &ЛТ;/код&ГТ;&ЛТ;/пре&ГТ; в <предварительно&ГТ;&ЛТ;код&ГТ; недействительными тест() { Чара так[kDisplayWidth+1]; // буфер для работы pBin длинный вал инт=1; делать { функции printf(" по%ЛД =\т\т%#ЛК =\Т\t0b%я\с N&;, Вэл,Вэл,pBinFill(вал,так,'0')); Вэл*=11; // генерировать тестовые данные } пока (Вэл &амп;ЛТ; 100000000); }
Выход: 00000001 = 0x000001 = 0b00000000000000000000000000000001 00000011 = 0x00000b = 0b00000000000000000000000000001011 00000121 = 0x000079 = 0b00000000000000000000000001111001 00001331 = 0x000533 = 0b00000000000000000000010100110011 00014641 = 0x003931 = 0b00000000000000000011100100110001 00161051 = 0x02751b = 0b00000000000000100111010100011011 01771561 = 0x1b0829 = 0b00000000000110110000100000101001 19487171 = 0x12959c3 = 0b00000001001010010101100111000011 &ЛТ;/код&ГТ;&ЛТ;/пре&ГТ;
Может быть, немного ОТ, но если тебе это нужно только для отладки, чтобы понять или повторить некоторые бинарные операции вы делаете, вы могли бы взглянуть на wcalc (простой калькулятор консоли). С -B параметры, вы получаете двоичного выхода.
например в <предварительно&ГТ; $ wcalc -в ”(256 | 3) &амп; значение 0xFF"и = 0b11 &ЛТ;/пред&ГТ;
В стандартной библиотеке C нет функции форматирования для вывода двоичных данных подобным образом. Все операции форматирования, поддерживаемые семейством printf, направлены на создание текста, читаемого человеком.
Следующая рекурсивная функция может быть полезной:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
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');
}
}
Я оптимизировал лучшие решения для размер и 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;
}
Нет стандартного и портативного способа.
Некоторые реализации предоставляют itoa(), но это не будет в большинстве, и у него несколько некачественный интерфейс. Но код находится за ссылкой и должен позволить вам реализовать свой собственный форматтер довольно легко.
Мне понравился код на Игра paniq, статический буфер-это хорошая идея. Однако это не удается, если вы хотите использовать несколько двоичных форматов в одной функции printf (), потому что она всегда возвращает тот же указатель и перезаписывает массив.
Здесь'ы с падени-в стиле, который вращает указатель на буфер сплит.
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;
}