繁体   English   中英

uint64_t变量带&operations

[英]uint64_t variable with & operations

我有一个函数,它在64位变量(RFID标签号)中搜索九个“1”系列,如果找到,则将它们移动到MSB。 理解为什么它不能正常工作我有一个很大的问题。

这是我的变量

uint64_t volatile RFID_data2= 0b1111111110000000000000000000000000000000000000000000000000000000;

我发送它作为函数的指针

test_flag= header_align(&RFID_data2);


uint8_t header_align(uint64_t *data){

uint64_t bit_mask=(uint64_t) 
0b1111111110000000000000000000000000000000000000000000000000000000;


if((*data&bit_mask)==bit_mask){
PORTA ^= (1<<PORTA2);
return 1;
}

这种情况永远不会实现,但如果我改变了这个条件:

if((*data==bit_mask){
PORTA ^= (1<<PORTA2);
return 1;
    }

它似乎运作良好。

更有甚者,我写了另一个条件 - 这是有效的。

if((*data&bit_mask)>(bit_mask-1) && (*data&bit_mask)<(bit_mask+1 )){
    PORTA ^= (1<<PORTA2);
    return 1

我可以看到它与AND'&'操作有关。 另外,当我将RFID_data更改为32位变量时没有任何问题。 我正在使用Attiny441和GCC编译器,Atmel Studio有没有办法让它在64位上工作?

我改变了函数来取uint64t(非指针),但问题仍然存在。 我也尝试创建全局变量,并删除volatile变换器,但它仍然无法正常工作。 使用宏UINT64_C也没有帮助。 看起来像 :

uint64_t RFID_data;// global var

int main(void)
{
  RFID_data=(0xFF80000000000000);// write into global var
 uint64_t RFID_data2=(0xFF80000000000000);
   while(1)
   {
    test_flag=header_align(RFID_data2);// send local variable
   }
}


 uint8_t header_align(uint64_t data){
  uint64_t bit_mask = UINT64_C(0xFF80000000000000);


    if((data&bit_mask)==bit_mask){
     PORTA ^= (1<<PORTA2);//nothink
        return 1;
    }

我还尝试通过全局变量检查if-condtion:

     if((RFID_data&bit_mask)==bit_mask){
     PORTA ^= (1<<PORTA2);///nothink
        return 1;
    }

在两种方式中它都不会返回1,也不会改变PORTA2状态。

它只适用于我在header_allgin中创建一个新的局部变量,如下所示:

 uint8_t header_align(uint64_t data){
  uint64_t RFID_data3 = UINT64_C(0xFF80000000000000);
  uint64_t bit_mask = UINT64_C(0xFF80000000000000);


    if((RFID_data3&bit_mask)==bit_mask){
     PORTA ^= (1<<PORTA2);// here i can see signal
        return 1;
    }}

它是通过全局变量还是通过函数调用来实现的?

只需使用正确的后缀即可。

L为int32

LL为int64

UL for uint32

uint64的ULL

好像你在这里发现了一个真正的编译器错误!

GCC版本:

avr-gcc(GCC)4.8.1

(启用了-O1或-O2优化,在-O0,问题似乎不存在)

减少测试用例:

#include <stdint.h>


uint8_t volatile tmp;


__attribute__((noinline)) void test_64(uint64_t d64)
{
 if ((d64 & 0xFF800000UL) == 0xFF800000UL){
  tmp ++;
 }
}

__attribute__((noinline)) void test_32(uint32_t d32)
{
 if ((d32 & 0xFF800000UL) == 0xFF800000UL){
  tmp ++;
 }
}


int main(void)
{
 test_64(0);
 test_32(0);

 while(1);
}

关键部分的汇编器输出:

00000228 <test_64>:
 228:   08 95           ret

0000022a <test_32>:
 22a:   66 27           eor r22, r22
 22c:   77 27           eor r23, r23
 22e:   80 78           andi    r24, 0x80   ; 128
 230:   61 15           cp  r22, r1
 232:   71 05           cpc r23, r1
 234:   80 48           sbci    r24, 0x80   ; 128
 236:   9f 4f           sbci    r25, 0xFF   ; 255
 238:   09 f0           breq    .+2         ; 0x23c <test_32+0x12>
 23a:   08 95           ret
 23c:   80 91 00 20     lds r24, 0x2000
 240:   8f 5f           subi    r24, 0xFF   ; 255
 242:   80 93 00 20     sts 0x2000, r24
 246:   08 95           ret

00000248 <main>:
 248:   20 e0           ldi r18, 0x00   ; 0
 24a:   30 e0           ldi r19, 0x00   ; 0
 24c:   40 e0           ldi r20, 0x00   ; 0
 24e:   50 e0           ldi r21, 0x00   ; 0
 250:   60 e0           ldi r22, 0x00   ; 0
 252:   70 e0           ldi r23, 0x00   ; 0
 254:   80 e0           ldi r24, 0x00   ; 0
 256:   90 e0           ldi r25, 0x00   ; 0
 258:   0e 94 14 01     call    0x228   ; 0x228 <test_64>
 25c:   60 e0           ldi r22, 0x00   ; 0
 25e:   70 e0           ldi r23, 0x00   ; 0
 260:   cb 01           movw    r24, r22
 262:   0e 94 15 01     call    0x22a   ; 0x22a <test_32>
 266:   ff cf           rjmp    .-2         ; 0x266 <main+0x1e>

意见

对于32位,生成正确的代码。 对于64位,无比较全部执行,所述代码编译仿佛的结果if是始终为false。 本机GCC正确编译这两个函数。

您应该避免在代码中使用64位变量。

该错误现已在GCC bugtracker中得到确认,您可以在此处关注:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85805

所以在撰写本文时,所有足够现代的avr-gcc版本都会受到影响,直到修复完毕。

将常量uint64_t转换为uint64_t并不是制作uint64_t文字的正确方法。 您应该使用UINT64_C宏代替:

uint64_t bit_mask = UINT64_C(0b1111111110000000000000000000000000000000000000000000000000000000);

或者如果你喜欢十六进制

uint64_t bit_mask = UINT64_C(0xFF80000000000000);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM