首页 > 解决方案 > asm关键字作为C中的标识符名称?

问题描述

我见过一个使用asm关键字作为变量名的项目,并且代码可以使用提供的Makefileon编译得很好Linux

int
main(int ac, char *av[])
{
    struct TMap *tm;
    FILE *inf, *hf;
    char *f, *sep;
    int c, asm; // <---

    asm = Defasm;
    // ...
}

这是整个Makefile

BIN = qbe

V = @
OBJDIR = obj

SRC      = main.c util.c parse.c cfg.c mem.c ssa.c alias.c load.c copy.c \
           fold.c live.c spill.c rega.c gas.c
AMD64SRC = amd64/targ.c amd64/sysv.c amd64/isel.c amd64/emit.c
ARM64SRC = arm64/targ.c arm64/abi.c arm64/isel.c arm64/emit.c
SRCALL   = $(SRC) $(AMD64SRC) $(ARM64SRC)

AMD64OBJ = $(AMD64SRC:%.c=$(OBJDIR)/%.o)
ARM64OBJ = $(ARM64SRC:%.c=$(OBJDIR)/%.o)
OBJ      = $(SRC:%.c=$(OBJDIR)/%.o) $(AMD64OBJ) $(ARM64OBJ)

CFLAGS += -Wall -Wextra -std=c99 -g -pedantic

$(OBJDIR)/$(BIN): $(OBJ) $(OBJDIR)/timestamp
    @test -z "$(V)" || echo "ld $@"
    $(V)$(CC) $(LDFLAGS) $(OBJ) -o $@

$(OBJDIR)/%.o: %.c $(OBJDIR)/timestamp
    @test -z "$(V)" || echo "cc $<"
    $(V)$(CC) $(CFLAGS) -c $< -o $@

$(OBJDIR)/timestamp:
    @mkdir -p $(OBJDIR)
    @mkdir -p $(OBJDIR)/amd64
    @mkdir -p $(OBJDIR)/arm64
    @touch $@

$(OBJ): all.h ops.h
$(AMD64OBJ): amd64/all.h
$(ARM64OBJ): arm64/all.h
obj/main.o: config.h

config.h:
    @case `uname` in                               \
    *Darwin*)                                      \
        echo "#define Defasm Gasmacho";        \
        echo "#define Deftgt T_amd64_sysv";    \
        ;;                                     \
    *)                                             \
        echo "#define Defasm Gaself";          \
        case `uname -m` in                     \
        *aarch64*)                             \
            echo "$define Deftgt T_arm64"; \
            ;;                             \
        *)                                     \
            echo "#define Deftgt T_amd64_sysv";\
            ;;                             \
        esac                                   \
        ;;                                     \
    esac > $@

install: $(OBJDIR)/$(BIN)
    mkdir -p "$(DESTDIR)/$(PREFIX)/bin/"
    cp $< "$(DESTDIR)/$(PREFIX)/bin/"

uninstall:
    rm -f "$(DESTDIR)/$(PREFIX)/bin/$(BIN)"

clean:
    rm -fr $(OBJDIR)

clean-gen: clean
    rm -f config.h

check: $(OBJDIR)/$(BIN)
    tools/test.sh all

check-arm64: $(OBJDIR)/$(BIN)
    TARGET=arm64 tools/test.sh all

src:
    @echo $(SRCALL)

80:
    @for F in $(SRCALL);                       \
    do                                         \
        awk "{                             \
            gsub(/\\t/, \"        \"); \
            if (length(\$$0) > $@)     \
                printf(\"$$F:%d: %s\\n\", NR, \$$0); \
        }" < $$F;                          \
    done

.PHONY: clean clean-gen check check-arm64 src 80 install uninstall

我想知道如何实现编译器将允许asm作为变量名(忽略这样做是不好的风格的事实)。我尝试将 移植Makefile到 aCMakeLists.txt但由于asm. 如何在不更改代码的情况下解决此问题?我已经强制使用C99标准Makefile并使用相同的C编译器标志,但这没有帮助:

cmake_minimum_required(VERSION 3.10.2)
project(qbe C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-Wall -Wextra -std=c99 -g -pedantic")

include_directories(amd64)

add_executable(qbe
        amd64/all.h
        amd64/emit.c
        amd64/isel.c
        amd64/sysv.c
        amd64/targ.c
        alias.c
        all.h
        cfg.c
        copy.c
        fold.c
        gas.c
        live.c
        load.c
        main.c
        mem.c
        ops.h
        parse.c
        rega.c
        spill.c
        ssa.c
        util.c)

CMake由于IDE支持,我想使用。

标签: cassemblymakefilecmakekeyword

解决方案


asm不是标准 C 的关键字,也不是保留标识符,尽管标准将其识别为公共扩展。该标准还指出

包含可能导致严格符合的程序无效的任何扩展都会导致实现不符合。此类扩展的示例包括新关键字、标准头文件中声明的额外库函数或名称不以下划线开头的预定义宏。

这在附录 J中,它是非规范性的,但它只是总结了一个可以从规范性文本中得出的结论。因此,符合标准的实现不会基于它asm用作标识符而拒绝代码。

例如,我发现 GCC 在使用它支持的任何严格一致性模式( or或)asm时接受使用作为标识符,但默认情况下会因错误或专门启用 GNU 扩展(例如 with )而拒绝它。如果您使用的是不同的编译器,那么您将需要查阅其文档以了解如何获得与该领域标准的一致性,如果确实可以这样做的话。-std=c89-std=c99-std=c11-std=gnu11

附录

至于您的 CMake 尝试失败的原因,该CMAKE_C_STANDARD属性并没有像您认为的那样做。它告诉 CMake 尽可能选择提供 C 标准指定版本的功能的编译器选项,但它不要求严格遵守该标准。文档特别假设它会导致-std=gnu11在某些情况下使用该选项,并且该选项或类似的包容性选项会产生与您想要的相反的效果。


推荐阅读