มีตัวแปลง printf เพื่อพิมพ์ในรูปแบบไบนารีหรือไม่?


434

ฉันสามารถพิมพ์ด้วย printf เป็นเลขฐานสิบหกหรือฐานแปด มีแท็กรูปแบบที่จะพิมพ์เป็นไบนารีหรือฐานโดยพลการหรือไม่?

ฉันกำลังเรียกใช้ gcc

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"

คุณไม่สามารถทำได้เท่าที่ฉันรู้โดยใช้ printf เห็นได้ชัดว่าคุณสามารถเขียนวิธีช่วยเพื่อทำสิ่งนี้ให้สำเร็จ แต่นั่นไม่ได้เสียงเหมือนทิศทางที่คุณต้องการไป
Ian P

ไม่มีรูปแบบที่กำหนดไว้ล่วงหน้าสำหรับสิ่งนั้น คุณจำเป็นต้องแปลงมันเป็นสตริงแล้วพิมพ์สตริง
rslite

การค้นหาโดย Google อย่างรวดเร็วทำให้หน้านี้มีข้อมูลบางอย่างที่อาจเป็นประโยชน์: forums.macrumors.com/archive/index.php/t-165959.html
Ian P

12
ไม่ได้เป็นส่วนหนึ่งของ ANSI Standard C Library - หากคุณกำลังเขียนโค้ดแบบพกพาวิธีที่ปลอดภัยที่สุดคือการหมุนของคุณเอง
tomlogic

หนึ่งคำสั่งมาตรฐานและแบบทั่วไป (สำหรับประเภทอินทิกรัลใด ๆ ก็ได้) ของการแปลงเป็นสตริงสตริงบน C ++: stackoverflow.com/a/31660310/1814353
luart

คำตอบ:


266

แฮ็ก แต่ใช้ได้สำหรับฉัน:

#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 หลายครั้งในข้อเสนออื่น ๆ ที่นี่


13
และยังมีข้อดีอีกอย่างที่สามารถเรียกคืนได้หลายครั้งprintfซึ่งสิ่งที่staticบัฟเฟอร์ไม่สามารถทำได้
Patrick Schlüter

4
ฉันเอาเสรีภาพที่จะเปลี่ยน%dไป%cเพราะมันควรจะเป็นได้เร็วยิ่งขึ้น ( %dมีการดำเนินการ digit-> ถ่านแปลงในขณะที่%cเพียงแค่เอาท์พุทอาร์กิวเมนต์

3
โพสต์เวอร์ชันขยายของแมโครนี้ด้วยการสนับสนุน int 16, 32, 64 บิต: stackoverflow.com/a/25108449/432509
คิด man42 42

2
โปรดทราบว่าวิธีนี้ไม่เป็นมิตรกับกองซ้อน สมมติว่าintเป็น 32- บิตบนระบบการพิมพ์ค่า 32- บิตเดียวจะต้องการพื้นที่สำหรับค่า 32 * 4 ไบต์ รวม 128 ไบต์ ซึ่งขึ้นอยู่กับขนาดสแต็กอาจหรืออาจจะไม่เป็นปัญหา
694733

1
สิ่งสำคัญคือการเพิ่มวงเล็บรอบ ๆ ไบต์ในแมโครหรือคุณอาจพบปัญหาเมื่อส่งการดำเนินการ BYTE_TO_BINARY (a | b) -> a | b & 0x01! = (a | b) & 0x01
Ivan Hoffmann

203

พิมพ์ไบนารีสำหรับประเภทข้อมูลใด ๆ

//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;
}

8
แนะนำsize_t i; for (i=size; i-- > 0; )ให้หลีกเลี่ยงsize_tและintจับคู่ผิด
chux - Reinstate Monica

1
มีใครช่วยอธิบายรายละเอียดเกี่ยวกับตรรกะที่อยู่เบื้องหลังรหัสนี้ได้ไหม
jII

