用作计数器的整数值的意外输出
Unexpected output for integer values used as counter
在编写应该是一个非常简单的程序时(出自 K&R C 书),我得到了一些我不理解的输出。如果我马上 EOF
,nl_count
是正确的 0,但是 space_count
总是 32767(最大 int
范围的一半),并且 tab_count
是一个很大的值(通常很高或很低)。
当我将所有变量初始化为 0 时,程序运行正常。我在这里错过了什么?
10 int main(void)
11 {
12 int tab_count, space_count, nl_count;
13
14 //tab_count = space_count = nl_count = 0;
15
16 int c;
17 while( (c = getchar()) != EOF ){
18 if( c == '\t' )
19 tab_count++;
20 if( c == ' ' )
21 space_count++;
22 if( c == '\n' )
23 nl_count++;
24 }
25
26 printf("\n");
27 printf("TABS = %d\n", tab_count);
28 printf("SPACES = %d\n", space_count);
29 printf("NEWLINES = %d\n", nl_count);
30
31 return 0;
32 }
输入和输出:
这是另一个输入,它再次正确输出换行符 3,但制表符为垃圾,空格为 32767。
(space)(space)(space)\t\t\t\n\n\n
TABS = 441446448
SPACES = 32767
NEWLINES = 3
When I initialize all vars to 0, then the program works correctly. What am I missing here?
tab_count
、space_count
和nl_count;
是自动存储变量。如果您不将它们初始化为 0
,它们将具有 不确定的 值。从他们那里读取在技术上是 未定义的行为 (UB)。由于您在初始化它们之前增加了它们的值,因此您正在调用 UB。 UB的一种表现就是产生看似无意义的值。
无法抗拒
When I initialize all vars to 0, then the program works correctly.
What am I missing here?
您错过了必须将所有变量初始化为零的信息。
也许您真正缺少的是违反规则的 C 程序可能具有 undefined/unspecified 行为这一事实。这意味着它们可能看起来有效或部分有效,即使它们不正确。
只有外部变量和静态变量默认初始化为0。所有其他变量都有一个不确定的值,这就是为什么在使用它们之前必须将它们初始化为 0。
这里的问题是,当您定义自动局部变量时,它们不会隐式初始化为任何值。您必须 显式 初始化它们。否则,那些变量的内容就是垃圾和不确定的。
参考:C11
,章节 §6.7.9,初始化
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
接下来,如果没有 write(至少,初始化),如果您尝试 use(读取)该值,它会调用undefined behaviour.
参考:C11
,附件 §J.2
The value of an object with automatic storage duration is used while it is
indeterminate
然后,回答
When I initialize all vars to 0, then the program works correctly
当然可以,因为这样就没有 UB。
因此,在您的代码中,您必须更改
int tab_count, space_count, nl_count;
至
int tab_count = 0;
int space_count = 0;
int nl_count = 0;
在编写应该是一个非常简单的程序时(出自 K&R C 书),我得到了一些我不理解的输出。如果我马上 EOF
,nl_count
是正确的 0,但是 space_count
总是 32767(最大 int
范围的一半),并且 tab_count
是一个很大的值(通常很高或很低)。
当我将所有变量初始化为 0 时,程序运行正常。我在这里错过了什么?
10 int main(void)
11 {
12 int tab_count, space_count, nl_count;
13
14 //tab_count = space_count = nl_count = 0;
15
16 int c;
17 while( (c = getchar()) != EOF ){
18 if( c == '\t' )
19 tab_count++;
20 if( c == ' ' )
21 space_count++;
22 if( c == '\n' )
23 nl_count++;
24 }
25
26 printf("\n");
27 printf("TABS = %d\n", tab_count);
28 printf("SPACES = %d\n", space_count);
29 printf("NEWLINES = %d\n", nl_count);
30
31 return 0;
32 }
输入和输出:
这是另一个输入,它再次正确输出换行符 3,但制表符为垃圾,空格为 32767。
(space)(space)(space)\t\t\t\n\n\n
TABS = 441446448
SPACES = 32767
NEWLINES = 3
When I initialize all vars to 0, then the program works correctly. What am I missing here?
tab_count
、space_count
和nl_count;
是自动存储变量。如果您不将它们初始化为 0
,它们将具有 不确定的 值。从他们那里读取在技术上是 未定义的行为 (UB)。由于您在初始化它们之前增加了它们的值,因此您正在调用 UB。 UB的一种表现就是产生看似无意义的值。
无法抗拒
When I initialize all vars to 0, then the program works correctly. What am I missing here?
您错过了必须将所有变量初始化为零的信息。
也许您真正缺少的是违反规则的 C 程序可能具有 undefined/unspecified 行为这一事实。这意味着它们可能看起来有效或部分有效,即使它们不正确。
只有外部变量和静态变量默认初始化为0。所有其他变量都有一个不确定的值,这就是为什么在使用它们之前必须将它们初始化为 0。
这里的问题是,当您定义自动局部变量时,它们不会隐式初始化为任何值。您必须 显式 初始化它们。否则,那些变量的内容就是垃圾和不确定的。
参考:C11
,章节 §6.7.9,初始化
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
接下来,如果没有 write(至少,初始化),如果您尝试 use(读取)该值,它会调用undefined behaviour.
参考:C11
,附件 §J.2
The value of an object with automatic storage duration is used while it is indeterminate
然后,回答
When I initialize all vars to 0, then the program works correctly
当然可以,因为这样就没有 UB。
因此,在您的代码中,您必须更改
int tab_count, space_count, nl_count;
至
int tab_count = 0;
int space_count = 0;
int nl_count = 0;