c - 外部变量和全局变量

标签 c

我无法理解该程序的奇怪行为。它发出警告,但输出令人惊讶。我有3个文件,file1.c,file2c,file1.h

文件1.c:

#include "file1.h"

extern void func(void);

 int main(void)
{
func();
printf("%d\n",var);
return 0;
}

文件2.c:

int var;

 void func(void)
{
var = 1;
}

file1.h 是:

#include<stdio.h>

extern double var;

当我编译并运行时,它按预期显示警告,但在打印时打印 1。但是当我更改 file2.c 中声明的 var 时怎么可能

最佳答案

你似乎有未定义的行为——但在很多时候,这种行为在许多机器上可能是无害的。

由于您的 extern 声明说 var 是一个 double,而实际上它是一个 int,因此尝试访问它作为双重导致未定义的行为。

但实际上,在典型情况下,double 将是八个字节,而 int 是四个字节。这意味着当您将 var 传递给 printf 时,8 个字节的数据将被压入堆栈(但从 var 实际占用的四个字节开始)。

然后

printf 将尝试将其前四个字节(确实对应于 var 的字节)转换为 int,它与 var 的实际类型匹配。这就是为什么这种行为通常是无害的。

同时,如果您的编译器正在进行边界检查,则尝试加载 4 字节变量的 8 字节很容易导致某种“越界”异常,因此您的程序将无法正常工作。大多数 C 编译器不执行任何边界检查,这只是你的不幸。

也有可能(可能在大端机器上)而不是与 var 对应的字节恰好位于堆栈上的正确位置,以便 printf将它们作为 int 访问,构成 double 的其他四个字节将最终出现在该位置,并且会打印垃圾。

另一种可能性是,8 个字节的位模式恰好对应于某个浮点值,一旦您尝试将其作为 float 访问,就会导致异常。考虑到与发出 NaN 等信号相对应的位模式的(小)百分比,出现这种情况的可能性相当小(如果编译器只是将 8 个字节压入堆栈并将其保留,即使正确的位模式也可能不会触发任何内容)在那)。

关于c - 外部变量和全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9962063/

相关文章:

c - 多线程程序的测量时间

c - 每个 str-function 缩写词/首字母缩略词是什么意思?

C - 对函数内部的 Struct* 数组的副本进行排序

c - 为什么 printf 在调用后不会刷新,除非格式字符串中有换行符?

C:读取二进制文件输出零

c - Knapsack - 编程时无法理解某个部分

c - 将 int 传递给需要 char* 的函数

c - C 中体系结构 x86_64 的 undefined symbol

将短数组的值复制到长数组

c - 为什么是 "#define EOF (-1)"而不仅仅是 "#define EOF -1"