2
ใช้แต่ละไบต์ในptr(วงรอบนอก); จากนั้นสำหรับไบต์ปัจจุบัน (วงใน) แต่ละบิตให้ปิดบังไบต์ด้วยบิตปัจจุบัน ( 1 << j) เลื่อนไปทางขวาส่งผลให้เกิดไบต์ที่มี 0 ( 0000 0000b) หรือ 1 ( 0000 0001b) พิมพ์ printf %uไบต์ส่งผลให้มีรูปแบบ HTH
nielsbot

1
@ ZX9 สังเกตว่ารหัสที่ใช้>กับsize_tและไม่ใช่>=ความคิดเห็นของคุณเพื่อพิจารณาว่าเมื่อใดที่จะยุติการวนซ้ำ
chux - Reinstate Monica

3
@ ZX9 ยังเป็นความคิดเห็นดั้งเดิมที่มีประโยชน์สำหรับคุณเนื่องจากผู้เขียนจำเป็นต้องระมัดระวังในการพิจารณาการใช้เคส >และ>=ชนิดที่ไม่ได้ลงนาม เป็นกรณีที่ขอบไม่ได้ลงนามและมักเกิดขึ้นแตกต่างจากคณิตศาสตร์เซ็นสัญญากับร่วมกันน้อยลง0 INT_MAX/INT_MIN
chux - Reinstate Monica

151

นี่คือแฮ็คด่วนเพื่อสาธิตเทคนิคการทำสิ่งที่คุณต้องการ

#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;
}

2
นี่คือ "แปลก" น้อยกว่าการเขียนแบบกำหนดเองเกินพิกัดที่หลีกเลี่ยงสำหรับ printf มันง่ายที่จะเข้าใจสำหรับนักพัฒนาที่เพิ่งรู้รหัสเช่นกัน
Coder Furious

43
การเปลี่ยนแปลงเล็กน้อย: strcatเป็นวิธีที่ไม่มีประสิทธิภาพในการเพิ่มอักขระตัวเดียวในสตริงในแต่ละรอบของลูป แต่เพิ่มและแทนที่ภายในวงด้วย char *p = b; ควรเริ่มต้นที่ 128 (2 ^ 7) แทน 256 (2 ^ 8) พิจารณาปรับปรุงเพื่อใช้เป็นตัวชี้การบัฟเฟอร์กับการใช้งาน (เพื่อความปลอดภัยด้าย) เพื่อที่คล้ายกัน *p++ = (x & z) ? '1' : '0'zinet_ntoa()
tomlogic

3
@EvilTeach: คุณใช้ผู้ประกอบการที่ประกอบไปด้วยตัวเองเป็นพารามิเตอร์สำหรับstrcat()! ฉันยอมรับว่าstrcatอาจจะง่ายต่อการเข้าใจมากกว่าการเพิ่มตัวชี้ภายหลังลงทะเบียนสำหรับการกำหนด แต่ผู้เริ่มต้นจำเป็นต้องรู้วิธีใช้ไลบรารีมาตรฐานอย่างถูกต้อง บางทีการใช้อาเรย์แบบดัชนีสำหรับการมอบหมายอาจเป็นการสาธิตที่ดี (และใช้งานได้จริงเนื่องจากbไม่ได้รีเซ็ตเป็นศูนย์ทั้งหมดทุกครั้งที่คุณเรียกใช้ฟังก์ชัน)
tomlogic

3
สุ่ม: ถ่านบัฟเฟอร์ฐานสองเป็นแบบคงที่และจะถูกล้างไปที่ศูนย์ทั้งหมดในการมอบหมาย สิ่งนี้จะล้างเฉพาะในครั้งแรกที่เรียกใช้และหลังจากนั้นจะไม่ชัดเจน แต่ใช้ค่าสุดท้ายแทน
markwatson

8
printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))นอกจากนี้ควรจัดทำเอกสารผลก่อนหน้านี้จะไม่ถูกต้องหลังจากเรียกฟังก์ชั่นอีกครั้งเพื่อให้สายที่ไม่ควรพยายามที่จะใช้มันเช่นนี้
Paŭlo Ebermann

84

ไม่มีตัวระบุการแปลงแบบไบนารีใน glibc ตามปกติ

