全局变量似乎有两个不同的地址......?

时间:2015-02-18 20:24:18

标签: c msvc12

考虑以下4个文件:

[core.h]

#pragma once  
static int MY_MARK = -1;  

[count.h]

#pragma once
#include "core.h"
#include <stdarg.h>
#define Count(...) CountImpl(&MY_MARK, __VA_ARGS__, &MY_MARK)
int CountImpl(void*, ...);

[count.c]

#include "count.h"

int CountImpl(void* dummy, ...) {
    int     count = 0;
    va_list lst;

    va_start(lst, dummy);

    for(;;) {
        void* ptr = va_arg(lst, void *);
        if(ptr == &MY_MARK) {break;}
        ++count;
    }

    va_end(lst);
    return count;
}

[WeirdProblem.c]

#include <tchar.h>
#include "count.h"

int _tmain(int argc, wchar_t* argv[], wchar_t* envp[]) {
    int a = 1;
    int b = 2;
    int c = 3;
    int d = Count(&a, &b, &c);
    return 0;
}

我正在使用Microsoft Visual Studio Community 2013.
当运行上面的代码时,我希望'd'变量的值为3.问题是执行永远不会从循环中断,因为它不会比较'ptr'和'&amp; MY_MARK'是相等的。 (最终它会在尝试读取受保护的内存或其他任何内容时抛出错误。)
实际上,我在Watch窗口中看到两个不同的地址:

(int*)ptr       0x000000013f8d9004 {WeirdProblemTest.exe!int MY_MARK} {-1}  int *
&MY_MARK        0x000000013f8d9000 {WeirdProblemTest.exe!int MY_MARK} {-1}  int *

我知道我可以使用'dummy'变量解决问题而不是引用'&amp; MY_MARK',但这不是重点。
我真的需要了解发生了什么,因为同样的问题发生在我的代码的不同部分,并且那里没有这么好的解决方法。

对于长篇文章感到抱歉,但我发现没有办法让它更短。

1 个答案:

答案 0 :(得分:4)

您已将.h文件中的变量声明并定义为static,这意味着每个文件#includes标题将获得自己的< em>私有变量的副本。

您需要将core.h分为core.hcore.c,如下所示:

core.h:

#pragma once  
extern int MY_MARK;

core.c:

#include "core.h"

int MY_MARK = -1;

所有其他文件应为#include "core.h",在编译和链接时,您应链接到core.c