Reputation: 31
I'm getting back to C after a long absence and I'm trying to learn the bitwise operators. I wrote this little program to demonstrate my confusion. The first printf works (after the header), but not the second. Is this some kind of order of operations thing or what?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
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(int argc, char *argv[])
{
unsigned int ch = atoi(argv[1]);
unsigned int a = atoi(argv[2]);
int chA;
int chB;
int chC;
int chD;
int chE;
int chF;
chA = ch & a;
chB = ch | a;
chC = ch ^ a;
chD = ~ch;
chE = ch << 2;
chF = ch >> 2;
char chAS[16];
char chBS[16];
char chCS[16];
char chDS[16];
char chES[16];
char chFS[16];
strcpy(chAS, byte_to_binary(chA));
strcpy(chBS, byte_to_binary(chB));
strcpy(chCS, byte_to_binary(chC));
strcpy(chDS, byte_to_binary(chD));
strcpy(chES, byte_to_binary(chE));
strcpy(chFS, byte_to_binary(chF));
printf("[c][%%d ][%%o ][%%x][ %%s ][ & ][ | ][ ^ ][ ~ ][ << ][ >> ]\n");
printf("[%c][%03d][%03o][%02x][%s][%s][%s][%s][%s][%s][%s]\n", isprint(ch) ? ch : ' ', ch, ch, ch, byte_to_binary(ch), chAS, chBS, chCS, chDS, chES, chFS);
printf("[%c][%03d][%03o][%02x][%s][%s][%s][%s][%s][%s][%s]\n", isprint(ch) ? ch : ' ', ch, ch, ch, byte_to_binary(ch), byte_to_binary(ch & a), byte_to_binary(ch | a), byte_to_binary(ch ^ a), byte_to_binary(~ch), byte_to_binary(ch << 2), byte_to_binary(ch >> 2));
return (0);
}
Upvotes: 0
Views: 63
Reputation: 140900
const char *byte_to_binary(int x)
{
static char b[9];
...
return b;
}
This function is not reentrant and returns a pointer to local value. So using it like : byte_to_binary(ch), byte_to_binary(ch & a)
will yield the same result twice, as the pointer value is the same(!).
But you can pass allocated space to your function:
const char *byte_to_binary(int x, char b[9]) {
...
return b;
}
And call using constant literal:
byte_to_binary(ch, (char[9]){0}), byte_to_binary(ch & a, (char[9]){0}),
This will allocate needed 9 chars on each function call. You can make that a macro:
const char *byte_to_binary_in(int x, char b[9]) {
...
return b;
}
#define byte_to_binary(x) byte_to_binary_in(x, (char[9]){0})
And have stay with the same interface, while your function stays reentrant.
Keep in mind however, that compound literals stop existing when exiting from a block, ie. after }
.
P.S. Have fun and see my small function printbinary
and macro PRINTBINARY_t(...)
, header and src. However there are maaany solution over the net for printing binary numbers.
Upvotes: 0
Reputation: 42109
You are returning a pointer to the same static
buffer from every call to byte_to_binary
, so by the time the printf
reads them they have (or rather, it has) only the last result.
Upvotes: 1
Reputation: 223699
Your byte_to_binary
function returns a pointer to a static array. You then call printf
, passing the return value of this function multiple times, and each of those calls returns the same pointer, so whichever invocation of the function happens to come last will be the one the results are printed for in all cases.
You need to either split up your printf
calls so that byte_to_binary
is only called once each time, or copy off the result into temporaries and print those. You're doing the latter in the second printf
call, so just use that and remove the third.
Upvotes: 2