เป็นไปได้ที่จะเพิ่มประเภทการแปลงที่กำหนดเองไปยังตระกูลของฟังก์ชัน printf () ใน glibc ดูregister_printf_functionสำหรับรายละเอียด คุณสามารถเพิ่มการแปลง% b ที่กำหนดเองสำหรับการใช้งานของคุณเองถ้ามันง่ายรหัสแอปพลิเคชันที่จะให้มันใช้ได้

นี่คือตัวอย่างของวิธีการใช้รูปแบบ printf ที่กำหนดเองใน glibc


ฉันมักจะเขียน v [snf] printf () ของฉันเองสำหรับกรณีที่ จำกัด ซึ่งฉันต้องการ radixs ที่แตกต่างกัน: ดีใจที่ฉันค้นพบสิ่งนี้
Jamie

3
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]มีฟังก์ชั่นใหม่ให้ทำเช่นเดียวกัน: register_printf_specifier(). ตัวอย่างของการใช้งานใหม่สามารถพบได้ที่นี่: codereview.stackexchange.com/q/219994/200418
Cacahuete Frito

47

คุณสามารถใช้ตารางขนาดเล็กเพื่อเพิ่มความเร็ว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ฉันส่วนใหญ่อ้างถึงแอพพลิเคชั่นที่ฝังตัวซึ่งเครื่องมือเพิ่มประสิทธิภาพไม่ก้าวร้าวมากและเห็นความแตกต่างของความเร็ว


27

พิมพ์บิตที่มีนัยสำคัญน้อยที่สุดและเลื่อนออกทางด้านขวา การทำเช่นนี้จนกระทั่งจำนวนเต็มกลายเป็นศูนย์พิมพ์ตัวแทนไบนารีโดยไม่ต้องนำศูนย์ แต่ในลำดับที่กลับรายการ การใช้การเรียกซ้ำคำสั่งซื้อสามารถแก้ไขได้ค่อนข้างง่าย

#include <stdio.h>

void print_binary(int number)
{
    if (number) {
        print_binary(number >> 1);
        putc((number & 1) ? '1' : '0', stdout);
    }
}

สำหรับฉันนี่เป็นหนึ่งในวิธีการแก้ปัญหาที่สะอาดที่สุด หากคุณชอบ0bคำนำหน้าและอักขระบรรทัดใหม่ที่ต่อท้ายฉันขอแนะนำให้ใช้ฟังก์ชัน

การสาธิตออนไลน์


ข้อผิดพลาด: มีอาร์กิวเมนต์น้อยเกินไปสำหรับการเรียกใช้ฟังก์ชันคาดว่า 2 มี 1 putc ((หมายเลข & 1) หรือไม่ '1': '0');
Koray Tugay

@KorayTugay ขอขอบคุณที่ชี้ว่า ฉันแก้ไขการเรียกฟังก์ชันและเพิ่มการสาธิต
danijar

6
คุณควรใช้หมายเลข int ที่ไม่ได้ลงชื่อเพราะเมื่อหมายเลขที่กำหนดเป็นลบฟังก์ชันจะเข้าสู่การเรียกซ้ำแบบไม่สิ้นสุด
Puffy

วิธีที่มีประสิทธิภาพมากขึ้นตั้งแต่ใน ASCII '0' + 1 = '1':putc('0'+(number&1), stdout);
Roger Dueck

22

ขึ้นอยู่กับคำตอบ @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

มันยอดเยี่ยมมาก มีเหตุผลพิเศษสำหรับการพิมพ์บิตที่เริ่มต้นด้วยบิตที่สำคัญน้อยที่สุดหรือไม่?
gaganso

2
คุณจะแนะนำให้เพิ่มเครื่องหมายจุลภาคอย่างไร
nmz787

จะเพิ่มการPRINTF_BYTE_TO_BINARY_INT#กำหนดรุ่นที่จัดกลุ่มไว้เพื่อเลือกใช้
ideasman42

16

นี่เป็นเวอร์ชั่นของฟังก์ชั่นที่ไม่ได้รับผลกระทบจากปัญหา 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การแสดงออกที่สำคัญใด ๆอยู่ที่ไหน


