30

如何确定整数是否未分配?

int i; /* no assignment */

if (/* conditional statement here to check if int i is unassigned or not */) {
   printf("Integer is unassigned!\n");
} else {
   printf("Integer is assigned!\n");
}
4

12 回答 12

24

你不能。它将具有“未定义”的内容,这意味着它将包含当时发生在该内存位置的内容。

. . . 除非 i 在全局范围内声明,否则它将被初始化为零。

于 2009-08-04T09:28:02.717 回答
8

C 本质上并不支持这一点——就像它本质上不支持对数组进行边界检查一样。这是速度/效率和安全性之间的权衡。

一般来说......初始化你的变量。

于 2009-08-04T09:28:14.980 回答
4

正如其他人所指出的,您不能编写一个 C 程序来检测其自身变量之一是否未初始化,并且您应该努力确保变量始终被初始化。

  • 如果您的目标是确保所有变量都已初始化,那么像valgrind这样的工具可以通过昂贵的运行时分析动态检测未初始化变量的使用。

  • 如果您的目标是确保私有数据只初始化一次,通常的方法是使用

    int i;
    static bool initialized = 0;
    
    ... 
    if (!initialized) {
      initialized = 1;
      i = ... i's initial value ...;
    }
    
于 2009-08-04T16:10:43.493 回答
4

如果i是全局的或者静态的,它的值就是0,否则它的值可以是任何东西,没有办法判断它是否是垃圾。

于 2009-08-04T09:28:18.927 回答
4

这很简单。你知道它是未分配的,因为你没有初始化它。

于 2009-08-04T09:29:55.473 回答
4

如果您使用未初始化的值,您可能会要求编译器警告。然而,它们并不完全可靠——在 DFA 没有你希望的那么聪明的情况下,你偶尔会得到误报,并且可能偶尔会出现误报(我希望不会,但我什么都不保证)。

对于海湾合作委员会:

-Wuninitialized -O1

如果要编写条件代码:

int a = 3;
int b;
int *p = (rand() > RAND_MAX/2) ? &a : &b;
if (is_uninitialized(*p)) // blah

那你就不走运了。与某些动态语言不同,C 没有“未定义值”的概念。如果一个变量没有被初始化,它就不会被赋予一些可以在以后测试的特殊值。它根本没有被赋予一个值,所以当你使用这个变量时会发生什么是未定义的。

于 2009-08-04T09:39:26.033 回答
1

在初始化(或赋值)之前使用变量是导致错误的严重原因。您无法在运行时可靠地检查它,但您可以在编译期间或之前检测到它。

我建议不要在代码中检查它。因为这可能会导致编译器警告(变量“i”在被赋值之前使用),会引入新的错误并且在大中型程序中成功的机会很小。

最好的方法是使用静态代码分析工具(如 QA/C 或 PCLint)。在高警告敏感度级别使用编译器是一个免费选项,作为专用工具的覆盖范围要小得多。

如果您执行代码审查,您还可以在清单中包括对未初始化变量的检查。这不能保证,但它会触发审阅者的手动检查。

如果它是您想要的运行时检查,那么您可以通过将变量初始化为超出范围的值来开始。例如 -1 表示其他正值。然后你可以检查

#define UNASSIGNED_VALUE -1
    static int number_of_apples = UNASSIGNED_VALUE;
    if (UNASSIGNED_VALUE == number_of_apples)
    {
       // error handling
    }

这不是一个真正的“未初始化”变量,但至少您可以检测到是否完成了合法范围内的运行时分配。

于 2009-08-04T10:05:08.727 回答
1

通常变量由 C 库设置为 0,但不一定。

但基本上,你不能。在定义中为它们分配一个默认值,例如:

int i = 0; /* Or what ever value you know won't be used elsewhere */

然后,如果您运行一些代码并想检查是否在那里设置了值,您可以与您的初始值进行比较。

于 2009-08-04T09:29:10.047 回答
1

正如所有先前的答案一样,无法在运行时检测到这一点。但是,几乎所有静态代码分析工具都会警告您未分配的变量。

于 2009-08-04T09:38:56.160 回答
0

在 C 中,整数在创建时具有未定义的值。这意味着,如果您第一次使用该整数来自带有 5893872 的寄存器/内存位置/设备,那么这就是该整数的值。(里程因调试/发布编译而异。)

处理此问题的常用方法是使用无意义的默认值:

int number_of_widgets = -1;

...或指示其状态的标志:

int number_of_widgets;
int number_of_widgets_assigned = 0;

if (number_of_widgets_assigned)
  do something
else
  do something else
number_of_widgets_assigned = 1;

没有其他方法可以检测是否已分配某些内容 - 除非您想进入硬件的调试功能,我怀疑这不是本次谈话的内容。

于 2009-08-04T09:32:03.693 回答
0

检查您正在使用的变量是否在运行时被初始化(分配)对于 C 来说是出了名的困难。它没有语言支持,运行时可用的信息不足以完美地检测未初始化的值。Valgrind/Memcheck 等动态分析工具经过了很长时间(例如跟踪进程地址空间中的每个内存字节,然后检查每个存储以将字节标记为已初始化)以确定使用的值是否已初始化和仍然容易出现误报。

如果您只是想尽量减少程序中的此类错误,那么 lint 等静态分析工具可以很好地告知您是否使用了未初始化的变量。事实上,我相信大多数编译器会尽力告诉你何时执行此操作(尽管它们当然并不完美。)

于 2009-08-04T10:13:48.507 回答
-5

在 C# 中,我会使用:

Nullable<int> i = null; /* null assignment */

if (i == null) {
   printf("Integer is unassigned!\n");
} else {
   printf("Integer is assigned!\n");
}

不过,不确定这是否会转化为 C。

于 2012-11-23T05:40:33.890 回答