gcc按位奇数行为

时间:2018-11-28 17:35:03

标签: c gcc bit-manipulation

很长一段时间后,我又回到了C,并且我正在尝试学习按位运算符。我写了这个小程序来证明我的困惑。第一个printf有效(在标题之后),但第二个无效。这是某种操作顺序的事情还是什么?

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

3 个答案:

答案 0 :(得分:2)

您的byte_to_binary函数返回一个指向静态数组的指针。然后,您调用printf,多次传递此函数的返回值,并且这些调用中的每一个都返回 same 指针,因此无论该函数最后发生的调用是哪一个在所有情况下都会打印结果。

您需要拆分printf调用,以使byte_to_binary每次仅被调用一次,或者将结果复制到临时文件中并打印出来。您将在第二个printf调用中使用后者,因此只需使用它并删除第三个。

答案 1 :(得分:2)

您从每次对static的调用中都返回了指向同一byte_to_binary缓冲区的指针,所以当printf读取它们时,它们只有(或者更确切地说)拥有最后结果。

答案 2 :(得分:0)

const char *byte_to_binary(int x)
{
    static char b[9];
    ...
    return b;
}

此函数不可重入,并返回指向本地值的指针。所以像byte_to_binary(ch), byte_to_binary(ch & a)这样使用它会产生两次相同的结果,因为指针值是相同的(!)。

但是您可以将分配的空间传递给函数:

const char *byte_to_binary(int x, char b[9]) { 
   ...
   return b; 
}

然后使用常量字面量进行调用:

byte_to_binary(ch, (char[9]){0}), byte_to_binary(ch & a, (char[9]){0}),

这将在每个函数调用中分配所需的9个字符。您可以将其设为宏:

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

并保持相同的界面,而功能保持可重入状态。

但是请记住,复合文字从一个块退出时即停止存在。在}之后。

P.S。玩得开心,看看我的小功能printbinary和宏PRINTBINARY_t(...)headersrc。但是,在网上有用于打印二进制数字的maaany解决方案。