ฉันสามารถพิมพ์ด้วย 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
ไบต์ส่งผลให้มีรูปแบบ HTH
>
กับ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;
ควรเริ่มต้นที่ 128 (2 ^ 7) แทน 256 (2 ^ 8) พิจารณาปรับปรุงเพื่อใช้เป็นตัวชี้การบัฟเฟอร์กับการใช้งาน (เพื่อความปลอดภัยด้าย) เพื่อที่คล้ายกัน *p++ = (x & z) ? '1' : '0'
z
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#
กำหนดรุ่นที่จัดกลุ่มไว้เพื่อเลือกใช้
นี่เป็นเวอร์ชั่นของฟังก์ชั่นที่ไม่ได้รับผลกระทบจากปัญหา reentrancy หรือข้อ จำกัด เกี่ยวกับขนาด / ประเภทของการโต้แย้ง:
#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);
จะไม่ทำงานตามที่คาดไว้ การบังคับให้ผู้เรียกส่งผ่านบัฟเฟอร์ทำให้เกิดความต้องการหน่วยเก็บข้อมูล แน่นอนว่าผู้เรียกใช้อิสระในการใช้บัฟเฟอร์แบบคงที่หากต้องการจริงๆแล้วการใช้บัฟเฟอร์เดิมซ้ำอีกครั้งจะกลายเป็นชัดเจน โปรดทราบด้วยว่าใน ABI ของ PIC แบบทันสมัยบัฟเฟอร์แบบคงที่มักจะต้องเสียค่าใช้จ่ายในการเข้าถึงรหัสมากกว่าบัฟเฟอร์บนสแต็ก
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 อักขระเพื่อให้อักขระตัวสุดท้ายสามารถยังคงเป็น terminator แบบ null ได้
static char b[9] = {0}
2. ประกาศย้ายออกจากวง: int z,y;
3 b[y] = 0
เพิ่มสุดท้ายศูนย์: วิธีนี้ไม่จำเป็นต้องเริ่มต้นใหม่
8
CHAR_BIT
วิธีแก้ปัญหาที่ง่ายและรวดเร็ว:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
ใช้งานได้กับทุกขนาดและสำหรับ ints ที่ลงชื่อและไม่ได้ลงชื่อ ต้องการ '& 1' เพื่อจัดการ ints ที่ลงนามเนื่องจากการเปลี่ยนแปลงอาจทำส่วนขยายสัญญาณ
มีหลายวิธีในการทำเช่นนี้ ต่อไปนี้เป็นวิธีที่ง่ายมากสำหรับการพิมพ์ 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);
Runtimes บางตัวรองรับ "% b" แม้ว่าจะไม่ได้มาตรฐาน
ดูที่นี่สำหรับการสนทนาที่น่าสนใจ:
http://bytes.com/forum/thread591027.html
HTH
รหัสนี้ควรรองรับความต้องการของคุณมากถึง 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 โดยใช้ specifiers มาตรฐานโดยตรง ฉันขอแนะนำให้สร้างฟังก์ชันที่แปลงตัวเลขเป็นสตริงตามความต้องการเฉพาะของรหัส
หากต้องการพิมพ์ในฐานใด ๆ [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 ++ - ness และไปที่วิธีนี้:
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 อาจทำให้เกิดปัญหาได้เท่านั้น
ไม่มีวิธีมาตรฐานและพกพา
การใช้งานบางอย่างให้itoa ()แต่มันจะไม่เป็นส่วนใหญ่และมีอินเทอร์เฟซที่ค่อนข้างร่วน แต่โค้ดอยู่หลังลิงค์และควรให้คุณใช้ฟอร์แมตเตอร์ของคุณเองได้อย่างง่ายดาย
การแปลงหนึ่งชุดคำสั่งสามัญประเภทใด ๆลงในการแทนสตริงไบนารีโดยใช้ไลบรารีมาตรฐาน :
#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