c语言两个数组按位合并,C语言中的布尔数组和按位运算

我必须实现一组带有每个8个输出的串行移位寄存器。 输出连接到开关,所以我目前在C中使用布尔数组,它们将开关打开(true)或关闭(false)。

因此,每个移位寄存器都有8个布尔值的数组,实际上是8位无符号整数。 我可以继续使用数组,但是我认为那要慢得多,然后只是按位操作整数。 将整数传递到SPI接口也比数组容易得多。

是否有一种简单的方法可以将布尔数组转换为整数或以与操作数组相同的方式来操作整数?

即:

bool switch[8];

switch[0] = True; //Switch 1 on

switch[1] = False; //Switch 2 off

...

是相同的

uint8_t switch;

switch = 0b00000001;

但是在考虑单个开关时,很难阅读和编程。

性能是关键,因为我的SPI需要非常快。

您为什么认为使用布尔数组比较慢?

因为例如如果要将它们全部设置为1,则必须使用循环,对于整数,我可以一次将它们全部分配。因此,从本质上讲,更多的for循环和for循环的速度较慢吗?

也许使用布尔数组和整数值的并集。

是的,一个工会似乎很有希望,它将研究

为此,请勿使用布尔数组,请勿使用位域,请勿使用枚举,请勿使用蓬松的狮子狗,请勿使用液压挖掘机。使用uint8_t。就是这样。

@Julian如果您需要在一个代码中循环,那么您还需要在另一个代码中循环。如果您可以直接进行按位分配,则数组分配也不需要循环。

一些挑剔:switch是一个关键字。 True,False和0b00000001是非标准的。在与bool相同的标题中使用True,False。使用十六进制常量0x01或显式移位(1u << 0)引用位值。

@ user694733很好地了解了是非,我看到了0b ...方法是非标准的,但是它显示的开关位置比十六进制要容易得多,所以我宁愿选择它也不是其他方法。

uint8_t用于存储8位硬件相关数据,周期。如果它是内存映射的硬件寄存器,则还必须符合volatile的要求。

如果要命名单个引脚,可以使用define来实现:

#define SWITCH3 (1u << 3);

使用按位运算符访问。

uint8_t switch = 0;

switch = SWITCH1 | SWITCH3;   // set all bits

switch |= SWITCH3;            // set a specific bit

switch &= (uint8_t)~SWITCH3;  // clear a specific bit

@Ctx这个答案比以前的答案好吗?它不使用位域。 ;-)

@AndrewHenle,我当然没有提及我的答案;)仅引用部分评论并以这种方式歪曲其含义并不公平。

@Ctx好吧,这是我唯一有足够信息要评论的部分,因为我不知道其他海报及其答案的最新情况,也不知道谁是袜子木偶。 :-D

我认为@AndrewHenle是"谁"的袜子木偶;)好吧,我只是观察到,这个答案与其他两个答案基本上走的是相同的路线,但是尽管被发布了几个,但还是立即被赞成(尽管其他答案不是) 分钟后。 那闻起来,那就是我要表达的意思。 但是当然还有其他原因...

您不能使用数组语法(这需要运算符重载,这在C ++中是可能的)。但是您可以使用一些辅助函数来设置和获取位(/ 8和%8已针对位移位和ands进行了优化,请注意,对于int而言,这与用于索引的类型不同)

typedef uint8_t bit_mem_t;

static inline void set_bit(bit_mem_t* array, unsigned index, bool value) {

array[index/8] = (array[index/8] | 1 << (index%8)) ^ !value << (index%8);

}

static inline bool get_bit(bit_mem_t const* array, unsigned index) {

return (array[index/8] & 1 << (index%8)) != 0;

}

static inline void flip_bit(bit_mem_t* array, unsigned index) {

array[index/8] ^= 1 << (index%8);

}

/*static inline size_t bit_array_size(size_t bit_count) {

return (bit_count+7) / 8;

}*/

#define bit_array_size(bit_count) (((size_t)(count)+7)/8)

int main() {

bit_mem_t array[bit_array_size(3)] {}; // clear it to 0s

set_bit(array, 0, true);

set_bit(array, 1, false);

set_bit(array, 2, !get_bit(array, 1));

}

#define SWITCH1 1U

#define SWITCH2 2U

#define SWITCH3 4U

#define SWITCH4 8U

#define SWITCH5 16U

#define SWITCH6 32U

#define SWITCH7 64U

#define SWITCH8 128U

unsigned int switches = 0x0U;

要打开开关,请说开关4

switches = (switches | SWITCH4)

要关闭开关,请说开关4

switches = (switches & ~SWITCH4)

SWITCH 4应该是0x10

或者更确切地说:0x1u,0x2u,0x4u,0x8u,0x10u。

...或者如果您出于某种原因坚持使用十进制,1u,2u,4u,8u,16u,32u,64u,128u。

@Lundin我错过了8U之间的时间,现在知道了

使用宏:

uint8_t sw;

#define SW_ON(s)    sw=(sw|(1u<

#define SW_OFF(s)   sw=(sw&(~(1u<

并用作:

SW_OFF(3);

SW_ON(2);

考虑使用1u整数常量,以避免在整数提升期间出现意外情况。您的SW_OFF宏通常会返回负整数值,这可能不是程序员期望的。

谢谢,@ Lundin,已解决该问题。实际上,表达式应该是实现OP所需的赋值。也修复了该问题。

您可以使用这样的位域:

union {

struct {

unsigned char s1:1,

s2:1,

s3:1,

s4:1,

s5:1,

s6:1,

s7:1,

s8:1

} sw;

unsigned char nr[1];

} u;

您可以分别访问交换机的字段(u.sw.s1-u.sw.s8),也可以访问u.nr [0]中的整数。

也可能使用unsigned char nr代替具有1个成员的数组,但是该标准仅声明它对char数组有效,因此最好放心使用。

使用位域是一个非常糟糕的主意。对于位域使用char是一个非常糟糕的主意。如果char已签名,则不会告诉该代码将执行什么操作。此外,无法确定s1是位0还是其他位。"但是该标准仅声明它对char数组有效",不是。 6.7 / 5"位字段的类型必须是_Bool的合格或不合格版本,signed int,unsigned int或某些其他实现定义的类型。"因此,此代码实际上可以执行任何操作。

@Lundin不是用于位字段,而是用于联合。但是你是正确的,应该是unsigned char。

该标准允许您对联合使用任何类型。

@Lundin但是它仅允许您将任何类型重新解释为char数组。

不,它允许各种形式的野生型修剪。您只能使用指向字符类型的指针来迭代其他更大的类型,但这就是另一个故事。字符类型,表示char,signed char,unsigned char,uint8_t等。

@Lundin不,不是,例如,将整数作为浮点数/双精度数访问是UB。

重要的是有效的类型和对齐方式。如果这些没问题,您可以键入pun。不要将C与C ++混淆。

@Lundin例如,将整数作为浮点数访问可能是导致UB的陷阱表示。

是的,因为那您使用了错误的有效类型。但是当涉及到punning时,char,unsigned char和unsigned char[1]之间没有区别。

@Lundin唯一保证没有陷阱表示的类型是unsigned char。是的,这确实有所作为。

signed char也不允许具有填充位/陷阱。无论如何,陷阱表示都是无关紧要的,如果您通过一个指针进行访问,该指针允许使用指向存储在那里的有效类型的指针进行别名。严格的别名规则是什么?

@Lundin有关于该主题的讨论,例如在这里:gustedt.wordpress.com/2010/09/21/anatomy-of-integer-types-in -c

普通整数类型的陷阱表示形式大多是虚构的,在ISO 9899之外的真实世界中,使用char类型的陷阱表示形式的系统将毫无用处。尽管如此,它仍然无法解释1)为什么使用unsigned char nr[1]而不是< x5>。 2)为什么您会通过指向不兼容类型的指针访问此联合。当然,一个结构位域可能不一定要别名一个无符号字符,但这并不是该无符号字符的错,但这是因为位域的定义太差了。

你可能感兴趣的:(c语言两个数组按位合并)