为什么我们不能在声明结构变量名时使用连字符?
Why can't we use of hyphen while declaring structure variable name?
构造生日{
整数 day:6;
}b-day;
在将 b-day
声明为结构时显示以下错误:
error: expected ':', ',', ';', '}' or '__attribute__' before '-' token|
但是从变量名中删除连字符后它起作用了,为什么?
连字符用作减法和取反运算符,因此不能在变量名中使用。 (变量是用于结构还是其他类型无关紧要。)
如果你有:
int a = 1;
int b = 2;
int a-b = 3;
printf("%d\n", a-b);
那么我们会不清楚是为 a
减去 b
打印“-1”还是为变量 a-b
.
打印“3”
因为 C 不允许使用连字符作为标识符名称。
基本上你只能使用字母、数字和下划线。
也不允许使用数字作为第一个字符。
引自N1570 6.4.2 标识符:
Syntax
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
identifier-nondigit:
nondigit
universal-character-name
other implementation-defined characters
nondigit: one of
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
digit: one of
0 1 2 3 4 5 6 7 8 9
这是因为标识符名称中不能使用符号'-'
。当它用在一系列符号之间时,编译器会根据上下文将其视为二元或一元减号运算符。
错误信息
error: expected ':', ',', ';', '}' or 'attribute' before '-' token|
意味着编译器试图解释声明至少像
struct birthday{
int day:6;
}b; -day;
你可以这样声明结构
struct birthday{
int day:6;
} b_day;
即使用下划线符号而不是连字符。
无聊的答案是语言定义不允许 -
成为标识符的一部分(变量名、函数名、typedef 名、枚举常量、标记名等)。
为什么会出现这种情况可能归结为以下几点:
在预处理阶段,您的源文本被分解为一系列 标记 - 标识符、标点符号、字符串文字和数字常量。除了分隔相同类型的标记外,空格并不重要。如果你写 a=b+c;
,编译器会看到标记序列 identifier (a
), punctuator (=
), 标识符 (b
), 标点符号 (+
), 标识符 (c
),以及 标点符号 (;
)。这是在它进行任何语法分析之前 - 它不查看该语句的含义或结构,它只是将其分解成它的组成部分。
它可以这样做是因为字符 =
和 +
以及 ;
可以 永远不会 成为标识符的一部分,所以它可以清楚地看到标识符开始和结束的位置1.
记号生成器是“贪婪的”,它将尽可能地构建最长的有效记号。在像
这样的声明中
int a;
你需要空格来告诉预处理器 int
和 a
是不同的标记,否则它会尝试将它们混合成一个标记 inta
。同样,在像 a=b- -c;
这样的语句中,您需要空格(或括号 a=b-(-c);
)来表示您要从 b
中减去 -c
,否则分词器将解释它a = b-- c
,这不是你想要的。
那么,如果 -
可以成为标识符的一部分,那么 x=a-b+c
应该如何标记化? a-b
是一个还是三个?你将如何编写你的分词器以便它可以跟踪它?您是否需要 -
前后的空格来表示它是一个运算符而不是变量的一部分?
当然可以定义一种允许 -
既是运算符又是标识符的一部分的语言(参见 COBOL),但它增加了编译标记化阶段的复杂性,而且它只是简单的 更容易不允许它。
- 巧合的是,这就是为什么在声明指针变量时
T *p;
和 T* p;
之间没有区别的原因 - *
永远不能成为标识符的一部分,因此不需要空格将类型与变量名分开。您可以将其写为 T*p;
甚至 T * p;
,它们将被完全相同地对待。
构造生日{ 整数 day:6; }b-day;
在将 b-day
声明为结构时显示以下错误:
error: expected ':', ',', ';', '}' or '__attribute__' before '-' token|
但是从变量名中删除连字符后它起作用了,为什么?
连字符用作减法和取反运算符,因此不能在变量名中使用。 (变量是用于结构还是其他类型无关紧要。)
如果你有:
int a = 1;
int b = 2;
int a-b = 3;
printf("%d\n", a-b);
那么我们会不清楚是为 a
减去 b
打印“-1”还是为变量 a-b
.
因为 C 不允许使用连字符作为标识符名称。
基本上你只能使用字母、数字和下划线。 也不允许使用数字作为第一个字符。
引自N1570 6.4.2 标识符:
Syntax
identifier: identifier-nondigit identifier identifier-nondigit identifier digit identifier-nondigit: nondigit universal-character-name other implementation-defined characters nondigit: one of _ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z digit: one of 0 1 2 3 4 5 6 7 8 9
这是因为标识符名称中不能使用符号'-'
。当它用在一系列符号之间时,编译器会根据上下文将其视为二元或一元减号运算符。
错误信息
error: expected ':', ',', ';', '}' or 'attribute' before '-' token|
意味着编译器试图解释声明至少像
struct birthday{
int day:6;
}b; -day;
你可以这样声明结构
struct birthday{
int day:6;
} b_day;
即使用下划线符号而不是连字符。
无聊的答案是语言定义不允许 -
成为标识符的一部分(变量名、函数名、typedef 名、枚举常量、标记名等)。
为什么会出现这种情况可能归结为以下几点:
在预处理阶段,您的源文本被分解为一系列 标记 - 标识符、标点符号、字符串文字和数字常量。除了分隔相同类型的标记外,空格并不重要。如果你写 a=b+c;
,编译器会看到标记序列 identifier (a
), punctuator (=
), 标识符 (b
), 标点符号 (+
), 标识符 (c
),以及 标点符号 (;
)。这是在它进行任何语法分析之前 - 它不查看该语句的含义或结构,它只是将其分解成它的组成部分。
它可以这样做是因为字符 =
和 +
以及 ;
可以 永远不会 成为标识符的一部分,所以它可以清楚地看到标识符开始和结束的位置1.
记号生成器是“贪婪的”,它将尽可能地构建最长的有效记号。在像
这样的声明中int a;
你需要空格来告诉预处理器 int
和 a
是不同的标记,否则它会尝试将它们混合成一个标记 inta
。同样,在像 a=b- -c;
这样的语句中,您需要空格(或括号 a=b-(-c);
)来表示您要从 b
中减去 -c
,否则分词器将解释它a = b-- c
,这不是你想要的。
那么,如果 -
可以成为标识符的一部分,那么 x=a-b+c
应该如何标记化? a-b
是一个还是三个?你将如何编写你的分词器以便它可以跟踪它?您是否需要 -
前后的空格来表示它是一个运算符而不是变量的一部分?
当然可以定义一种允许 -
既是运算符又是标识符的一部分的语言(参见 COBOL),但它增加了编译标记化阶段的复杂性,而且它只是简单的 更容易不允许它。
- 巧合的是,这就是为什么在声明指针变量时
T *p;
和T* p;
之间没有区别的原因 -*
永远不能成为标识符的一部分,因此不需要空格将类型与变量名分开。您可以将其写为T*p;
甚至T * p;
,它们将被完全相同地对待。