c 中的结构中的 _Noreturn:错误:“_Noreturn”之前预期有说明符限定符列表

2024-01-09

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

#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);

所以我尝试了来自的建议here https://stackoverflow.com/questions/28552467/is-there-a-way-to-use-gcc-attribute-noreturn-and-stdnoreturn-h-sanely-i:

#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:

#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

但错误仍然发生:

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 编译的,所以它应该可以工作:

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:

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 开始 https://gcc.gnu.org/wiki/C11Status).

我做错了什么以及如何解决此错误?

--
编辑:也许一个独立的示例可以帮助:

main.c:

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

struct s {

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

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

编译这个:

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:

$ 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.

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

你将不得不放弃这个想法。函数说明符 (inline and _Noreturn) 不是函数类型的一部分。

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


通过函数指针调用并保留_Noreturn语义,也许你可以做一个垫片,例如:

inline _Noreturn void call_somefunc( struct s *ps, bool b )
{
    ps->somenoreturnfunc(b);
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c 中的结构中的 _Noreturn:错误:“_Noreturn”之前预期有说明符限定符列表 的相关文章

随机推荐