所以我需要你帮我把这件事做好。我有这样的任务:
typedef struct {
char status[1];
} Dish;变量status必须只有一个字节:前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必须只有一个字节,所以我将它声明为上面的char status[1],对吗?我还尝试在status上直接使用二进制操作,但是它给了我一个错误,说明我不能在char和int之间使用二进制操作。我的最后一个目标是将字节中的所有信息都放入一个单独的变量:stars、canceled、ongoing。
发布于 2019-12-30 13:08:16
通过一些调整,您的代码可以工作:
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 {
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;
}这将产生以下结果:
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),您可能希望确保结构的对齐是正确的。
发布于 2019-12-30 13:08:48
将数据成员状态声明为带有一个元素的数组没有太大意义。
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由位字段组成,所以您可以使用掩码来提取每个位字段,而不是提取一位。
另一种方法是使用位字段而不是类型为无符号字符的对象。有点像
typedef struct {
unsigned char stars: 3;
unsigned char cancelled: 1;
//...
} Dish;发布于 2019-12-30 13:15:39
正如在下面的评论中所警告的,请注意这段代码的行为并不保证在所有平台上都是一致的。
建议的答案使工作得以完成。如果您不想进入位移位操作,请尝试如下:
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);https://stackoverflow.com/questions/59531192
复制相似问题