7
ใช่คุณสามารถทำได้ แต่มันเป็นการออกแบบที่แย่จริงๆ แม้ว่าคุณจะไม่มีเธรดหรือการแสดงซ้ำผู้เรียกต้องทราบว่าบัฟเฟอร์แบบสแตติกกำลังถูกนำมาใช้ซ้ำและสิ่งต่าง ๆ เช่นchar *a = binary_fmt(x), *b = binary_fmt(y);จะไม่ทำงานตามที่คาดไว้ การบังคับให้ผู้เรียกส่งผ่านบัฟเฟอร์ทำให้เกิดความต้องการหน่วยเก็บข้อมูล แน่นอนว่าผู้เรียกใช้อิสระในการใช้บัฟเฟอร์แบบคงที่หากต้องการจริงๆแล้วการใช้บัฟเฟอร์เดิมซ้ำอีกครั้งจะกลายเป็นชัดเจน โปรดทราบด้วยว่าใน ABI ของ PIC แบบทันสมัยบัฟเฟอร์แบบคงที่มักจะต้องเสียค่าใช้จ่ายในการเข้าถึงรหัสมากกว่าบัฟเฟอร์บนสแต็ก
. GitHub หยุดช่วยน้ำแข็ง

8
นั่นยังคงเป็นการออกแบบที่ไม่ดี มันต้องมีขั้นตอนการทำสำเนาเพิ่มเติมในกรณีเหล่านั้นและมันก็ไม่แพงไปกว่าการที่ผู้โทรจัดเตรียมบัฟเฟอร์แม้แต่ในกรณีที่ไม่จำเป็นต้องคัดลอก การใช้ที่จัดเก็บข้อมูลแบบคงที่เป็นเพียงสำนวนที่ไม่ดี
. GitHub หยุดช่วยน้ำแข็ง

3
ต้องทำให้เนมสเปซเป็นมลภาวะของตารางตัวประมวลผลล่วงหน้าหรือสัญลักษณ์สัญลักษณ์ตัวแปรที่มีชื่อพิเศษที่ไม่จำเป็นซึ่งจะต้องใช้เพื่อปรับขนาดหน่วยเก็บข้อมูลที่ถูกจัดสรรโดยผู้เรียกทุกคนอย่างเหมาะสมและบังคับให้ผู้เรียกทุกคนรู้ค่านี้ การจัดเก็บข้อมูลเป็นการออกแบบที่ไม่ดีเมื่อโซลูชันหน่วยความจำภายในฟังก์ชันที่เรียบง่ายจะเพียงพอสำหรับความต้องการและจุดประสงค์ส่วนใหญ่และเมื่อการโทร strdup () แบบง่ายครอบคลุม 99% ของการใช้งานที่เหลือทั้งหมด
Greg A. Woods

5
ที่นี่เราจะต้องไม่เห็นด้วย ฉันไม่เห็นวิธีการเพิ่มสัญลักษณ์ preprocessor ที่ไม่สร้างความรำคาญมาที่ใดก็ได้ใกล้กับความเป็นอันตรายของการ จำกัด กรณีการใช้งานอย่างรุนแรงทำให้ข้อผิดพลาดของส่วนต่อประสานการสำรองพื้นที่เก็บข้อมูลถาวรตลอดระยะเวลาของโปรแกรมสำหรับค่าชั่วคราว แพลตฟอร์มที่ทันสมัย
. GitHub หยุดช่วยน้ำแข็ง

5
ฉันไม่สนับสนุนการเพิ่มประสิทธิภาพแบบไมโครโดยไม่มีเหตุผล (เช่นการวัด) แต่ฉันคิดว่าประสิทธิภาพแม้ว่ามันจะอยู่ในระดับ micro-gain มันก็คุ้มค่าที่จะกล่าวถึงเมื่อมันมาเป็นโบนัสพร้อมกับการออกแบบที่เหนือชั้น
. GitHub หยุดช่วยน้ำแข็ง

13
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;
}

6
ชัดเจนขึ้นถ้าคุณใช้'1'และ'0'แทน49และ48ในไตรภาคของคุณ นอกจากนี้bควรมีความยาว 9 อักขระเพื่อให้อักขระตัวสุดท้ายสามารถยังคงเป็น terminator แบบ null ได้
tomlogic

