对char使用按位运算

问题描述 投票:0回答:3

因此,我需要一些帮助来解决此问题。我有这样的作业:

typedef struct {
    char status[1];
} Dish;

变量status只能有1个字节:前3位将包含碟子的星数(0-5),第4位告诉我们是否取消了碟子,第5位告诉我们是否菜是否在进行中。我试图获得像这样的星星数量,但它不起作用:

getBit(char data, int bitNumber) {
 return (data & (1 << bitNumber-1)) != 0;
}
int number = 0;
number = getBit(dish.status,0);
number = number << 1 + getBit(dish.status,1);
number = number << 1 + getBit(dish.status,2);

因为status只能有1个字节,所以我在上面声明了它char status[1]是否正确?我也尝试直接在status上使用二进制运算,但是它给我一个错误,提示我不能在charint之间使用二进制运算。我的最终目标是将该字节中的所有信息放入一个单独的变量中:starscanceledongoing

c binary
3个回答
0
投票

[将数据成员状态声明为具有一个元素的数组没有太大意义

char status[1];

您可以这样声明

unsigned char status;

该函数看起来像在下面的演示程序中所示。

#include <stdio.h>
#include <limits.h>

unsigned int getBit( unsigned char data, unsigned int bitNumber ) 
{
    bitNumber %= CHAR_BIT;

    return ( data & (1 << bitNumber ) ) != 0;
}

int main(void) 
{
    for ( int i = 0; i <3; i++ )
    {
        printf( "%d\n", getBit( 6, i ) );
    }       

    return 0;
}

程序输出为

0
1
1

另一方面,由于数据成员status由位字段组成,因此除了提取一位以外,您还可以对每个位字段使用掩码来提取它。

[另一种方法是使用位字段代替unsigned char类型的对象。有点像

typedef struct {
    unsigned char stars: 3;
    unsigned char cancelled: 1;
    //... 
} Dish;

0
投票

建议的答案可以完成工作。如果您不想进行移位操作,请尝试以下方法:

typedef struct dist {
    union {
        uint8_t number_of_stars : 3 ;
        uint8_t cancel_status : 1 ;
        uint8_t ongoing_status :1 ;
        uint8_t reserved : 3;

        struct {
            uint8_t status;        
        };
    };

} DishType;

DishType Dish;

如果检查Dish的大小,您会发现它仍然占用一个字节的内存。

您可以在一行中设置参数,例如:

Dish.status = 0x0C; // For example

或者您可以设置特定的参数,例如:

Dish.cancel_status = 1;
Dish.ongoing_status = 0;

但是,仍然可以单独访问或打印或修改它:

printf("\nNo. of starts = %u", Dish.number_of_stars);

0
投票

通过一些调整,您的代码有效:

int getBit(char data, size_t bitNumber) {
 return (data & (1 << (bitNumber - 1))) != 0;
}

int main(void) {

  char status = 3 + (1 << 5);

  for (size_t i = 1; i <= 8; ++i) {
    printf("Bit %d: %d\n", (int) i, getBit(status, i));
  }
  return 0;
}

我使用size_t表示位数(无符号),并在术语周围固定了花括号。

使用位字段,代码可能如下所示:

#include <stdio.h>

typedef struct {
  union {
    struct {
      char stars:3;
      char cancelled:1;
      char ongoing:1;
    };
    char data;
  };
} Dish;

void printDish(Dish dish) {
  printf("Stars = %d, Cancelled = %d, Ongoing = %d\nValue: %d\n", dish.stars, dish.cancelled, dish.ongoing, dish.data);
}

int main(void) {

  Dish dish1;
  dish1.stars = 3;
  dish1.cancelled = 1;
  dish1.ongoing = 1;
  printDish(dish1);

  Dish dish2;
  dish2.stars = 5;
  dish2.cancelled = 0;
  dish2.ongoing = 0;

  printDish(dish2);
  return 0;
}

这将输出:

clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
 clang-7 -pthread -lm -o main main.c
 ./main
Stars = 3, Cancelled = -1, Ongoing = -1
Value: 99
Stars = 5, Cancelled = 0, Ongoing = 0
Value: 5

您可以使用.data访问其他'char'值,并使用命名字段访问其他所有内容。如果要投射(通过fread)读取的文件,则可能要确保该结构的对齐正确。

请参见https://repl.it/repls/SimultaneousIncredibleRoot

© www.soinside.com 2019 - 2024. All rights reserved.