我在标头中定义了一个全局变量/缓冲区。我有两个源文件,一个函数库(lib.c)和一个测试平台(tb.c),两者都包含头文件。
在库中,我填充全局变量缓冲区,打印指针值并通过迭代指针来打印u8缓冲区的一些条目,即[1,2,3,4,5等],指针0xC8004C58 (缓冲长度= 2144)。
现在在测试平台上,我以相同的方式在完全中获取指向同一个全局u8缓冲区的指针。现在我的解释是全局变量保持在同一个位置,所以指向它的开始的指针应该是相同的,但是我得到指针0xC80054D8。显然,当指针现在不同时,返回的数据是[0,0,0,0,0等]。
所以: 如果u8缓冲区停留在同一个地方并且是全局定义的,为什么我指向这个缓冲区的指针会有所不同,这取决于我是否在lib.c或tb.c中?
我使用以下方法在标题中创建缓冲区:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
我使用:
在lib.c文件中创建指针u32 *RxBufferPtr_Data = RxBuffer_Data;
我使用以下命令在tb.c文件中创建指针:L u32 * RxBufferPtr_Data = RxBuffer_Data;或& RxBuffer_Data。这两个都返回相同的值,并且都不等于正确打印出lib.c文件中缓冲区数据的指针。
答案 0 :(得分:4)
static
指示编译器实例化一个变量,该变量具有与当前翻译单元的内部链接(.c文件加上所有#include
d个东西)。内部链接表示不导出符号(名称)。因此,使用匹配名称这一事实无关紧要。
因此,在这里,您为每个.c文件获取一个单独的实例#include
该标头。作为单独的对象,它们当然具有不同的地址。
如果你想在多个TU之间共享一个实例(以及因此地址),那么就这样做:
extern
- 而不是static
。这样做表示它具有 extern al链接,即在其他地方定义。不要在标题中定义变量。它必须只定义一次,所以...... 对static
vs extern
的基础知识的一些轻松阅读将使这一切清楚。
答案 1 :(得分:2)
每个编译单元都包含自己的缓冲区,因为您通过在标头的缓冲区声明中提供关键字static
来声明它具有内部链接。
您应该在标题中声明它,如
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
并在某些模块中将其定义为
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
或者就像
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
没有初始值设定项,因为无论如何它都会被编译器初始化为具有静态存储持续时间的零。
在这种情况下,缓冲区将由包含标题的所有编译单元共享。
答案 2 :(得分:1)
问题在于:
我使用以下方法在标题中创建缓冲区:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
上面在包含标题的每个c文件中创建了一个单独的变量副本。换句话说,来自单独模块的可能全局变量对于链接器是不可见的,这使它们彼此无关,并为它们提供单独的地址。
如果你想创建一个全局变量,请在标题中声明它,如
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
然后在包含main()
函数的文件中定义它,如下所示:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
答案 3 :(得分:1)
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
您在头文件中将RxBuffer_Data
定义为static
,它告诉编译器您只需在此文件中使用此变量。当lib.c
包含您的头文件时,它在lib.c中定义。RxBuffer_Data
tb.c
会在包含头文件时重新定义,此RxBuffer_Data
是一个新变量。因此,您可以找到两个指向RxBuffer_Data
的指针不同。< / p>
如果要定义全局变量,可以在lib.c
:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
并在你的头文件中声明:
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
顺便说一下,不要在头文件中定义全局变量,因为一旦你包含了这个头文件,你就会重新定义它。