ยังต้องเริ่มต้น B ทุกครั้ง
EvilTeach

2
ไม่ได้ถ้าคุณเปลี่ยนบาง 1. พื้นที่เพิ่มสำหรับสุดท้ายศูนย์: static char b[9] = {0}2. ประกาศย้ายออกจากวง: int z,y;3 b[y] = 0เพิ่มสุดท้ายศูนย์: วิธีนี้ไม่จำเป็นต้องเริ่มต้นใหม่
Kobor42

1
ทางออกที่ดี ฉันจะเปลี่ยนบางสิ่งแม้ว่า เช่นกำลังย้อนกลับไปในสตริงเพื่อให้อินพุตของขนาดใด ๆ สามารถจัดการได้อย่างถูกต้อง
Kobor42

ทุกคนควรจะถูกแทนที่ด้วย8 CHAR_BIT
alk

12

วิธีแก้ปัญหาที่ง่ายและรวดเร็ว:

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);

10

ไม่มีคำตอบที่โพสต์ก่อนหน้านี้ตรงกับที่ฉันค้นหาดังนั้นฉันจึงเขียนไว้ มันง่ายมากที่จะใช้% 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);
    }

1
โอเวอร์โฟลว์นี้จะมีมากกว่า 50 บิตหรือไม่
Janus Troelsen

โทรดีใช่มันจะ ... ฉันบอกว่าฉันต้องใช้ malloc ไม่เคยทำเช่นนั้น?
TechplexEngineer

ใช่แน่นอน ง่ายสุด ๆ :char* buffer = (char*) malloc(sizeof(char) * 50);
Janus Troelsen

@JanusTroelsen หรือสะอาดกว่าเล็กกว่าบำรุงรักษาได้:char *buffer = malloc(sizeof(*buffer) * 50);
Shahbaz

ทำไม "% B" จะแตกต่างจาก "% b" ในแง่นี้ คำตอบก่อนหน้านี้พูดถึงสิ่งต่างๆเช่น"ไม่มีฟังก์ชั่นการจัดรูปแบบในไลบรารีมาตรฐาน C เพื่อส่งออกไบนารีเช่นนั้น" และ " บาง runtimes สนับสนุน"% b "แม้ว่าจะไม่ได้มาตรฐาน .
Peter Mortensen

8

Runtimes บางตัวรองรับ "% b" แม้ว่าจะไม่ได้มาตรฐาน

ดูที่นี่สำหรับการสนทนาที่น่าสนใจ:

http://bytes.com/forum/thread591027.html

HTH


1
นี่เป็นคุณสมบัติของไลบรารีรันไทม์ C ไม่ใช่คอมไพเลอร์
cjm

7

รหัสนี้ควรรองรับความต้องการของคุณมากถึง 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

1
"#define width 64" ขัดแย้งกับ stream.h จาก log4cxx กรุณาใช้ชื่อกำหนดสุ่มแบบสุ่ม :)
kagali-san

5
@hhambra: คุณควรบอก log4cxx ให้ใช้ชื่อสามัญเช่นนี้widthแทน!
u0b34a0f6ae

7

มีตัวแปลง printf เพื่อพิมพ์ในรูปแบบไบนารีหรือไม่?

printf()ครอบครัวเป็นเพียงสามารถที่จะพิมพ์ในฐาน 8, 10 และ 16 โดยใช้ specifiers มาตรฐานโดยตรง ฉันขอแนะนำให้สร้างฟังก์ชันที่แปลงตัวเลขเป็นสตริงตามความต้องการเฉพาะของรหัส


หากต้องการพิมพ์ในฐานใด ๆ [2-36]

