你如何在 C 中获取倒置复合垃圾的地址?
How do you take the address of an inverted compound litteral in C?
我不太确定我应该为这个问题使用什么标题,但我会尝试通过解释来澄清:
总而言之,我想要一个函数参数接受一个数组和一个整数作为同一个参数。不太难,只需要使用指针就可以了?所以我有这个:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&BIT0);
}
对于常规值,一切都很好,花花公子,但在我的情况下,我需要能够反转值,所以我认为这会起作用:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&~BIT0);
}
传递时只需用按位非(~)反转值。没什么大不了的吧?好吧,我得到了错误
error: lvalue required as unary '&' operand
如果我改写为:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&(unsigned char){~BIT0});
}
首先,这是一个非常丑陋的解决方案,我真的不想在我的代码中使用它。感觉一点都不直观。
其次,它按我最初希望的方式工作,但我认为这告诉我的是“~”运算符正在将 unsigned char 提升为 unsigned int。所以我必须将它转换回 unsigned char 函数才能接受地址。但是错误消息与令我困惑的消息并不完全匹配。
这是怎么回事?我该如何解决这个问题以获得我想要的行为?
错误的原因是某些运算符(如一元*
)return一个so-called可修改的lvalue,意思是引用到您可以更改的对象。然而,大多数运算符不这样做,~
就是这样的运算符。您从中得到的只是一个临时 read-only 值。它确实也将操作数提升为有符号 int
,这通常是有问题的,但不是错误的原因。
至于如何解决问题,就看你如何使用这些宏了。如果 BIT0
是一个设置了位 0 的复合文字,那么为了保持一致,人们可能会创建一个类似的宏:
#define BITS1_7 (unsigned char){0xFE}
(注意二进制文字不是标准的 C。)
但我也不会那样做。问题的根源在于过度设计和坚持以奇怪的方式使用复合文字。而是应用 KISS principle。如果您有一个接受单个字节或数组的函数,那么编写程序的最易读的方式是:
#define BIT0 (1u << 0) // industry de facto standard way to write a bit mask
...
uint8_t tmp = BIT0;
foo(&tmp);
或者
uint8_t tmp = ~BIT0;
所有 C 程序员都可以阅读和理解这段代码。
我不太确定我应该为这个问题使用什么标题,但我会尝试通过解释来澄清:
总而言之,我想要一个函数参数接受一个数组和一个整数作为同一个参数。不太难,只需要使用指针就可以了?所以我有这个:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&BIT0);
}
对于常规值,一切都很好,花花公子,但在我的情况下,我需要能够反转值,所以我认为这会起作用:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&~BIT0);
}
传递时只需用按位非(~)反转值。没什么大不了的吧?好吧,我得到了错误
error: lvalue required as unary '&' operand
如果我改写为:
#define BIT0 (unsigned char){0b00000001}
void foo (unsigned char *ptr_bar)
{
printf("%x", *ptr_bar);
}
void main (void)
{
foo(&(unsigned char){~BIT0});
}
首先,这是一个非常丑陋的解决方案,我真的不想在我的代码中使用它。感觉一点都不直观。 其次,它按我最初希望的方式工作,但我认为这告诉我的是“~”运算符正在将 unsigned char 提升为 unsigned int。所以我必须将它转换回 unsigned char 函数才能接受地址。但是错误消息与令我困惑的消息并不完全匹配。
这是怎么回事?我该如何解决这个问题以获得我想要的行为?
错误的原因是某些运算符(如一元*
)return一个so-called可修改的lvalue,意思是引用到您可以更改的对象。然而,大多数运算符不这样做,~
就是这样的运算符。您从中得到的只是一个临时 read-only 值。它确实也将操作数提升为有符号 int
,这通常是有问题的,但不是错误的原因。
至于如何解决问题,就看你如何使用这些宏了。如果 BIT0
是一个设置了位 0 的复合文字,那么为了保持一致,人们可能会创建一个类似的宏:
#define BITS1_7 (unsigned char){0xFE}
(注意二进制文字不是标准的 C。)
但我也不会那样做。问题的根源在于过度设计和坚持以奇怪的方式使用复合文字。而是应用 KISS principle。如果您有一个接受单个字节或数组的函数,那么编写程序的最易读的方式是:
#define BIT0 (1u << 0) // industry de facto standard way to write a bit mask
...
uint8_t tmp = BIT0;
foo(&tmp);
或者
uint8_t tmp = ~BIT0;
所有 C 程序员都可以阅读和理解这段代码。