2

I am trying to print binary numbers in C language. I'm having a problem with binary numbers starting with 0. When you try to keep it in the arrays and try to print it, random numbers come up, when you get input with scanf, the leading zero of the number disappears.

What should I do in this situation? Thank you in advance for your help.

int main(){
    int binarys[3] ={01001001, 01100110, 00100000};
    size_t i;
    for(i=0; i<3; i++)
    {
        printf("%d\n", binarys[i]);
    }

    int binary;
    printf("Enter a binary: ");
    scanf("%d", &binary);
    printf("%d", binary); 
}

Output:

262657
294984
32768
Enter a binary: 01001001
1001001
TruthSeeker
  • 1,539
  • 11
  • 24
  • 1
    Have you tried what happens when you remove those leading zeroes from the numbers in `binarys`? Does that illuminate what happens? What if you print `binarys[i] + 2`? :) – AKX Apr 20 '22 at 08:22
  • 2
    Your array is made up of ints. So you will probably agree that 010 = 10 in decimal? That is exactly what is happening. You should probably try to save your numbers as char * . Also the output you are getting is all but random! Let me give you a hand: 100000 outputs 32768 which is 2^(15) – Vladouch Apr 20 '22 at 08:24
  • Those are the decimal representations of your binary numbers. You're actually entering a decimal number that looks like binary. – Tibrogargan Apr 20 '22 at 08:25
  • Does this answer your question? [Is there a printf converter to print in binary format?](https://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format) – Tibrogargan Apr 20 '22 at 08:25
  • 2
    prepend `0b` for binary literals – OTheDev Apr 20 '22 at 08:25
  • Side note: you should format your code properly, for example like the samples in your learning material – Jabberwocky Apr 20 '22 at 08:28
  • 5
    @Vladouch actually `010` is not 10 in decimal but 8, because literals prepended with `0` are octal. – Jabberwocky Apr 20 '22 at 08:31

3 Answers3

2

Integer literals:

In C and C++, an integer literal starting with a 0 means it is represented in octal (base 8).

The array of ints you have initialized therefore contains the octal values of 1001001, 1100110, 100000, which are 262657, 294984, 32768 respectively.

Binary literals are availbale in C++ since C++ 14. C is supposed to support it in C23 (see: https://en.cppreference.com/w/c/language/integer_constant).

In this code example:

int main()
{
    int a = 010;
    printf("%d\n", a);

    int b = 0b10;
    printf("%d\n", b);
}

The following will be printed (C++ 14):

8
2

Because 8 is the decimal value for the octal 10, and 2 is the decimal value for the binary 10.

The issue with scanf:

scanf parses the entered value as a decimal int (since you specified the %d format specifier). It does not apply the language literal rules. Therefore the leading 0 that has no mathematical meaning is ignored. You entered 01001001, which is parsed as the decimal int with value 1001001 and that is what you see in the printf that follows (which again uses the %d format specifier).

wohlstad
  • 12,661
  • 10
  • 26
  • 39
2

I'm having a problem with binary numbers starting with 0

Integer constants starting with 0 are not binary but octal.

If you have a compiler that offers the 0b prefix as an extension (or come from the future where this has been standardized) and want to declare an integer with the value 32, in base two for whatever reason, write 0b00100000. It'll still have exactly the same contents as if you just wrote 32 though, because a base is how a number is represented, and doesn't affect its value.

when you get input with scanf,

The scanf function does not have a conversion specifier for binary, and %d explicitly means decimal, ie, base 10.

If you want to scan numbers written in binary, you'll need to read a string, confirm it's only ones and zeroes, and convert it yourself (ie, using strtol like strol(str, &end, 2)).

... the leading zero of the number disappears

Leading zeroes are not printed by default.

Again, printf does not have a binary conversion specifier anyway, but if you want to print leading zeroes, you need both to set a field width and to request zero padding, like %08d.

If you want to print numbers in binary, you need to convert those to a string yourself first as well.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • You can add `scanf` with `%i` , for binary or octal input – TruthSeeker Apr 20 '22 at 08:37
  • 1
    Worth noting that Standard C does not have the binary prefix `0b`, but that is provided by specific compilers by extension. See [How do I use a binary prefix in accordance with C11?](https://stackoverflow.com/q/9014958/3422102) – David C. Rankin Apr 20 '22 at 08:42
1

C does not (yet) support binary integer constants or scanf/print conversion specifiers for binary. It has been proposed for the upcoming C standard "C23". Until then, 0b prefix and %b conversion specifiers may be supported by some compilers as non-standard extensions (0b very likely, %b not so likely).

Numbers starting with 0 are actually octal integer constants. Either way, printing/reading some 01001001 integer constant using %d is nonsense.

With current standard C, you could cook up a compile-time conversion using a bunch of admittedly ugly macros:

#include <stdio.h>

#define STATIC_ASSERT(expr) (int [expr]){0}

#define STR_TO_BIN(str) ( (str[0]-'0') * 128 + \
                          (str[1]-'0') *  64 + \
                          (str[2]-'0') *  32 + \
                          (str[3]-'0') *  16 + \
                          (str[4]-'0') *   8 + \
                          (str[5]-'0') *   4 + \
                          (str[6]-'0') *   2 + \
                          (str[7]-'0') *   1 )

#define BINARIFY(n) (STATIC_ASSERT(sizeof(#n)==9), STR_TO_BIN(#n))

int main(){
    int binaries[3] ={BINARIFY(01001001), BINARIFY(01100110), BINARIFY(00100000)};
    
    for(size_t i=0; i<3; i++)
    {
        printf("%d\n", binaries[i]);
    }
}

(The "poor man's static assert" protects against array out of bounds access but not against incorrect input formats.)

Lundin
  • 195,001
  • 40
  • 254
  • 396