คำตอบอื่น ๆ ทั้งหมดมีข้อ จำกัด เหล่านี้อย่างน้อยหนึ่งข้อ

  1. ใช้หน่วยความจำแบบคงที่สำหรับบัฟเฟอร์ส่งคืน ซึ่งจะ จำกัด printf()จำนวนครั้งที่ฟังก์ชั่นอาจจะใช้เป็นข้อโต้แย้งไปยัง

  2. จัดสรรหน่วยความจำที่ต้องใช้รหัสการโทรเพื่อเพิ่มพอยน์เตอร์

  3. ต้องการรหัสการโทรเพื่อระบุบัฟเฟอร์ที่เหมาะสมอย่างชัดเจน

  4. โทรprintf()โดยตรง นี้บังคับให้ฟังก์ชั่นใหม่สำหรับการfprintf(), sprintf(), vsprintf()ฯลฯ

  5. ใช้ช่วงจำนวนเต็มลดลง

ต่อไปนี้จะมีไม่มีข้อ จำกัด ดังกล่าวข้างต้น มันไม่จำเป็นต้อง 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

มันมีประโยชน์มาก คุณรู้วิธีใช้งานใน C ++ หรือไม่? เมื่อฉันคอมไพล์มันจะสร้างข้อผิดพลาด "รหัสความรุนแรงคำอธิบายข้อผิดพลาดสถานะการระงับบรรทัดไฟล์โครงการ C4576 ประเภทวงเล็บแล้วตามด้วยรายการเริ่มต้นคือไวยากรณ์การแปลงประเภทที่ไม่ได้มาตรฐานอย่างชัดเจนสวัสดี C: \ my_projects \ hello \ hello \ main.cpp 39 "
แค่ผู้เรียน

1
@Justalearner สิ่งนี้จะสร้าง C ++ เพราะถ้าหากใช้ตัวอักษร C แบบผสมซึ่งไม่ใช่ส่วนหนึ่งของ C ++ บางทีโพสต์การใช้งาน C ++ ของคุณที่พยายามทำเช่นเดียวกัน - แม้ว่าไม่สมบูรณ์ฉันมั่นใจว่าคุณจะได้รับความช่วยเหลือ - ตราบใดที่คุณแสดงความพยายามครั้งแรก
chux - Reinstate Monica

6

อาจจะเป็นบิต OT แต่ถ้าคุณต้องการสิ่งนี้เฉพาะในการดีบักเพื่อทำความเข้าใจหรือย้อนกลับการดำเนินการไบนารีบางอย่างที่คุณทำคุณอาจดู wcalc (เครื่องคิดเลขคอนโซลแบบง่าย) ด้วยอ็อพชัน -b คุณจะได้รับเอาต์พุตไบนารี

เช่น

$ wcalc -b "(256 | 3) & 0xff"
 = 0b11

1
มีตัวเลือกอื่น ๆ ไม่กี่หน้านี้มากเกินไป ... ruby -e 'printf("%b\n", 0xabc)', dcตามด้วย2oตามด้วย0x123pและอื่น ๆ
lindes

6

ไม่มีฟังก์ชั่นการจัดรูปแบบในไลบรารีมาตรฐาน C เพื่อส่งออกไบนารีเช่นนั้น การดำเนินการรูปแบบทั้งหมดที่ตระกูลการสนับสนุน printf มีต่อข้อความที่มนุษย์สามารถอ่านได้


5

ฟังก์ชันเวียนเกิดต่อไปนี้อาจมีประโยชน์:

void bin(int n)
{
    /* Step 1 */
    if (n > 1)
        bin(n/2);
    /* Step 2 */
    printf("%d", n % 2);
}

7
ระวังนี่ใช้ไม่ได้กับจำนวนเต็มลบ
Anderson Freitas

4

ฉันปรับแก้ปัญหาสูงสุดสำหรับขนาดและ 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;
}

3
หากคุณต้องการใช้หน่วยความจำแบบไดนามิก (ผ่านstd::string) คุณอาจกำจัดstaticอาเรย์ได้เช่นกัน วิธีที่ง่ายที่สุดคือเพียงแค่ดรอปstaticรอบคัดเลือกและสร้างให้bกับฟังก์ชัน
Shahbaz

((x>>z) & 0x01) + '0'เพียงพอแล้ว
Jason C

4

พิมพ์บิตจากประเภทใดก็ได้โดยใช้รหัสและทรัพยากรน้อยลง

