GCC побитовое странное поведение - PullRequest
0 голосов
/ 28 ноября 2018

Я возвращаюсь к 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 голосов
/ 28 ноября 2018

Вы возвращаете указатель на один и тот же буфер static из каждого вызова на byte_to_binary, поэтому к тому моменту, когда printf читает их, они имеют (или, скорее, имеют) только последний результат.

0 голосов
/ 28 ноября 2018
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})

И остаться с тем же интерфейсом, в то время как ваша функция остается реентерабельной.

Однако имейте в виду, что составные литералы перестают существовать при выходе изблок, т.е.после }.

PS Развлекайся и посмотри мои маленькие функции printbinary и макрос PRINTBINARY_t(...), header и src .Тем не менее, в сети есть решение для печати двоичных чисел.

0 голосов
/ 28 ноября 2018

Ваша функция byte_to_binary возвращает указатель на статический массив.Затем вы вызываете printf, передавая возвращаемое значение этой функции несколько раз, и каждый из этих вызовов возвращает указатель того же , поэтому любой вызов функции, который произойдет последним, будет последним.для всех случаев.

Вам нужно либо разделить ваши printf вызовы так, чтобы byte_to_binary вызывался только один раз каждый раз, либо скопировать результат во временные файлы и распечатать их.Вы делаете последнее во втором printf вызове, поэтому просто используйте его и удалите третий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...