0

当我编译一个 C 文件时,其内容如下:

#include <stdio.h>
#define FILE_NAME "text\ 1"

int main()
{
    FILE* file_ptr = fopen(FILE_NAME, "w");
    fclose(file_ptr);

    return 0;
}

得到警告:

tt.c: In function ‘main’:
tt.c:6:37: warning: unknown escape sequence: '\040'
    6 |     FILE* file_ptr = fopen(FILE_NAME, "w");
      | 

我知道它是由\ 我的 C 语言代码字符串引起的,并且是SPACE 的 ASCII40十进制。为什么警告不是?32'\040''\x20'

并且似乎也在 bash\ 转移到\040种子到二进制文件(不确定)。

有规定强制吗?


更新:删除 '\32' 用于将 SPACE 的 ASCII 表示为十进制。


我如何遇到这个问题?

我只是想知道 Bash 如何处理 ESCAPED SPACE,我想 bash 将其转为 SPACE,但是在我检查了 Bash 的源代码之后(对我来说很难)。我发现 Bash 可能将\ 其视为普通字符串,如下面的不涉及源代码\

#define slashify_in_quotes "\\`$\"\n"
#define slashify_in_here_document "\\`$"

#define shell_meta_chars   "()<>;&|"
#define shell_break_chars  "()<>;&| \t\n"

#define shell_quote_chars   "\"`'"

所以我认为 Bash 转为\ 命令或二进制文件来处理,所以我在上面写了一个简单的 C 文件来检查 C 是如何处理的\


所以我的问题是为什么'\040'没有gcc 警告'\x20'

对于 Bash 的处理方式\ 仍然需要我检查......

4

1 回答 1

2

回答更新的问题

为什么警告是 '\040' 而不是 '\x20'?

这只是编译器实现者的选择。当你\在一个字符串或字符常量后面跟着不是一个可识别的转义序列时,编译器会警告你。例如,如果您有\g,编译器会警告您\g无法识别。当后面的字符\可能不清楚时,因为它是无法与其他字符区分开来的空白字符(如制表符的空格)或不是可打印字符,编译器会在错误消息中按值显示。这可以帮助您在文本编辑器中找到确切的字符,以防某些不可打印的字符滑入源代码。编译器作者本可以使用十六进制,但只是选择使用八进制。

我会指责他们使用不一致的风格。在 GCC 10.2 中,\g结果为 message unknown escape sequence: '\g',但\ 结果为 message unknown escape sequence: '\040'。这些应该是:

  • unknown escape sequence: 'g'unknown escape sequence: '\040'
  • unknown escape sequence: '\g'unknown escape sequence: '\\040'

回答原始模糊问题

C 2018 6.4.4.4 C 源代码中的特定字符常量,第 1 段列出了escape-sequence 的四种选择:simple-escape-sequenceoctal-escape-sequencehexdecimal-escape-sequenceunivesal-char-name

八进制转义序列后跟\一到三个八进制数字。因此,\040代码为 040 8 = 32\32的字符,是代码为 32 8 = 26 的字符。

没有十进制转义序列;\32是八进制转义序列,而不是十进制。(另请注意,由于八进制转义序列可以有各种长度,如果希望在其后跟一个八进制数字,则必须使用所有三个允许的数字。\324将被解析为一个字符,而不是后跟\324而后跟。)\0324\0324

十六进制转义序列后跟\x任何正整数的十六进制数字。\x20等于\040

简单转义序列\'\"\?\\\a\b\f\n\r\t或之一\v通用字符名称后跟\u四个十六进制数字或\U八个十六进制数字。)

于 2020-11-27T13:04:19.367 回答