【问题标题】:Is there an example of when a null pointer is necessary for proper program execution in C? [closed]是否有一个示例说明何时需要空指针才能在 C 中正确执行程序? [关闭]
【发布时间】:2013-01-01 14:00:18
【问题描述】:

什么是需要使用空指针才能正确执行的应用程序示例?简单地检查空指针并进行测试不算数。这个例子应该是 C 程序员“常用的”。

经过深思熟虑,我有一个可能的例子,但我不想影响响应(目前)。

编辑:这个问题是针对需要 C 知识而不是神一般技能的编程工作的面试。答案不会是该语言的某些深奥方面。

【问题讨论】:

  • 什么意思?就像取消引用 NULL 应该做点什么?
  • 那么你问这个有什么意义呢?
  • @Adam27X - “只检查空指针......不算数”。如果你不能检查一个指针是否为空,你还能用它做什么?
  • 是否使用NULL 来初始化指针数组?
  • NULL 的全部意义在于它是编译器保证不会作为有效内存地址分配给您的唯一值。所以面试问题很奇怪,因为正确的程序执行总是需要NULL。所以你应该能够处理任何涉及使用指针的常见情况,无论它是否是一个简单的测试。

标签: c pointers


【解决方案1】:

函数strtok() 在第二次和后续迭代中依赖 NULL;表现得更好的亲戚strtok_r()strtok_s()也是如此。


重点略有不同:

  • strchr()strstr() 等字符串搜索函数在找不到您要求的内容时返回 NULL 指针。

  • 内存分配函数在分配失败时返回 NULL 指针。

  • fopen() 函数在打开文件失败时返回一个 NULL 指针。

  • opendir() 函数在打开目录失败时返回一个 NULL 指针。

注意到这里的主题了吗? NULL 指针通常作为错误指示返回。这是否算作“只是检查”可能更值得商榷。

【讨论】:

  • 我还被问到在使用malloc() 后是否需要检查任何东西,所以这肯定是在正确的轨道上。
【解决方案2】:

execvp 系列函数期望参数列表以空指针终止。例如,

 execvp("/bin/ls", arguments);

这里arguments应该以NULL结尾。

【讨论】:

  • 不就是“检查空指针并进行测试”吗?我的意思是,这就是 execvp 内部发生的事情 - NULL 只是一个哨兵。也许我误解了这个问题。
  • @CarlNorum:这更像是使用空指针作为可变长度数组的终止符。
  • @Adam27X 你把这个问题变成了令人沮丧的横向思维难题之一,除了更精细的语义点。你想要一个如上所述的答案,还是你想要的一个答案?
  • @Adam27X 让人们猜测你的想法与让他们猜测面试官的想法有何不同?我真的不确定这个问题是否可以回答。
  • @Adam27X 那么你的面试官很深奥。 (判断一个面试问题是否愚蠢的一个很好的经验法则是它会在 SO 上结束。)
【解决方案3】:

链接列表。

struct node
{
   int data;
   node* next;
}

最后一个指针总是必须是NULL,对吧?如果不是,程序将无法正确执行。这仍然可以算作测试,但它是正确执行程序所必需的。想法?

【讨论】:

  • 这不是完全必要的。虽然它确实很常见,但任何其他类型的标志都可以使用。
  • 这个答案与@KingsIndian 的答案基本相同。他的示例将 NULL 用于可变长度数组终止。这个使用它作为一个列表,但两者都不需要
  • IIRC, Sedgewick's linked list implementation in C++(不是这个版本,而是第 2 版,我想。也许它的实现仍然相同。)分配了一个端节点(它在 next 中指向自身),它是列表末尾。
  • 你可以有一个循环链表,其中尾节点指向头节点,并且没有指针为空(除非链表为空)。
【解决方案4】:

NULL 值显然对于指示某个值的“结束”或“不存在”非常有用。例如,函数中的可选参数由 NULL 表示。或“尚未分配...”。

但是 NULL 值作为参考没有用,除了比较之外,在不需要指针时使用 NULL 值或赋值是不正确的[显然,假设它已被正确释放]。

我正在编写一段在操作系统启动初期运行的代码 - 在代码的后期运行中,它需要在某些地方具有当前任务。但在系统正常启动之前,没有当前任务。所以我需要指出“没有当前任务”。我使用 NULL 指针 [然后如果指针为 NULL 则访问相关的“保留”数据结构] 和一个变量来检查是否已创建任务。 [这很简单,但概念适用]。

从技术上讲,在 MS-DOS(或“实模式”下的其他 8086)中,NULL 指针也将用于设置除以零的向量 [即“向量零”,向量表位于地址零 - 所以 NULL]。但是由于现代操作系统[通常]在其他地方有中断向量表,并且零地址通常受到读/写操作的保护,这不再是指针的“有效使用”。当然,其他一些嵌入式系统可能仍然使用地址零来表示“有意义”。

【讨论】:

    【解决方案5】:

    在我的头顶:

    • strtok 中使用以获取第一个令牌之后的后续令牌;
    • exec* 函数中终止参数列表
    • realloc 中用于初始分配

    【讨论】:

      【解决方案6】:

      NULL 可以安全地传递给free(),因此初始化指向NULL 的指针通常很有用,因为它们可能会或可能不会在以下代码中得到malloc()-ed。然后您可以安全地拨打free(),例如在函数的末尾,不管指针是否被实际使用,例如

      int * p = NULL; // NB: without this initialisation we would need additional logic
                      //     to know whether to call free(p) or not later...
      ...
      
      if (...)
      {
          ...
          if (...)
          {
             ...
             p = malloc(42);
             ...
          }
          ...
      }
      
      ...
      
      free(p);         // free allocated memory, or no-op if p == NULL
      

      【讨论】:

      • free 的这种行为是否得到保证?我敢肯定,如果你释放了一个 NULL 指针,我过去使用的一些 C 实现会产生非常奇怪的效果。适用于 MacOS Classic 的 ThinkC 就是其中之一……
      • @KenKeenan - 见Does free(ptr) where ptr is NULL corrupt memory?。答案是:是的,很安全。
      • 是的,我相信它在 C89 和 C99 中是标准的,但早期的实现(C89 之前的)可能没有兑现这一点。顺便说一句,相同的约定适用于 C++ 中的 deletedelete []
      猜你喜欢
      • 2015-09-05
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 2022-08-16
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多