编译期间出现以下错误:
error: ‘asm’ undeclared (first use in this function)
EXCHANGE( s, *(a) );
^
在头文件中调用宏,如下所示:
EXCHANGE( s, *(a) );
宏的实际定义如下:
#define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) )
宏调用和定义存在于同一个头文件中。 出了什么问题?
我正在使用CMAKE构建项目,CFLAGS如下:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wswitch-default")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
#-Wno-deprecated-declarations to suppress the deprecation errors with newer version of JSON-C
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-overflow=5")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Winline")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wundef")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wnested-externs")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-cast-qual")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunreachable-code")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wfloat-equal")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-aliasing=2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wredundant-decls")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wold-style-definition")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3 -ggdb")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -E")
答案 0 :(得分:11)
您正在使用选项-std=c99
进行编译。
这会禁用某些非标准GCC扩展程序,例如asm
功能。
请参阅https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-112了解一些(非常精确的)文档。
如果需要内联汇编,请从cmakefile中删除或更改行set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
。
答案 1 :(得分:8)
使用__asm__
代替asm
代替-std=c99
,或使用-std=gnu99
来自GCC文档https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Extended-Asm.html
asm关键字是GNU扩展。在编写可以使用-ansi和各种-std选项编译的代码时,请使用
__asm__
而不是asm(请参阅备用关键字)。
和https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Alternate-Keywords.html#Alternate-Keywords:
-ansi和各种-std选项会禁用某些关键字。当您想要使用GNU C扩展或所有程序(包括ISO C程序)都可以使用的通用头文件时,这会导致麻烦。关键字asm,typeof和inline在使用-ansi或-std编译的程序中不可用(尽管内联可以在使用-std = c99或-std = c11编译的程序中使用)。 ISO C99关键字限制仅在-std = gnu99(最终将是默认值)或-std = c99(或等效的-std = iso9899:1999)时使用,或者使用后续标准版本的选项时才可用。
解决这些问题的方法是将
__
放在每个有问题的关键字的开头和结尾。例如,使用__asm__
代替asm,使用__inline__
代替内联。其他C编译器不接受这些替代关键字;如果要使用其他编译器进行编译,可以将备用关键字定义为宏,以使用常规关键字替换它们。它看起来像这样:
#ifndef __GNUC__ #define __asm__ asm #endif
-pedantic和其他选项会导致许多GNU C扩展的警告。您可以通过在表达式之前写
__extension__
来防止在一个表达式中出现此类警告。__extension__
除此之外没有任何影响。
-std=gnu99
启用了asm
之类的GNU扩展,同时仍保持与C99类似的语言。
C99标准
GCC的工作方式符合C99标准。来自C99 N1256 standard draft 7.1.3"保留标识符" 1:
每个标头声明或定义其相关子条款中列出的所有标识符,以及 可选地声明或定义其关联的未来库方向中列出的标识符 子条款和标识符,它们总是保留用于任何用途或用作文件 范围标识符。
- 所有以下划线和大写字母或其他字母开头的标识符 下划线总是保留用于任何用途。
否则就是法律程序,如:
int asm = 0;
会变得非法。
测试计划
#include <assert.h>
#include <stdint.h>
int main(void) {
uint32_t io = 0;
__asm__ volatile (
"movl %0, %%eax;"
"inc %%eax;"
"movl %%eax, %0;"
: "+m" (io)
:
: "%eax"
);
assert(io == 1);
}
在Ubuntu 17.10,GCC 7.2上测试。
答案 2 :(得分:3)
asm
是gcc扩展程序,因此您无法使用std=c99
或ansi
等标记
更多细节 https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions