首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中结构中的_Noreturn :错误:预期的说明符-限定符-在'_Noreturn‘之前的列表

C中结构中的_Noreturn :错误:预期的说明符-限定符-在'_Noreturn‘之前的列表
EN

Stack Overflow用户
提问于 2018-08-08 12:34:19
回答 3查看 812关注 0票数 4

我正在试图编译一段包含_Noreturn的代码:

代码语言:javascript
复制
#ifndef SOMEHEADER_H
#define SOMEHEADER_H

#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

extern struct s {

    _Noreturn void (*somenoreturnfunc)(bool);
} svar;

#endif

这给了我:

error: expected specifier-qualifier-list before '_Noreturn' on:_Noreturn void (*somenoreturnfunc)(bool);

所以我尝试了这里的建议

代码语言:javascript
复制
#ifndef SOMEHEADER_H
#define SOMEHEADER_H

#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

#include "noreturn.h"

extern struct s {

    noreturn void (*somenoreturnfunc)(bool);
} svar;

#endif

不返回。h:

代码语言:javascript
复制
#ifndef NO_RETURN_H
#define NO_RETURN_H
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define noreturn _Noreturn
#elif defined(__GNUC__)
#define noreturn __attribute__((noreturn))
#else
#define noreturn
#endif
#endif

但错误仍在发生:

代码语言:javascript
复制
In file included from ../include/someinclude.h:8:0,
                 from src/main.c:17:
../include/noreturn.h:4:18: error: expected specifier-qualifier-list before '_Noreturn'
 #define noreturn _Noreturn
                  ^
../include/someinclude.h:19:5: note: in expansion of macro 'noreturn'
     noreturn void (*somenoreturnfunc)(bool);
     ^

我感到很困惑,因为它是用c11编译的,所以它应该能工作:

代码语言:javascript
复制
make V=1
cc src/main.c
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -std=c11 -Wall -pedantic -ffreestanding -static -I../libopencm3/include -I../include -DSTM32F1 -g -DDEBUG -DBUILD_STYLE=\"DEBUG\" -O0 -Iinclude -I../librt/include  -MMD -MT build/main.o -MF build/main.d -o build/main.o -c src/main.c
In file included...

GCC版本为5.4.1:

代码语言:javascript
复制
arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:5.4.1+svn241155-1) 5.4.1 20160919
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

它应该支持所有C11特性(_Noreturn支持自4.7以来)。

我做错了什么,如何解决这个错误?

--

编辑:也许一个自我包含的示例可以帮助:

C.主要:

代码语言:javascript
复制
#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

struct s {

    _Noreturn void (*somenoreturnfunc)(bool);
} svar;

int main()
{
        svar.somenoreturnfunc = 0;
        return 0;
}

汇编如下:

代码语言:javascript
复制
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -std=c11 -Wall -pedantic -ffreestanding -static -DSTM32F1 -g -DDEBUG -DBUILD_STYLE=\"DEBUG\" -O0 -MMD -MT main.o -MF main.d -o main.o -c main.c
main.c:7:5: error: expected specifier-qualifier-list before '_Noreturn'
     _Noreturn void (*somenoreturnfunc)(bool);
     ^
main.c:5:8: warning: struct has no members [-Wpedantic]
 struct s {
        ^
main.c: In function 'main':
main.c:12:6: error: 'struct s' has no member named 'somenoreturnfunc'
  svar.somenoreturnfunc = 0;
      ^

然而,当使用相同的命令行编译并删除_Noreturn时,编译就成功了。

使用gcc -std=c11 -o main main.c编译时也会发生这种情况。

代码语言:javascript
复制
$ gcc -std=c11 -o main main.c
main.c:7:5: error: expected specifier-qualifier-list before ‘_Noreturn’
     _Noreturn void (*somenoreturnfunc)(bool);
     ^~~~~~~~~
main.c: In function ‘main’:
main.c:12:6: error: ‘struct s’ has no member named ‘somenoreturnfunc’
  svar.somenoreturnfunc = 0;
      ^
$ gcc --version
gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-08 13:14:56

在ISO中,_Noreturn不能用于函数指针的声明。它只能用于函数的声明。(参考: C11 6.7.4/2)。

你必须放弃这个想法。函数说明符(inline_Noreturn)不是函数类型的一部分。

代码中还有另一个问题:在标头中定义svar,如果头包含在两个或多个翻译单元中,这将导致ODR冲突。它只应该在头中有一个声明,在一个单元中有一个定义。

要通过函数指针调用并保留_Noreturn语义,也许可以创建一个shim,例如:

代码语言:javascript
复制
inline _Noreturn void call_somefunc( struct s *ps, bool b )
{
    ps->somenoreturnfunc(b);
}

但是,没有办法让编译器强制执行,当您分配给函数指针时,它实际上是一个_Noreturn函数。

票数 5
EN

Stack Overflow用户

发布于 2018-08-08 13:15:28

函数说明符_Noreturninline不是函数类型的一部分,它们是声明的一部分。C17标准在6.7.4中指出,函数说明符“只能用于函数标识符的声明”。这意味着它们不能在指向函数的指针的声明中使用。

因此,不幸的是,这是不可能的;类型胡枝子也不会有帮助。

票数 2
EN

Stack Overflow用户

发布于 2018-08-08 14:33:33

已经有许多好的答案了,但为了清楚起见,我想指出以下几点:

来自C11,6.7.4.9:

实现应该为使用_Noreturn函数说明符声明的函数生成一条诊断消息,该说明符似乎能够返回到其调用方。

因此,_Noreturn的目的是通知编译器检查它实际返回的函数中没有控制路径,该路径声明为_Noreturn。

知道了这一点,现在很清楚为什么不能声明函数指针为_Noreturn,因为编译器不能检查分配的函数的返回语义。

(当然,编译器可以将_Noreturn看作类型的一部分,然后检查是否只将_Noreturn函数分配给函数指针。目前标准中的定义对我来说似乎有点无用。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51746897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档