是否可以将三个数字插入到 2 个字节的变量中?
Is it possible to insert three numbers into 2 bytes variable?
例如,我想存储包含日、月、年的日期。
- 天 ->
31
,月 -> 12
,年 -> 99
。
我想将 31
、12
、99
存储在一个变量中,并将使用移位运算符 <<
和 >>
来操作它。
我尝试做的事情:
short date = 0;
date = 31; // day
date << 5;
date = 12; // month
date << 7;
date = 99; // year
printf("date: %d\n", date >> 15); // print the first value
但结果是0
。
我不知道这个想法本身是否可行。
你的意思是 <<=
,而不是 <<
。
也就是说,您的代码还有另外两个问题:
- 你想要一个无符号变量; signed 整数在移位时有令人惊讶的行为。 (至少,如果您将整数视为位序列,它们会这样做)
- 如果你想要 16 位类型,你应该使用
int16_t
或 uint16_t
,而不是希望 short
是正确的大小。
你想要这样的东西
static inline uint16_t pack_date(unsigned day, unsigned month, unsigned year)
{
// Consider inserting some checking here to make sure the numbers
// are in their expected ranges
return (day << 11) | (month << 7) | year;
}
static inline uint16_t get_day(uint16_t packed_value)
{
return packed_value >> 11;
}
static inline uint16_t get_month(uint16_t packed_value)
{
return (packed_value >> 7) & 0xf;
}
static inline uint16_t get_year(uint16_t packed_value)
{
return packed_value & 0x7f;
}
是的,可以这样做。我会使用适当的 union
来掩盖值区域:
union mydate_struct {
struct {
uint16_t day : 5; // 0 - 31
uint16_t month : 4; // 0 - 12
uint16_t year : 7; // 0 - 127
};
uint16_t date_field;
};
这使您的年份范围从 0 到 127。您的决定,如果这足以满足您的实际用例。
一种对代码进行最少修改的可能方法,
#include<stdio.h>
#include<stdint.h>
int main()
{
uint16_t date = 0;
date |= 31; // day
date <<= 4;
date |= 12; // month
date <<= 7;
date |= 99; // year
printf("day: %d\n", date>>11); // print the first value(day)
printf("month:%d\n",(date>>7)&0xF);
printf("year:%d\n",date&0x7F);
}
date
值与 printf("date value:%04x\n",date);
的日志输出:
date value:0000
date value:001f
date value:01f0
date value:01fc
date value:fe00
date value:fe63
day: 31
month:12
year:99
date value:fe63
但是正如其他人所说,最好使用Bit Field with Struct,比如
/* define a structure with bit fields */
struct
{
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status2;
例如,我想存储包含日、月、年的日期。
- 天 ->
31
,月 ->12
,年 ->99
。
我想将 31
、12
、99
存储在一个变量中,并将使用移位运算符 <<
和 >>
来操作它。
我尝试做的事情:
short date = 0;
date = 31; // day
date << 5;
date = 12; // month
date << 7;
date = 99; // year
printf("date: %d\n", date >> 15); // print the first value
但结果是0
。
我不知道这个想法本身是否可行。
你的意思是 <<=
,而不是 <<
。
也就是说,您的代码还有另外两个问题:
- 你想要一个无符号变量; signed 整数在移位时有令人惊讶的行为。 (至少,如果您将整数视为位序列,它们会这样做)
- 如果你想要 16 位类型,你应该使用
int16_t
或uint16_t
,而不是希望short
是正确的大小。
你想要这样的东西
static inline uint16_t pack_date(unsigned day, unsigned month, unsigned year)
{
// Consider inserting some checking here to make sure the numbers
// are in their expected ranges
return (day << 11) | (month << 7) | year;
}
static inline uint16_t get_day(uint16_t packed_value)
{
return packed_value >> 11;
}
static inline uint16_t get_month(uint16_t packed_value)
{
return (packed_value >> 7) & 0xf;
}
static inline uint16_t get_year(uint16_t packed_value)
{
return packed_value & 0x7f;
}
是的,可以这样做。我会使用适当的 union
来掩盖值区域:
union mydate_struct {
struct {
uint16_t day : 5; // 0 - 31
uint16_t month : 4; // 0 - 12
uint16_t year : 7; // 0 - 127
};
uint16_t date_field;
};
这使您的年份范围从 0 到 127。您的决定,如果这足以满足您的实际用例。
一种对代码进行最少修改的可能方法,
#include<stdio.h>
#include<stdint.h>
int main()
{
uint16_t date = 0;
date |= 31; // day
date <<= 4;
date |= 12; // month
date <<= 7;
date |= 99; // year
printf("day: %d\n", date>>11); // print the first value(day)
printf("month:%d\n",(date>>7)&0xF);
printf("year:%d\n",date&0x7F);
}
date
值与 printf("date value:%04x\n",date);
的日志输出:
date value:0000 date value:001f date value:01f0 date value:01fc date value:fe00 date value:fe63 day: 31 month:12 year:99 date value:fe63
但是正如其他人所说,最好使用Bit Field with Struct,比如
/* define a structure with bit fields */ struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status2;