C语言 对字符使用按位运算



所以我需要一些帮助来解决这个问题。我有这样的作业:

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

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

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: %dn", (int) i, getBit(status, i));
}
return 0;
}

我使用size_t作为位号(无符号(并修复了术语周围的大括号。

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

#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 = %dnValue: %dn", 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: 27
Stars = 5, Cancelled = 0, Ongoing = 0
Value: 37

您可以使用 .data 访问"char"值,也可以使用命名字段访问其他所有值。如果要强制转换读取的文件(通过 fread(,则可能需要确保结构的对齐正确。

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

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

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( "%dn", getBit( 6, i ) );
}       
return 0;
}

程序输出为

0
1
1

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

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

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

正如下面的评论中所警告的那样,请注意,此代码的行为不能保证在所有平台上保持一致。
建议的答案可以完成工作。如果您不想进入位移操作,请尝试以下操作:

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的大小,您会发现它仍然消耗一个字节的内存。

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

Dish.status = 0x0C; // For example

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

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

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

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

最新更新