【C言語】
2進定数をC23仕様のprintf書式%bで表示する

2進数/10進数 変換

■新しいC23仕様のC言語では2進数が使える

#include <stdio.h>
int main(void){
    //2進定数を2進数のprintf書式で表示する
    printf("%b\n",0b11110000);
}

●gcc version 12.2.0の実行結果

./a.out 
11110000

注意:
2024年9月現在C23に対応しているコンパイラは少ないので
読者の環境下ではうまく動かないかもしれません。


■以下に示す自作10進/2進変換の課題はもうすぐ時代遅れになります。


■10進数値を2進文字列変換

#include    <stdio.h>
#include    <stdlib.h>
#include    <stdint.h>
#include    <limits.h>
#include    <string.h>
#include    <assert.h>
//  16進⇒二進変換表
static char *cnv16to2[] = {
    [0]  ="0000",[1]  ="0001",[2]  ="0010",[3]  ="0011",
    [4]  ="0100",[5]  ="0101",[6]  ="0110",[7]  ="0111",
    [8]  ="1000",[9]  ="1001",[0xa]="1010",[0xb]="1011",
    [0xc]="1100",[0xd]="1101",[0xe]="1110",[0xf]="1111",
};
//  十進数値⇒二進文字列変換
char    *dec2bin(unsigned int x) {
    static char output[256];    
    sprintf(output,
        "%s%s%s%s%s%s%s%s",
        cnv16to2[(x & 0xF0000000) >> 28],
        cnv16to2[(x & 0x0F000000) >> 24],
        cnv16to2[(x & 0x00F00000) >> 20],
        cnv16to2[(x & 0x000F0000) >> 16],
        cnv16to2[(x & 0x0000F000) >> 12],
        cnv16to2[(x & 0x00000F00) >>  8],
        cnv16to2[(x & 0x000000F0) >>  4],
        cnv16to2[(x & 0x0000000F) ]
    );
    return  output ;
}

intは32bitを前提としています。


■2進数文字列を10進数値に変換

//  二進文字列⇒十進数値変換
//      1111    = 2^3+2^2+2^1+2^0
//              = 1<<3+1<<2+1<<1+1<<0;
//      1010
//              = 1<<3+0<<2+1<<1+0<<0;
unsigned int bin2dec(char *二進文字列){
    unsigned int 十進数値 = 0;
    int 桁 = 0;
    for(int len = strlen(二進文字列)-1;len >= 0 ; len--){
        if(二進文字列[len] == '1'){
            十進数値 += (1 << 桁);  //桁の重み加算  
        }
        桁++ ;  //桁上げ    
    }
    return  十進数値 ;
}


■使用例と検算

int main(void) {
    //10進数値⇒2進文字列変換
    for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
        printf("%8x->%s\t",num-1,dec2bin(num-1));
        printf("%8x->%s\t",num,  dec2bin(num  ));
        printf("%8x->%s\n",num+1,dec2bin(num+1));
    }

    //検算:10進数値⇒ 2進文字⇒10進数値(元の数値に戻ればOK)
    for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
        if(num-1 != bin2dec(dec2bin(num-1)))    assert(0);
        if(num   != bin2dec(dec2bin(num  )))    assert(0);
        if(num+1 != bin2dec(dec2bin(num+1)))    assert(0);   
    }
}

■コード全部

#include    <stdio.h>
#include    <stdlib.h>
#include    <stdint.h>
#include    <limits.h>
#include    <string.h>
#include    <assert.h>
//  16進⇒二進変換表
static char *cnv16to2[] = {
    [0]  ="0000",[1]  ="0001",[2]  ="0010",[3]  ="0011",
    [4]  ="0100",[5]  ="0101",[6]  ="0110",[7]  ="0111",
    [8]  ="1000",[9]  ="1001",[0xa]="1010",[0xb]="1011",
    [0xc]="1100",[0xd]="1101",[0xe]="1110",[0xf]="1111",
};
//  十進数値⇒二進文字列変換
char    *dec2bin(unsigned int x) {
    static char output[256];    
    sprintf(output,
        "%s%s%s%s%s%s%s%s",
        cnv16to2[(x & 0xF0000000) >> 28],
        cnv16to2[(x & 0x0F000000) >> 24],
        cnv16to2[(x & 0x00F00000) >> 20],
        cnv16to2[(x & 0x000F0000) >> 16],
        cnv16to2[(x & 0x0000F000) >> 12],
        cnv16to2[(x & 0x00000F00) >>  8],
        cnv16to2[(x & 0x000000F0) >>  4],
        cnv16to2[(x & 0x0000000F) ]
    );
    return  output ;
}
//  二進文字列⇒十進数値変換
//      1111    = 2^3+2^2+2^1+2^0
//              = 1<<3+1<<2+1<<1+1<<0;
//      1010
//              = 1<<3+0<<2+1<<1+0<<0;
unsigned int bin2dec(char *二進文字列){
    unsigned int 十進数値 = 0;
    int 桁 = 0;
    for(int len = strlen(二進文字列)-1;len >= 0 ; len--){
        if(二進文字列[len] == '1'){
            十進数値 += (1 << 桁);  //桁の重み加算  
        }
        桁++ ;  //桁上げ    
    }
    return  十進数値 ;
}
int main(void) {
    //10進数値⇒2進文字列変換
    for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
        printf("%8x->%s\t",num-1,dec2bin(num-1));
        printf("%8x->%s\t",num,  dec2bin(num  ));
        printf("%8x->%s\n",num+1,dec2bin(num+1));
    }

    //検算:10進数値⇒ 2進文字⇒10進数値(元の数値に戻ればOK)
    for(uint32_t num = UINT_MAX;num != 0 ;num /= 2){
        if(num-1 != bin2dec(dec2bin(num-1)))    assert(0);
        if(num   != bin2dec(dec2bin(num  )))    assert(0);
        if(num+1 != bin2dec(dec2bin(num+1)))    assert(0);   
    }
}