在C中明确定义了用于在不同尺寸变量之间进行比特或操作员的行为,并从较小的UINT中减去较大的UINT?
我试图弄清C中以下命令的最终结果是什么,以及可能是更好的方法。
这是我的变量。所有都是uint16
或uint32
cnt_a
的无符号整数:这是uint32
*位读/写计数器在微处理器中。它直接指向此寄存器的地址,因此始终包含来自寄存器的值。处理器会自动递增,但可以由程序重置或写入设定值。从制造商的文档中,16位是“保留的”,因此,我相信,始终报告0
,并且实际上不会写入,因此实际上是16位值。
*NOTE: `CNT_A` is always called as a `uint32` in the code, but it is declared as a union of a `uint32` and a 32-bit `bitfield`, with the upper 16 bits of the bitfield unused.
update_counter
:这是一个“挥发性UINT16”,每当调用该功能时,它会在另一个函数中递增。
detect_pulse
是boolean
,如果在系统中检测到脉冲
ignore_time
是const uint16
wtempa
:this 是正确的,那么是uint16
,从reg_a
lwtempb
:这是uint32
() > l
= 长
)用作存储两个16位值的临时变量,但涉及32位计算
lwtempc
:这是A uint32
用于通过其他变量
“ lwlasta”中的差异检测更改:这是静态uint32
,它存储lwtempa
lwtempa的最终值代码>并将其运送到函数的下一个调用中,并与新的lwtempa
进行了比较,
这是函数中相关的代码的相关实际段(注释是我在此帖子中添加的注释,而不是在实际文件中):
void changeHandler(void) {
wTempA = REG_A; //Assigning a uint32 to a uint16, but upper 16 bits of uint32 are always 0
lwTempB = update_counter; //Assigning a uint16 to a uint32
lwTempB <<= 16; //Shifting uint16 value to upper 16 bits
lwTempB |= wTempA //Doing a logical OR of a uint16 with a uint32, then storing back to that uint32
...
if (detect_pulse)
{
lwLastA = wTempA //Setting "previous" value to wTempA if a pulse was detected
}
lwtempC = lwTempB - lwLastA //Subtracting uint16 from a uint32
if (lwTempC <= ignore_time) //There must be a significant difference to perform the following actions
{
return;
}
//...perform important actions with micro... (redacted)
...
lwLastA = wTempA //Setting previous value of wTempA
}
我从以前的程序员继承了此功能。这不是我这样做的方式,但是如果我不需要,我不想重写整个事情。
我认为,如果发生两个条件之一,该功能应触发“重要动作”。一个是,如果发生外部事件,导致update_counter
递增,另一个是如果过去的时间比image> image_time
。
上述这些线的所有预期行为是否明确定义,并且会产生一致的结果吗?
我有一些具体的问题:
清楚地定义了LWTEMPB(UINT32)和WTEMPA(UINT16)之间的位置。
update_counter
将在一定的时间过去后滚动(除非有问题,否则计数以设定的频率发生),在该滚动点,LWLASTA实际上会更大比lwtempb。这里会有明确定义的行为,其中两个未签名的整数以通常会产生负面结果的方式减去,然后将其分配给未签名的整数?从布尔数学数学来看,我认为这将导致lwtempc始终具有大于ignore_time的值,因此仍然引起触发器,因此草率编码仍应提供所需的结果?
I'm trying to figure out what the end result of the following commands in c would be, and what might be a better way to go about it.
Here are my variables. All are unsigned integers of type either uint16
or uint32
CNT_A
: This is a uint32
* but represents a 16-bit read/write counter register in the microprocessor. It points directly to the address of this register, so this always contains the value from the register. It is automatically incremented by the processor, but can be reset or written to a set value by the program. From the manufacturer's documentation, the upper 16-bits are "reserved" and therefore, I believe, always report 0
and won't actually be written, so it is actually a 16-bit value.
*NOTE: `CNT_A` is always called as a `uint32` in the code, but it is declared as a union of a `uint32` and a 32-bit `bitfield`, with the upper 16 bits of the bitfield unused.
update_counter
: this is a 'volatile uint16' which is incremented in another function whenever that function is called.
detect_pulse
is boolean
which is TRUE if a pulse is detected in the system
ignore_time
is a const uint16
wTempA
: this is a uint16
that pulls the 16-bit counter value from REG_A
lwTempB
: this is a uint32
(l
=long
) that is used as a temporary variable that stores two 16-bit values, but is involved in 32-bit calculations
lwTempC
: this is a uint32
that is used to detect a change via differences in the other variables
'lwLastA': this is a static uint32
that stores the final value of lwTempA
and carries it to the next call of the function and is compared to the new lwTempA
Here are the relevant actual pieces of code in the function (note comments shown are ones I added for this post, not in actual file):
void changeHandler(void) {
wTempA = REG_A; //Assigning a uint32 to a uint16, but upper 16 bits of uint32 are always 0
lwTempB = update_counter; //Assigning a uint16 to a uint32
lwTempB <<= 16; //Shifting uint16 value to upper 16 bits
lwTempB |= wTempA //Doing a logical OR of a uint16 with a uint32, then storing back to that uint32
...
if (detect_pulse)
{
lwLastA = wTempA //Setting "previous" value to wTempA if a pulse was detected
}
lwtempC = lwTempB - lwLastA //Subtracting uint16 from a uint32
if (lwTempC <= ignore_time) //There must be a significant difference to perform the following actions
{
return;
}
//...perform important actions with micro... (redacted)
...
lwLastA = wTempA //Setting previous value of wTempA
}
I inherited this function from a previous programmer. It is not the way I would do it, but I don't want to rewrite the entire thing if I don't have to.
The function, I believe, should trigger the "important actions" if one of two conditions occur. One is if an outside event occurs that causes update_counter
to increment, the other is if more time has passed than ignore_time
.
Is all of the expected behavior for each of these lines above clearly defined and will it produce consistent results?
A few specific concerns I have:
Is it clearly defined that the bitwise OR between lwTempB (uint32) and wTempA (uint16) will compare the lower 16-bits.
update_counter
will roll-over after a certain amount of time passes (the events it counts occur at a set frequency unless there's a problem), at that roll-over point, lwLastA will actually be larger than lwTempB. Will there be clearly defined behavior here, where a two unsigned integers are subtracted in a way that would normally yield a negative result, and then it is being assigned to an unsigned integer? From the boolean math, I think this will result in lwTempC always having a value larger than ignore_time and therefore cause a trigger still, so the sloppy coding should still provide the desired result?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有实现定义的行为。这意味着,C语言不能定义行为,但是您的实现(编译器和标准库)必须。
在整数操作中,根据您的编译器给出的规则,将双方晋升为INT,无签名的INT,长或未签名的长度。现在,涉及的类型之一是“未签名的短”。在16位系统上,短和int都可以是16位,因此无符号短的简短不能被“促进”到INT,而是将未签名的INT替换为int。在32位系统上,INT将为32位,未签名的简短将晋升为INT。因此,您的操作可以使用未签名的INT或INT操作数执行,这有所作为。特别是如果您比较数字。
打开所有可用警告,希望您会被告知有关不良行为的信息。
There is implementation defined behaviour. That means, the C language doesn't define the behaviour, but your implementation (compiler and standard library) must.
In an integer operation, both sides are promoted to the int, unsigned int, long or unsigned long, depending on rules given by your compiler. Now one of the types involved is "unsigned short". On a 16 bit system, short and int could both be 16 bits, so unsigned short cannot be "promoted" to int, but to unsigned int instead. On a 32 bit system, int would be 32 bit, and unsigned short would be promoted to int. So your operation could be performed with unsigned int or with int operands, and that makes a difference. Especially if you compare numbers.
Turn on all available warnings, and hopefully you will be told about unwanted behaviour.