Tôi có thể in với printf dưới dạng số hex hoặc bát phân. Có một thẻ định dạng để in dưới dạng nhị phân, hoặc cơ sở tùy ý?
Tôi đang chạy gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Tôi có thể in với printf dưới dạng số hex hoặc bát phân. Có một thẻ định dạng để in dưới dạng nhị phân, hoặc cơ sở tùy ý?
Tôi đang chạy gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Câu trả lời:
Hacky nhưng làm việc cho tôi:
#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));
Đối với các loại nhiều byte
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
Bạn cần tất cả các báo giá thêm không may. Cách tiếp cận này có rủi ro hiệu quả của các macro (không chuyển một hàm làm đối số BYTE_TO_BINARY
) nhưng tránh các vấn đề về bộ nhớ và nhiều yêu cầu của strcat trong một số đề xuất khác ở đây.
printf
đó những người có static
bộ đệm không thể.
%d
thành %c
, bởi vì nó thậm chí còn nhanh hơn ( %d
phải thực hiện chuyển đổi chữ số-> char, trong khi %c
chỉ cần đưa ra đối số
int
là 32 bit trên hệ thống, in một giá trị 32 bit sẽ yêu cầu không gian cho các giá trị 32 * 4 byte; tổng cộng 128 byte. Mà, tùy thuộc vào kích thước ngăn xếp, có thể hoặc không thể là một vấn đề.
In nhị phân cho bất kỳ kiểu dữ liệu nào
//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("");
}
kiểm tra
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; )
nghị để tránh size_t
so với int
trận đấu sai.
ptr
(vòng ngoài); sau đó với mỗi bit byte hiện tại (vòng lặp bên trong), che dấu byte bằng bit hiện tại ( 1 << j
). Thay đổi quyền đó dẫn đến một byte chứa 0 ( 0000 0000b
) hoặc 1 ( 0000 0001b
). In ra byte printf với định dạng %u
. HTH.
>
cùng với size_t
không phải là >=
nhận xét của bạn để xác định thời điểm chấm dứt vòng lặp.
>
và >=
với các loại không dấu. 0
là một trường hợp cạnh không dấu và thường xảy ra, không giống như toán học đã ký với ít phổ biến hơn INT_MAX/INT_MIN
.
Dưới đây là một bản hack nhanh để thể hiện các kỹ thuật để làm những gì bạn muốn.
#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
là một phương pháp không hiệu quả khi thêm một char vào chuỗi trên mỗi lần vượt qua của vòng lặp. Thay vào đó, thêm một char *p = b;
và thay thế vòng lặp bên trong bằng *p++ = (x & z) ? '1' : '0'
. z
nên bắt đầu từ 128 (2 ^ 7) thay vì 256 (2 ^ 8). Xem xét cập nhật để đưa một con trỏ đến bộ đệm để sử dụng (để đảm bảo an toàn cho luồng), tương tự như inet_ntoa()
.
strcat()
! Tôi đồng ý rằng điều đó strcat
có thể dễ hiểu hơn so với việc tăng sau một con trỏ được bỏ qua cho bài tập, nhưng ngay cả những người mới bắt đầu cũng cần biết cách sử dụng đúng thư viện chuẩn. Có thể sử dụng một mảng được lập chỉ mục để gán sẽ là một minh chứng tốt (và thực sự sẽ hoạt động, vì b
không được đặt lại thành các số không mỗi khi bạn gọi hàm).
printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.
Bình thường không có công cụ chuyển đổi nhị phân trong glibc.
Có thể thêm các loại chuyển đổi tùy chỉnh vào họ hàm printf () trong glibc. Xem register_printf_function để biết chi tiết. Bạn có thể thêm một chuyển đổi% b tùy chỉnh cho mục đích sử dụng của riêng bạn, nếu nó đơn giản hóa mã ứng dụng để có sẵn nó.
Dưới đây là một ví dụ về cách triển khai định dạng printf tùy chỉnh trong glibc.
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Có một chức năng mới để làm tương tự, mặc dù : register_printf_specifier()
. Một ví dụ về cách sử dụng mới có thể được tìm thấy ở đây: codereview.stackexchange.com/q/219994/200418
Bạn có thể sử dụng một bảng nhỏ để cải thiện tốc độ 1 . Các kỹ thuật tương tự rất hữu ích trong thế giới nhúng, ví dụ, để đảo ngược một byte:
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 Tôi chủ yếu đề cập đến các ứng dụng nhúng trong đó trình tối ưu hóa không quá mạnh và có thể thấy sự khác biệt về tốc độ.
In bit quan trọng nhất và dịch chuyển nó ra bên phải. Làm điều này cho đến khi số nguyên trở thành số không in biểu diễn nhị phân mà không có số 0 đứng đầu nhưng theo thứ tự đảo ngược. Sử dụng đệ quy, thứ tự có thể được sửa chữa khá dễ dàng.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Đối với tôi, đây là một trong những giải pháp sạch nhất cho vấn đề. Nếu bạn thích 0b
tiền tố và một ký tự dòng mới, tôi khuyên bạn nên bọc hàm.
putc('0'+(number&1), stdout);
Dựa trên câu trả lời @William Whyte, đây là một vĩ mô cung cấp int8
, 16
, 32
& 64
các phiên bản, tái sử dụng các INT8
macro để tránh lặp lại.
/* --- 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;
}
Kết quả này:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Để dễ đọc, bạn có thể muốn thêm một dấu phân cách, ví dụ:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
PRINTF_BYTE_TO_BINARY_INT#
định nghĩa được nhóm lại để sử dụng tùy ý.
Đây là phiên bản của hàm không gặp phải vấn đề giới hạn hoặc giới hạn về kích thước / loại đối số:
#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;
}
Lưu ý rằng mã này sẽ hoạt động tốt như nhau đối với bất kỳ cơ sở nào trong khoảng từ 2 đến 10 nếu bạn chỉ thay thế 2 cơ sở bằng cơ sở mong muốn. Cách sử dụng là:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
Trường hợp x
bất kỳ biểu thức tích phân.
char *a = binary_fmt(x), *b = binary_fmt(y);
sẽ không hoạt động như mong đợi. Việc buộc người gọi phải vượt qua một bộ đệm làm cho yêu cầu lưu trữ bùng nổ; người gọi tất nhiên là miễn phí sử dụng bộ đệm tĩnh nếu điều đó thực sự mong muốn, và sau đó việc sử dụng lại bộ đệm đó trở nên rõ ràng. Cũng lưu ý rằng, trên các ABI PIC hiện đại, bộ đệm tĩnh thường tốn nhiều mã để truy cập hơn bộ đệm trên ngăn xếp.
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'
và '0'
thay vì 49
và 48
trong ternary của bạn. Ngoài ra, b
nên dài 9 ký tự để ký tự cuối cùng có thể vẫn là dấu kết thúc null.
static char b[9] = {0}
2. di chuyển khai báo ra khỏi vòng lặp: int z,y;
3. Thêm số không cuối cùng : b[y] = 0
. Cách này không cần tái sinh.
8
nên được thay thế bởi CHAR_BIT
.
Giải pháp nhanh chóng và dễ dàng:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Hoạt động cho bất kỳ loại kích thước và cho ints đã ký và không dấu. '& 1' là cần thiết để xử lý các số nguyên đã ký vì ca làm việc có thể thực hiện gia hạn ký.
Có rất nhiều cách để làm điều này. Đây là một cách cực kỳ đơn giản để in 32 bit hoặc n bit từ loại 32 bit đã ký hoặc không dấu (không đặt âm nếu được ký, chỉ in các bit thực tế) và không trả về vận chuyển. Lưu ý rằng tôi bị giảm trước khi dịch chuyển bit:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
Điều gì về việc trả về một chuỗi với các bit để lưu trữ hoặc in sau này? Bạn có thể phân bổ bộ nhớ và trả lại và người dùng phải giải phóng nó, nếu không bạn trả lại một chuỗi tĩnh nhưng nó sẽ bị ghi đè nếu nó được gọi lại hoặc bởi một luồng khác. Cả hai phương pháp được hiển thị:
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;
}
Gọi với:
// 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);
Không có câu trả lời nào được đăng trước đó chính xác là những gì tôi đang tìm kiếm, vì vậy tôi đã viết một câu trả lời. Thật đơn giản để sử dụng% B với 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);
Một số thời gian chạy hỗ trợ "% b" mặc dù đó không phải là một tiêu chuẩn.
Cũng xem ở đây cho một cuộc thảo luận thú vị:
http://bytes.com/forum/thread591027.html
HTH
Mã này sẽ xử lý nhu cầu của bạn lên đến 64 bit. Tôi đã tạo 2 hàm pBin & pBinFill. Cả hai đều làm điều tương tự, nhưng pBinFill lấp đầy trong các không gian hàng đầu với fillChar. Hàm kiểm tra tạo ra một số dữ liệu kiểm tra, sau đó in ra bằng cách sử dụng chức năng.
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
thay vào đó!
Có một công cụ chuyển đổi printf để in ở định dạng nhị phân?
Các printf()
gia đình duy nhất có khả năng in trong cơ sở 8, 10, và 16 bằng cách sử dụng tiêu chuẩn specifiers trực tiếp. Tôi đề nghị tạo một hàm chuyển đổi số thành chuỗi theo nhu cầu cụ thể của mã.
Để in trong bất kỳ cơ sở nào [2-36]
Tất cả các câu trả lời khác cho đến nay có ít nhất một trong những hạn chế này.
Sử dụng bộ nhớ tĩnh cho bộ đệm trở lại. Điều này giới hạn số lần hàm có thể được sử dụng làm đối số printf()
.
Phân bổ bộ nhớ yêu cầu mã gọi đến con trỏ miễn phí.
Yêu cầu mã gọi để cung cấp một bộ đệm phù hợp.
Gọi printf()
trực tiếp. Này buộc một chức năng mới cho tới fprintf()
, sprintf()
, vsprintf()
vv
Sử dụng một phạm vi số nguyên giảm.
Sau đây không có giới hạn ở trên . Nó không yêu cầu C99 trở lên và sử dụng "%s"
. Nó sử dụng một nghĩa đen để cung cấp không gian bộ đệm. Nó không gặp rắc rối với nhiều cuộc gọi trong a 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;
}
Đầu ra
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
Có thể một chút OT, nhưng nếu bạn chỉ cần điều này để gỡ lỗi để hiểu hoặc truy xuất một số thao tác nhị phân bạn đang thực hiện, bạn có thể xem qua wcalc (một máy tính bảng điều khiển đơn giản). Với các tùy chọn -b, bạn có được đầu ra nhị phân.
ví dụ
$ wcalc -b "(256 | 3) & 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)'
, dc
tiếp 2o
theo là tiếp theo 0x123p
, v.v.
Hàm đệ quy sau có thể hữu ích:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Tôi đã tối ưu hóa giải pháp hàng đầu cho kích thước và C ++ - và đã có giải pháp này:
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
), bạn cũng có thể thoát khỏi static
mảng. Cách đơn giản nhất là chỉ cần bỏ static
vòng loại và tạo b
cục bộ cho hàm.
((x>>z) & 0x01) + '0'
là đủ.
Cách tiếp cận này có các thuộc tính:
#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
Tôi đã sử dụng một cách tiếp cận khác ( bitprint.h ) để điền vào một bảng với tất cả các byte (dưới dạng chuỗi bit) và in chúng dựa trên byte đầu vào / chỉ mục. Thật đáng để xem.
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');
}
}
Tôi thích mã bởi paniq, bộ đệm tĩnh là một ý tưởng tốt. Tuy nhiên, nó không thành công nếu bạn muốn nhiều định dạng nhị phân trong một printf () vì nó luôn trả về cùng một con trỏ và ghi đè lên mảng.
Đây là một kiểu thả xuống kiểu C xoay con trỏ trên bộ đệm chia.
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
đạt đến MAXCNT - 1
, mức tăng tiếp theo count
sẽ làm cho nó MAXCNT
thay vì bằng 0, điều này sẽ khiến quyền truy cập ra khỏi ranh giới của mảng. Bạn nên làm count = (count + 1) % MAXCNT
.
MAXCNT + 1
các cuộc gọi đến chức năng này trong một lần duy nhất printf
. Nói chung, nếu bạn muốn cung cấp tùy chọn cho nhiều hơn 1 điều, hãy làm cho nó vô hạn. Các số như 4 chỉ có thể gây ra vấn đề.
Một câu lệnh chuyển đổi chung của bất kỳ loại tích phân nào thành biểu diễn chuỗi nhị phân bằng thư viện chuẩn :
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
Hoặc chỉ: std::cout << std::bitset<sizeof(num) * 8>(num);
Giải pháp của tôi:
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");
Dựa trên đề nghị @ ideasman42 trong câu trả lời của mình, đây là một vĩ mô cung cấp int8
, 16
, 32
& 64
các phiên bản, tái sử dụng các INT8
macro để tránh lặp lại.
/* --- 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;
}
Kết quả này:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Để dễ đọc, bạn có thể thay đổi: #define PRINTF_BINARY_SEPARATOR
thành #define PRINTF_BINARY_SEPARATOR ","
hoặc#define PRINTF_BINARY_SEPARATOR " "
Điều này sẽ xuất ra:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
hoặc là
My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
Sử dụng:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
Để biết thêm tham khảo, hãy xem Cách in số nhị phân qua 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);
}
}
nên làm việc - chưa được kiểm tra.
/* 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" */
Tiếp theo sẽ hiển thị cho bạn bố trí bộ nhớ:
#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;
}
Đây là một biến thể nhỏ của giải pháp paniq sử dụng các mẫu để cho phép in các số nguyên 32 và 64 bit:
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);
}
Và có thể được sử dụng như:
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() );
Đây là kết quả:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000