【问题标题】:C, Why is my 'px' variable zero?C,为什么我的 'px' 变量为零?
【发布时间】:2016-03-09 21:31:59
【问题描述】:

好的,这个错误很奇怪,我不知道发生了什么。 我在 at90usb1286 上运行我的代码。

这是有问题的代码:

        uint16_t r = rand();
        t1 = r;

        px = r%52;
        t2 = px;

        py = r%28;
        t3 = py;

        px = px * 6;
        t4 = px;

        py = py * 8;
        t5 = py;

        py += 8;

上下文:

t# 变量是我用来调试的临时变量... 它们显示在连接的显示器上。 px 和 py 只是全局 uint16_ts。

错误:

除 t4 之外的所有 t# 变量都显示合理值,但无论 t2 显示什么值,t4 都保持为 0。

为什么!!!?

这几个小时一直在我的脑海里挥之不去! :'(

感谢您的建议! :) 我知道这可能不是使用随机数的好方法:P

(我已经标记了 arduino,因为我怀疑它可能相似)

其余代码: (我也尝试过使用非静态全局变量)

#include "util/cli.h"
#include "drivers/lcd/syscalls.h"
#include "drivers/input/syscalls.h"
#include "drivers/led/syscalls.h"
#include "drivers/scheduler/syscalls.h"
#include <util/delay.h>

static int x = 0, y = 0;

static int px;
static int py; /*Pickup*/

static uint16_t score = 0;

static uint8_t dir; /*0 -> NESW <- 3*/

static uint16_t t1, t2, t3, t4, t5;

void render_thread() {
    lcd_clear_screen();

    while(1) {
        cli();
        lcd_display_char_xy(' ', x, y);
        if(dir & 0x01)
            y -= 8;

        if(dir & 0x02)
            x += 6;

        if(dir & 0x04)
            y += 8;

        if(dir & 0x08)
            x -= 6;

        if(x < 0)
            x = 0;
        if(y < 8)
            y = 8;
        if(x > 312)
            x = 312;
        if(y > 232)
            y = 232;

        lcd_display_char_xy('.', px, py);
        lcd_display_char_xy('@', x, y);
        /*Display score*/
        lcd_display_move(0, 0);
        lcd_display_hex(&score, 2);

        /*Display test variables*/
        lcd_display_move(60, 0);
        lcd_display_hex(&t1, 2);
        lcd_display_move(100, 0);
        lcd_display_hex(&t2, 2);
        lcd_display_move(140, 0);
        lcd_display_hex(&t3, 2);
        lcd_display_move(180, 0);
        lcd_display_hex(&t4, 2);
        lcd_display_move(220, 0);
        lcd_display_hex(&t5, 2);
        sei();
        _delay_ms(16);
    }
}

void game_thread() {
    px = 24;
    py = 32;

    while(1) {
        cli();
        if(px == x && py == y) {
            uint16_t r = rand();
            t1 = r;

            px = r%52;
            t2 = px;

            py = r%28;
            t3 = py;

            px = px * 6;
            t4 = px;

            py = py * 8;
            t5 = py;

            py += 8;
            score++;
        }
        sei();
        scheduler_switch();
    }
}

void user_thread() {
    while(1) {
        if(switch_north())
            dir |= 1;
        else
            dir &= 0x0E;

        if(switch_east())
            dir |= 1<<1;
        else
            dir &= 0x0D;

        if(switch_south())
            dir |= 1<<2;
        else
            dir &= 0x0B;

        if(switch_west())
            dir |= 1<<3;
        else
            dir &= 0x07;

        scheduler_switch();
    }
}

void cli_start() {
    Task* game_task = scheduler_create_task(game_thread, 128);
    scheduler_submit_task(game_task);

    Task* render_task = scheduler_create_task(render_thread, 128);
    scheduler_submit_task(render_task);

    Task* user_task = scheduler_create_task(user_thread, 128);
    scheduler_submit_task(user_task);
}

【问题讨论】:

  • 那么,基本上你想说(rand()%52)*6总是0?
  • t# 变量是如何声明的?
  • 你能显示完整的代码吗?同时提供所有涉及的值。
  • 你打电话给srand了吗?在您的实现中,未播种的rand 可能会产生一个可被52 整除的数字。 rand 返回什么?
  • 如果未提供要求的信息,则投票结束。

标签: c arduino avr


【解决方案1】:

rand() 的初始值可能可以被 52 整除(正如 Lashane 所建议的那样)。首先,如果您正在使用,请尝试确保您致电srand() - 但请确保您准确且仅调用一次。对于简单的应用程序,您可以使用 time() 值播种到 srand,但是对于更安全的应用程序,您应该找到一些不容易被猜到的东西来播种。

你总是有这个值可以被 52 整除的风险,所以如果零是一个不受欢迎的值,请使用

px = (r%51)+1;

确保返回的值在 1 到 51 之间

【讨论】:

  • 感谢您的建议,从我上面的评论中可以看出,rand() 返回的值非常好。模数也产生了良好的价值。只有当我将它相乘时它才变为零。也就是说,无论 th 模的结果如何,它总是为零。
  • 我不知道您使用的是什么编译器,但我会开始研究任何已知的 (1) 编译器问题,(2) 不同的优化级别,以及 (3) 查看创建 - 并使用您可以使用的任何调试器来单步执行代码。
  • 是的,我认为编译器可能在这里做了一些愚蠢的事情......:/我会调查一下。
  • 确保 sizeof int 是您认为的那样,至少使用 gcc,有编译器选项可以在 AVR 处理器上制作 int 8 位,尽管您还应该仔细查看(所有)任何代码缓冲区溢出,您可以移动 px 的声明以尝试查看是否有任何缓冲区溢出影响它。
  • 看看地址 19A 和 1BC,game_thread() 似乎在两个地方......看起来也很奇怪的是,21C 似乎依赖 1BC 来获取 r15 中的值。这种奇怪的设置正常吗? drive.google.com/…
【解决方案2】:

您正在创建 3 个线程,但您不关心写入内存冲突。

两个线程都在使用 px:game_threadrender_thread,可能 render_thread 中的 lcd_display_char_xy 需要引用 px,并在未预料的时间内对其进行修改。

我建议你尝试使用一个“int pxg”专门用于game_thread,其他“int pxr”专门用于render_thread(并删除int px)。它必须解决问题。

或者,为了测试,您可以注释 lcd_display_char_xy('.', px, py);,并且 game_thread 中的 px 必须按预期方式工作。

【讨论】:

  • 请记住,我编写了调度程序并在访问变量时禁用了中断。我认为这不是问题。
  • 不,评论 lcd_display_char_xy('.', px, py);不起作用... :(
  • 和 int pxg y int pxr 测试?
  • 没有写冲突。中断被禁用,因此任务切换不会发生。
  • 这是在单核 8 位微控制器上顺便说一句:P
【解决方案3】:

嗯,这似乎是一个优化问题。我最初使用优化标志 -Os 并将其更改为 -O3-Ofast 后它似乎运行完美:)

我不知道大小优化代码到底发生了什么,但编译器似乎将 game_thread 代码分成了几个混乱的部分......

感谢大家的帮助! :D

【讨论】:

    猜你喜欢
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多