Saya dapat mencetak dengan printf sebagai angka hex atau oktal. Apakah ada tag format untuk dicetak sebagai biner, atau basis arbitrer?
Saya menjalankan gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Saya dapat mencetak dengan printf sebagai angka hex atau oktal. Apakah ada tag format untuk dicetak sebagai biner, atau basis arbitrer?
Saya menjalankan gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Jawaban:
Meretas tetapi bekerja untuk saya:
#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));
Untuk tipe multi-byte
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
Sayangnya, Anda membutuhkan semua kutipan tambahan. Pendekatan ini memiliki risiko efisiensi makro (jangan melewati fungsi sebagai argumen untuk BYTE_TO_BINARY) tetapi menghindari masalah memori dan beberapa pemanggilan strcat dalam beberapa proposal lainnya di sini.
printfmana yang dengan staticbuffer tidak bisa.
%dke %c, karena harus lebih cepat ( %dharus melakukan konversi digit-> char, sementara %chanya mengeluarkan argumen
int32-bit pada sistem, mencetak nilai 32-bit tunggal akan membutuhkan ruang untuk nilai 32 * 4-byte; total 128 byte. Yang, tergantung pada ukuran tumpukan, mungkin atau mungkin tidak menjadi masalah.
Cetak Biner untuk Semua Datatype
//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("");
}
uji
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; )untuk menghindari size_tvs intsalah pertandingan.
ptr(loop luar); lalu untuk setiap bit byte saat ini (loop dalam), tutup byte dengan bit saat ini ( 1 << j). Geser ke kanan yang menghasilkan byte yang berisi 0 ( 0000 0000b) atau 1 ( 0000 0001b). Cetak byte printf yang dihasilkan dengan format %u. HTH.
>dengan size_tdan bukan >=dari komentar Anda untuk menentukan kapan harus mengakhiri loop.
>dan >=dengan tipe yang tidak ditandatangani. 0adalah kasus tepi yang tidak ditandatangani dan sering terjadi, tidak seperti matematika yang ditandatangani dengan yang kurang umum INT_MAX/INT_MIN.
Berikut ini adalah retasan cepat untuk menunjukkan teknik untuk melakukan apa yang Anda inginkan.
#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;
}
strcatadalah metode yang tidak efisien untuk menambahkan karakter tunggal ke string pada setiap lintasan loop. Sebagai gantinya, tambahkan char *p = b;dan ganti loop dalam dengan *p++ = (x & z) ? '1' : '0'. zharus dimulai pada 128 (2 ^ 7), bukan 256 (2 ^ 8). Coba perbarui untuk mengambil pointer ke buffer yang akan digunakan (untuk keamanan thread), mirip dengan inet_ntoa().
strcat()! Saya setuju bahwa strcatmungkin lebih mudah dipahami daripada menambahkan pointer dereferenced setelah penugasan, tetapi bahkan pemula perlu tahu cara menggunakan perpustakaan standar dengan benar. Mungkin menggunakan array yang diindeks untuk tugas akan menjadi demonstrasi yang baik (dan benar-benar akan berfungsi, karena btidak disetel ulang ke all-nol setiap kali Anda memanggil fungsi).
printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4)).
Biasanya tidak ada specifier konversi biner di glibc.
Dimungkinkan untuk menambahkan jenis konversi khusus ke keluarga fungsi printf () di glibc. Lihat register_printf_fungsi untuk detailnya. Anda dapat menambahkan konversi% b kustom untuk penggunaan Anda sendiri, jika itu menyederhanakan kode aplikasi agar tersedia.
Berikut adalah contoh cara menerapkan format printf kustom di glibc.
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]Ada fungsi baru untuk melakukan hal yang sama, meskipun: register_printf_specifier(). Contoh penggunaan baru dapat ditemukan di sini: codereview.stackexchange.com/q/219994/200418
Anda bisa menggunakan meja kecil untuk meningkatkan kecepatan 1 . Teknik serupa berguna di dunia tertanam, misalnya, untuk membalikkan 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 Saya kebanyakan mengacu pada aplikasi yang dibenamkan di mana pengoptimal tidak begitu agresif dan perbedaan kecepatan terlihat.
Cetak bit yang paling tidak signifikan dan geser keluar di sebelah kanan. Melakukan ini sampai bilangan bulat menjadi nol mencetak representasi biner tanpa memimpin nol tetapi dalam urutan terbalik. Menggunakan rekursi, pesanan dapat dikoreksi dengan mudah.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Bagi saya, ini adalah salah satu solusi terbersih untuk masalah ini. Jika Anda menyukai 0bawalan dan karakter baris baru yang tertinggal, saya sarankan membungkus fungsi.
putc('0'+(number&1), stdout);
Berdasarkan jawaban @William Whyte, ini adalah makro yang menyediakan int8, 16, 32& 64versi, menggunakan kembali INT8makro untuk menghindari pengulangan.
/* --- 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;
}
Output ini:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Untuk keterbacaan, Anda mungkin ingin menambahkan pemisah misalnya:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
PRINTF_BYTE_TO_BINARY_INT#definisi yang dikelompokkan untuk digunakan secara opsional.
Berikut adalah versi fungsi yang tidak mengalami masalah reentrancy atau batasan ukuran / jenis argumen:
#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;
}
Perhatikan bahwa kode ini akan berfungsi dengan baik untuk setiap pangkalan antara 2 dan 10 jika Anda hanya mengganti 2 dengan pangkalan yang diinginkan. Penggunaannya adalah:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
Di mana xada ekspresi integral.
char *a = binary_fmt(x), *b = binary_fmt(y);tidak akan berfungsi seperti yang diharapkan. Memaksa penelepon untuk melewati buffer membuat persyaratan penyimpanannya jelas; penelepon tentu saja bebas menggunakan buffer statis jika itu benar-benar diinginkan, dan kemudian menggunakan kembali buffer yang sama menjadi eksplisit. Juga perhatikan bahwa, pada PIC ABI modern, buffer statis biasanya membutuhkan lebih banyak kode untuk diakses daripada buffer pada stack.
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'dan '0'bukannya 49dan 48di ternary Anda. Juga, bharus sepanjang 9 karakter sehingga karakter terakhir dapat tetap menjadi terminator nol.
static char b[9] = {0}2. Langkah deklarasi keluar dari loop: int z,y;3. Tambahkan akhir nol: b[y] = 0. Dengan cara ini tidak diperlukan reinitalization.
8itu harus diganti oleh CHAR_BIT.
Solusi cepat dan mudah:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Bekerja untuk semua jenis ukuran dan untuk int yang ditandatangani dan tidak ditandatangani. Tanda '& 1' diperlukan untuk menangani int yang ditandatangani karena shift mungkin melakukan ekstensi sign.
Ada banyak cara untuk melakukan ini. Inilah yang super sederhana untuk mencetak 32 bit atau n bit dari jenis 32 bit yang ditandatangani atau tidak ditandatangani (tidak menempatkan negatif jika ditandatangani, hanya mencetak bit yang sebenarnya) dan tidak ada carriage return. Perhatikan bahwa saya dikurangi sebelum bit shift:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
Bagaimana dengan mengembalikan string dengan bit untuk disimpan atau dicetak nanti? Anda dapat mengalokasikan memori dan mengembalikannya dan pengguna harus membebaskannya, atau Anda mengembalikan string statis tetapi itu akan musnah jika dipanggil lagi, atau dengan utas lainnya. Kedua metode yang ditampilkan:
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;
}
Telepon dengan:
// 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);
Tidak ada jawaban yang diposting sebelumnya persis apa yang saya cari, jadi saya menulis satu. Sangat mudah menggunakan% B dengan 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);
Beberapa runtime mendukung "% b" walaupun itu bukan standar.
Lihat juga di sini untuk diskusi yang menarik:
http://bytes.com/forum/thread591027.html
HTH
Kode ini harus menangani kebutuhan Anda hingga 64 bit. Saya membuat 2 fungsi pBin & pBinFill. Keduanya melakukan hal yang sama, tetapi pBinFill mengisi ruang terkemuka dengan fillChar. Fungsi uji menghasilkan beberapa data uji, lalu mencetaknya menggunakan fungsi tersebut.
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!
Apakah ada konverter printf untuk mencetak dalam format biner?
The printf()keluarga hanya mampu mencetak dalam basis 8, 10, dan 16 dengan menggunakan penentu standar langsung. Saya sarankan membuat fungsi yang mengubah angka menjadi string per kebutuhan khusus kode.
Untuk mencetak basis apa pun [2-36]
Semua jawaban lain sejauh ini memiliki setidaknya satu dari keterbatasan ini.
Gunakan memori statis untuk buffer kembali. Ini membatasi berapa kali fungsi dapat digunakan sebagai argumen printf().
Alokasikan memori yang membutuhkan kode panggilan ke pointer gratis.
Memerlukan kode panggilan untuk secara eksplisit menyediakan buffer yang sesuai.
Hubungi printf()langsung. Ini mewajibkan fungsi baru untuk untuk fprintf(), sprintf(), vsprintf(), dll
Gunakan rentang integer yang dikurangi.
Berikut ini tidak memiliki batasan di atas . Itu membutuhkan C99 atau lebih baru dan penggunaan "%s". Ini menggunakan senyawa literal untuk menyediakan ruang buffer. Tidak memiliki masalah dengan beberapa panggilan dalam 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;
}
Keluaran
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
Mungkin sedikit OT, tetapi jika Anda hanya membutuhkan ini untuk debug untuk memahami atau menelusuri kembali beberapa operasi biner yang Anda lakukan, Anda mungkin melihat wcalc (kalkulator konsol sederhana). Dengan opsi -b Anda mendapatkan output biner.
misalnya
$ wcalc -b "(256 | 3) & 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)', dcdiikuti oleh 2odiikuti oleh 0x123p, dan sebagainya.
Tidak ada fungsi format di pustaka standar C untuk menghasilkan biner seperti itu. Semua operasi format yang didukung keluarga printf adalah terhadap teks yang dapat dibaca manusia.
Fungsi rekursif berikut mungkin berguna:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Saya mengoptimalkan solusi teratas untuk ukuran dan C ++ - ness, dan mendapatkan solusi ini:
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), Anda mungkin juga menyingkirkan staticarray. Cara paling sederhana adalah dengan hanya menjatuhkan statickualifikasi dan menjadikan blokal ke fungsi.
((x>>z) & 0x01) + '0'Cukup.
Pendekatan ini memiliki atribut:
#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
Saya telah menggunakan pendekatan lain ( bitprint.h ) untuk mengisi tabel dengan semua byte (sebagai string bit) dan mencetaknya berdasarkan input / index byte. Layak untuk dilihat.
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');
}
}
Saya menyukai kode oleh paniq, buffer statis adalah ide yang bagus. Namun gagal jika Anda ingin beberapa format biner dalam printf tunggal () karena selalu mengembalikan pointer yang sama dan menimpa array.
Ini adalah drop-in gaya C yang memutar pointer pada buffer split.
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;
}
countmencapai MAXCNT - 1, penambahan berikutnya countakan membuatnya MAXCNTbukan nol, yang akan menyebabkan akses keluar dari batas-batas array. Anda seharusnya melakukannya count = (count + 1) % MAXCNT.
MAXCNT + 1panggilan ke fungsi ini dalam satu printf. Secara umum, jika Anda ingin memberikan opsi untuk lebih dari 1 hal, buatlah tak terbatas. Angka seperti 4 hanya dapat menyebabkan masalah.
Satu pernyataan konversi generik dari semua tipe integral ke representasi string biner menggunakan pustaka standar :
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
Atau hanya: std::cout << std::bitset<sizeof(num) * 8>(num);
Solusi saya:
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");
Berdasarkan saran @ ideasman42 di jawabannya, ini adalah makro yang menyediakan int8, 16, 32& 64versi, menggunakan kembali INT8makro untuk menghindari pengulangan.
/* --- 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;
}
Output ini:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Untuk keterbacaan, Anda dapat mengubah: #define PRINTF_BINARY_SEPARATORmenjadi#define PRINTF_BINARY_SEPARATOR "," atau#define PRINTF_BINARY_SEPARATOR " "
Ini akan menampilkan:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
atau
My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
Menggunakan:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
Untuk referensi lebih lanjut, lihat Cara mencetak nomor biner melalui 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);
}
}
harus bekerja - belum diuji.
/* 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" */
Berikutnya akan menunjukkan kepada Anda tata letak memori:
#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;
}
Berikut ini adalah variasi kecil dari solusi paniq yang menggunakan templat untuk memungkinkan pencetakan integer 32 dan 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);
}
Dan bisa digunakan seperti:
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() );
Inilah hasilnya:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000