Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是否有一个属性告诉编译器忽略缺少的返回语句?_C - Fatal编程技术网

C 是否有一个属性告诉编译器忽略缺少的返回语句?

C 是否有一个属性告诉编译器忽略缺少的返回语句?,c,C,我不相信这是一个重复,因为函数确实返回了愉快的路径。使用属性no return允许编译器在假定函数永远不会返回的情况下进行优化,但这里的情况并非如此 我有一个C代码,它要么返回一个指针,要么调用另一个函数退出程序。这在if语句中,因此它要么返回结果,要么退出。由于函数返回一个void*,编译器警告函数可能不会返回值(这当然是真的): 错误:控件到达非无效函数的末尾[-Werror=返回类型] 我可以通过添加return*temp到函数末尾,但我想通过使用类似未使用变量属性的内容来明确我的意图:

我不相信这是一个重复,因为函数确实返回了愉快的路径。使用属性
no return
允许编译器在假定函数永远不会返回的情况下进行优化,但这里的情况并非如此

我有一个C代码,它要么返回一个指针,要么调用另一个函数退出程序。这在
if
语句中,因此它要么返回结果,要么退出。由于函数返回一个
void*
,编译器警告函数可能不会返回值(这当然是真的):

错误:控件到达非无效函数的末尾[-Werror=返回类型]

我可以通过添加
return*temp到函数末尾,但我想通过使用类似未使用变量属性的内容来明确我的意图:

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

这样我就可以打开
-Wall
,而不必添加不必要或可能令人困惑的代码

如果有更好的方式表达这个意图,我也会重新编写代码

代码如下所示:

void *get_memory() {
    void *temp = malloc(100);
    if (temp) {
        // do some setup work
        return temp;
    } else {
        exit_program_with_epic_fail();
    }
    // Compiler warns if the following line isn't present
    return temp;
}

有两种方法可以消除警告:

  • 在C11中使用适当的属性
    \u Noreturn
    退出程序\u添加epic\u fail()
    函数标记,但对于C11之前的编译器没有可移植的方法。许多编译器支持
    \uuuu属性((noreturn))
    ,特别是gccclangtinycc,但它是编译器特定的扩展
  • 重新组织代码,让编译器看到函数始终返回
以下是修改后的版本:

void *get_memory(void) {
    void *temp = malloc(100);
    if (!temp) {
        exit_program_with_epic_fail();
    }
    // do some setup work
    return temp;
}

这似乎是一个纯粹的设计问题

警告/错误“控制达到非无效函数的末尾”不是问题,它只是一个指示器,告诉您实际问题在哪里

您可以/应该简单地将函数重写为

void *get_memory (void) 
{
  void *temp = malloc(100);
  if(temp != NULL)
  {
    // do stuff
  }

  return temp;
}
并将错误处理留给调用方。因为终止应用程序不是分配函数的工作——这是糟糕的设计

具有详细错误处理的替代版本:

typedef enum
{
  OK,
  ERR_OUTOFMEMORY,
  ...
} err_t;

err_t get_memory (void** mem) 
{
  *mem = malloc(100);
  if(*mem == NULL)
  {
    return ERR_OUTOFMEMORY;
  }

  // do stuff

  return OK;
}

你能分享一下实际返回和退出调用的代码吗?问题在于退出的函数-!如何:
如果(!temp){
退出程序并失败()
/*执行一些设置工作*/
返回temp?或者:
if(temp){
/*做一些设置工作*/
}否则{
退出程序并返回temp;
返回temp?@IanAbbott这是一个如此明显的答案-我想我没有看到树木的树木!我很想看看这个用例是否有编译器属性,但如果没有,如果你把它作为答案,我会接受:)“终止应用程序不是分配函数的工作”,这是有争议的。当
malloc
和family开始出现故障时,这通常意味着系统内存不足,因此对于大多数应用程序来说,除了
exit
之外没有什么可做的。它还集中了错误处理。@dbush最好将错误处理集中在顶层。如果由于没有内存,程序甚至无法继续执行清理,那么可能不管您如何编写它。但如果可以的话,很容易知道程序在哪里失败以及为什么失败。也就是说,它在第666次调用
get_memory
时失败,而不仅仅是“分配内存失败”。@Lundin在这种情况下,分配函数(在实际代码中不是
malloc
)将需要在许多不同的位置进行自定义处理,所有这些都将简单地终止程序。至少对于我的用例来说,知道什么分配内存失败或者哪个尝试失败是没有用的——它无法获取内存,也无法继续,所以快速记录并退出,以便系统可以重新启动它。我当然有兴趣知道更好的方法来处理这个特殊问题!:)@PeterM终止程序的调用应该来自主应用程序,而不是它使用的模块/库。主应用程序也是在顶层集中错误处理的地方。没有什么比去中心化的错误处理更糟糕了。@PeterM糟糕库的一个典型例子是那些对“无论如何都不会发生”的事情进行本地化错误处理的人。通常,“意外错误”的发生并不是因为理论上的、永远不会发生的意外的事情,而是因为普通的老错误。例如,与没有内存的计算机相比,由于缓冲区溢出或代码失控,指向malloc内存的指针设置为null的可能性要大得多。