首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对char使用逐位操作

对char使用逐位操作
EN

Stack Overflow用户
提问于 2019-12-30 12:53:11
回答 3查看 98关注 0票数 0

所以我需要你帮我把这件事做好。我有这样的任务:

代码语言:javascript
复制
typedef struct {
    char status[1];
} Dish;

变量status必须只有一个字节:前3位将包含盘子的星星数(0-5),第4位告诉我们盘是否被取消,第5位告诉我们盘是否正在进行。我试着得到这样的星星数,但是没有用:

代码语言:javascript
复制
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必须只有一个字节,所以我将它声明为上面的char status[1],对吗?我还尝试在status上直接使用二进制操作,但是它给了我一个错误,说明我不能在charint之间使用二进制操作。我的最后一个目标是将字节中的所有信息都放入一个单独的变量:starscanceledongoing

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-30 13:08:16

通过一些调整,您的代码可以工作:

代码语言:javascript
复制
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作为位号(它是无符号的),并修正了这个术语的大括号。

对于位字段,代码可能如下所示:

代码语言:javascript
复制
#include <stdio.h>

typedef struct {
  union {
    struct {
      unsigned stars:3;
      char cancelled:1;
      char ongoing:1;
    };
    unsigned 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;
}

这将产生以下结果:

代码语言:javascript
复制
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: 27
Stars = 5, Cancelled = 0, Ongoing = 0
Value: 37

您可以使用.data访问“char”值,使用命名字段访问其他所有内容。如果您想转换所读取的文件(通过fread),您可能希望确保结构的对齐是正确的。

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

票数 2
EN

Stack Overflow用户

发布于 2019-12-30 13:08:48

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

代码语言:javascript
复制
char status[1];

你可以声明一下

代码语言:javascript
复制
unsigned char status;

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

代码语言:javascript
复制
#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;
}

程序输出是

代码语言:javascript
复制
0
1
1

另一方面,由于数据成员status由位字段组成,所以您可以使用掩码来提取每个位字段,而不是提取一位。

另一种方法是使用位字段而不是类型为无符号字符的对象。有点像

代码语言:javascript
复制
typedef struct {
    unsigned char stars: 3;
    unsigned char cancelled: 1;
    //... 
} Dish;
票数 2
EN

Stack Overflow用户

发布于 2019-12-30 13:15:39

正如在下面的评论中所警告的,请注意这段代码的行为并不保证在所有平台上都是一致的。

建议的答案使工作得以完成。如果您不想进入位移位操作,请尝试如下:

代码语言:javascript
复制
typedef struct dist {
    union {
        struct {
            uint8_t number_of_stars : 3 ;
            uint8_t cancel_status : 1 ;
            uint8_t ongoing_status :1 ;
            uint8_t reserved : 3;
        };

        uint8_t status;

    };

} DishType;

DishType Dish;

如果您检查Dish的大小,您将看到它仍然占用一个字节的内存。

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

代码语言:javascript
复制
Dish.status = 0x0C; // For example

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

代码语言:javascript
复制
Dish.cancel_status = 1;
Dish.ongoing_status = 0;

然而,单独访问、打印或修改它:

代码语言:javascript
复制
printf("\nNo. of starts = %u", Dish.number_of_stars);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59531192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档