【问题标题】:Function causes variables passed by reference to behave unexpectedly函数导致通过引用传递的变量行为异常
【发布时间】:2018-12-30 04:28:34
【问题描述】:

我有一个使用SDL2 的C 程序。当PenTool 的内容不在函数中而是在调用函数的位置时,我有一个工作程序,但是将其放入函数中导致了一个我无法理解的问题。避免使用全局变量,我已经通过引用传递了我需要操作的所有变量,包括 PenTool 中的函数bresline。该代码应该通过使当前鼠标坐标为终点而前一个鼠标坐标为线的起点来从鼠标绘制一条连续的线。但是,在这个功能布局中,当前鼠标坐标被正确识别并在屏幕上绘制,但之前的鼠标坐标保持不变,导致每条线都从同一点开始绘制,而不是实际的先前鼠标位置。此外,打印功能将所有变量显示为在鼠标移动时不变,尽管正在运行的程序绘制我的鼠标所在的位置。

问题在于bresline。当我注释掉它时,打印函数显示所有变量随着鼠标移动而正确更新,所以有人可以解释为什么bresline 会阻止以前的鼠标坐标被正确分配,以及为什么它会阻止printf 显示正确的鼠标坐标.

我在 StackOverflow 和其他地方查看了有关正确通过引用传递的其他问题,据我所知,我已经正确传递了我的变量,但我不知道如何阅读 C++/Java所以这些答案没有帮助,所以我真的不知道我哪里出错了。

void bresline(SDL_Renderer *,int *, int *, int *, int *, Uint32 *);
void PenTool(int, int *, int *, SDL_Point, int *, int *, SDL_Renderer *, Uint32 *);

int main(void)
{
    int mouseX = 0, mouseY = 0, prevMouseX = 0, prevMouseY = 0;
    int penSize = 1;
...
    case SDL_MOUSEMOTION:
        if(leftMouseButtonDown)
        {
            PenTool(penSize, &mouseX, &mouseY, mouse_position, &prevMouseX, 
                &prevMouseY, renderer, pixels);
        }
...
void bresline(SDL_Renderer *renderer, int *x0, int *y0, int *xn, int *yn, Uint32 *pixels)
{
    int dx = abs(*xn-*x0), sx = *x0<*xn ? 1 : -1;
    int dy = abs(*yn-*y0), sy = *y0<*yn ? 1 : -1; 
    int error = (dx>dy ? dx : -dy)/2, e2;
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    while(1)
    {
        pixels[*y0 * 1000 + *x0] = 0;
        if(*x0==*xn && *y0==*yn) break;
        e2 = error;
        if(e2 >-dx)
        {
            error -= dy;
            *x0 += sx;
        }
        if(e2 < dy)
        {
            error += dx;
            *y0 += sy;
        }
    }
}

void PenTool(int penSize, int *mouseX, int *mouseY, SDL_Point mouse_position, 
    int *prevMouseX, int *prevMouseY, SDL_Renderer *renderer, Uint32 *pixels)
{
    if(penSize == 1)
    {
        *mouseX = mouse_position.x;
        *mouseY = mouse_position.y;
        if((*prevMouseX == 0) && (*prevMouseY == 0))
        {
            *prevMouseX = *mouseX;
            *prevMouseY = *mouseY;
        }
        bresline(renderer, mouseX, mouseY, prevMouseX, prevMouseY, pixels);
        *prevMouseX = *mouseX;
        *prevMouseY = *mouseY;
        printf("M1_x: %d, M1_y: %d, M2_x: %d, M2_y: %d \n", *mouseX, *mouseY, *prevMouseX, *prevMouseY);
    }
}

【问题讨论】:

  • 尝试调试你的代码。
  • @AtulKumar 在 clang 中,我使用了 -Weverything 并且在编译过程中没有出现警告或错误。还有哪些其他的调试方案?
  • @User.Flynn -W 选项请求静态分析,这与调试是分开的。调试通常涉及检查程序实际运行时的行为。有多种工具可以帮助解决这个问题,具体取决于您的平台和编译器。
  • @AtulKumar 你能推荐任何我可以用于 Linux/RedHat 和 Clang 5.0 的吗?
  • 在基本级别上,在程序运行时,根据需要打印变量的值,尽可能多地调用printf。当您看到一个您不期望的值时,在显示预期值的最后一个和显示意外值的第一个之间添加更多对 printf 的调用。重复直到你确定问题出在哪里。

标签: c function pointers sdl pass-by-reference


【解决方案1】:

顺便说一句,我会将 bresline 更改为:

void bresline(SDL_Renderer *,int , int , int , int , Uint32 *);

void bresline(SDL_Renderer *renderer, int x0, int y0, int xn, int yn, Uint32 *pixels)
{
    int dx = abs(xn-x0), sx = x0<xn ? 1 : -1;
    int dy = abs(yn-y0), sy = y0<yn ? 1 : -1; 
    int error = (dx>dy ? dx : -dy)/2, e2;
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    while(1)
    {
        pixels[y0 * 1000 + x0] = 0;
        if(x0==xn && y0==yn) break;
        e2 = error;
        if(e2 >-dx)
        {
            error -= dy;
            x0 += sx;
        }
        if(e2 < dy)
        {
            error += dx;
            y0 += sy;
        }
    }
}

在您的代码中,您正在更改 Bresenham 算法函数中的值,因此,当函数退出时,MouseX 和 MouseY 将始终是 PrevMouseX 和 PrevMouseY。这可以解释您总是从同一点开始的问题。


并更改为此调用函数的方式:

bresline(renderer, *mouseX, *mouseY, *prevMouseX, *prevMouseY, pixels);

【讨论】:

  • 如果我这样做,我的编译器会警告说存在一个不兼容的指向整数转换的指针,它将“int *”传递给参数类型“int”。当我在窗口中单击时,忽略这些警告会导致分段错误。
  • 如果您更改函数参数的类型,您必须更改调用函数的方式以使它们匹配。顺便说一句,我建议您阅读有关指针、引用、按引用传递值和按值传递值的更多信息。我认为它可能对你有用。
  • 这个链接可能有用:overiq.com/c-programming/101/…
  • 成功了,非常感谢。在您回答之前,我已经阅读了很多关于通过引用传递的信息,所以我认为我没有遗漏任何知识,但我现在清楚地看到了。我现在将更多地研究这个主题。也感谢您提供建议的资源。
猜你喜欢
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
相关资源
最近更新 更多