วิธีการนี้มีคุณสมบัติดังนี้

  • ทำงานร่วมกับตัวแปรและตัวอักษร
  • ไม่ซ้ำบิตทั้งหมดเมื่อไม่จำเป็น
  • เรียกใช้ printf เมื่อทำไบต์ให้สมบูรณ์เท่านั้น (ไม่จำเป็นสำหรับบิตทั้งหมด)
  • ใช้ได้กับทุกประเภท
  • ทำงานได้กับ endianness น้อยและใหญ่ (ใช้ GCC #defines เพื่อตรวจสอบ)
  • ใช้ typeof () ที่ไม่ได้มาตรฐาน C แต่กำหนดไว้เป็นส่วนใหญ่
#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 ) เพื่อเติมตารางด้วยไบต์ทั้งหมด (เป็นสตริงบิต) และพิมพ์ตามไบต์อินพุต / ดัชนี มันคุ้มค่าที่จะดู


4
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');
    }

}

หรือเพิ่ม 0 หรือ 1 ให้กับค่าตัวอักษรของ '0';) ไม่จำเป็นต้องประกอบไปด้วย
Owl

3

ฉันชอบโค้ดโดย 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;
}

1
เมื่อมาcountถึงMAXCNT - 1การเพิ่มขึ้นครั้งต่อไปของcountจะทำให้มันMAXCNTเป็นศูนย์ซึ่งจะทำให้การเข้าถึงออกจากขอบเขตของอาร์เรย์ count = (count + 1) % MAXCNTคุณควรจะทำ
Shahbaz

1
โดยวิธีการนี้จะมาเป็นแปลกใจต่อมาให้กับนักพัฒนาที่ใช้โทรไปยังฟังก์ชั่นนี้ในครั้งเดียวMAXCNT + 1 printfโดยทั่วไปหากคุณต้องการให้ตัวเลือกมากกว่า 1 อย่างให้ไม่มีที่สิ้นสุด ตัวเลขเช่น 4 อาจทำให้เกิดปัญหาได้เท่านั้น
Shahbaz

3

ไม่มีวิธีมาตรฐานและพกพา

การใช้งานบางอย่างให้itoa ()แต่มันจะไม่เป็นส่วนใหญ่และมีอินเทอร์เฟซที่ค่อนข้างร่วน แต่โค้ดอยู่หลังลิงค์และควรให้คุณใช้ฟอร์แมตเตอร์ของคุณเองได้อย่างง่ายดาย


3

การแปลงหนึ่งชุดคำสั่งสามัญประเภทใด ๆลงในการแทนสตริงไบนารีโดยใช้ไลบรารีมาตรฐาน :

#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);


1
นั่นเป็นวิธีแก้ปัญหาเชิงสำนวนสำหรับ C ++ แต่เขาขอ C.
danijar

3

ทางออกของฉัน:

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");

3

ขึ้นอยู่กับ @ 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

ขอบคุณการคัดลอกรหัสนี้คนแรกที่คัดลอกในโครงการนี้ฉันกำลังทำงานเขียนนี้รู้สึกเหมือนงานที่น่าเบื่อ :)
DevZer0

3

ใช้:

char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);

สำหรับโทษมากขึ้น. ดูวิธีการพิมพ์เลขฐานสองผ่าน printf


1
คำตอบก่อนหน้ากล่าวว่า"การใช้งานบางอย่างให้ itoa () แต่มันจะไม่เป็นส่วนใหญ่" ?
Peter Mortensen

2
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);
        }
}

ควรทำงาน - ยังไม่ทดลอง


2
/* 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" */

4
การจ่ายค่าใช้จ่ายสำหรับการจัดวางมอลล์จะกระทบต่อประสิทธิภาพการทำงาน ผ่านความรับผิดชอบสำหรับการทำลายของบัฟเฟอร์ไปยังผู้โทรจะไม่เมตตา
EvilTeach

2

ถัดไปจะแสดงเค้าโครงหน่วยความจำให้คุณ:

#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;
}

คุณหมายถึงอะไรโดย"ถัดไปจะแสดงให้คุณเห็นรูปแบบหน่วยความจำ" ?
Peter Mortensen

2

นี่คือรูปแบบขนาดเล็กของโซลูชัน 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.