为什么函数在赋值给变量时会被调用?
Why is a function called when it is assigned to a variable?
我一直在做 K&R 中的练习:C 编程语言并注意到一些让我有点困惑的事情。
#include <stdio.h>
#define BLANK ' '
int c;
int d;
d = 0;
c = getchar();
当我执行这段代码时,getchar() 被调用,即使它已分配给变量 'c',但从未调用过 'c'。我也只是将变量 'c' 更改为
c = printf("hi");
程序执行时打印“hi”。所以,这种行为是一致的,但对我来说仍然没有意义。
这对于许多命令式编程语言来说是相当标准的1 - 语句c = getchar();
意味着程序应该在那个时间点,调用 getchar()
(从标准输入读取一个字符,必要时等待),并将其 return 值存储到为名为 [=13= 的变量分配的某个存储位置].您稍后不使用 c
的事实是无关紧要的(请注意,我使用“使用”一词而不是像您那样使用“调用”一词;我们不调用变量)。
在 printf
的第二个示例中,您的函数具有非常明显的副作用(打印到控制台)。同样,在执行语句 c = printf(...)
时会出现副作用,而在稍后使用 c
时 而不是 。
您还会注意到,在以下代码片段中,getchar 仅被调用一次,无论您使用 c
的值是零次、一次、两次还是更多次:
int c;
c = getchar();
printf("%c", c);
printf("%c", c);
1 还有其他语言家族,您确实有变量引用尚未发生的计算。这样的事情经常出现在各种场景下的函数式语言中,但是C不属于那一类。
2 这个问题涉及两个有副作用的函数 and/or 是不纯的。如果您更深入地研究该语言并开始学习诸如并发编程或编译器设计之类的东西,您应该知道这些规则适用于 visible 效果,例如您观察到的副作用。如果函数仅根据其输入参数进行计算而没有外部影响(如控制台输入或读取共享内存位置)或副作用(如控制台输出或写入共享内存位置),那么会有更微妙的影响(例如编译器重新排序你看不到其影响的东西,以提高效率,同时仍然确保你可以看到的副作用遵循这里讨论的规则)
如果你有 c = &getchar
(但是 c
必须是 int (*)(void)
而不是 int
类型),它会像你描述的那样,因为那时您将在 c
中保存指向 getchar
的函数指针。之后您就可以 c()
了。
但是你这里有getchar()
,它已经是一个函数调用!因此函数在这一行被调用(使用运算符 ()
),结果存储在 c
.
中
我一直在做 K&R 中的练习:C 编程语言并注意到一些让我有点困惑的事情。
#include <stdio.h>
#define BLANK ' '
int c;
int d;
d = 0;
c = getchar();
当我执行这段代码时,getchar() 被调用,即使它已分配给变量 'c',但从未调用过 'c'。我也只是将变量 'c' 更改为
c = printf("hi");
程序执行时打印“hi”。所以,这种行为是一致的,但对我来说仍然没有意义。
这对于许多命令式编程语言来说是相当标准的1 - 语句c = getchar();
意味着程序应该在那个时间点,调用 getchar()
(从标准输入读取一个字符,必要时等待),并将其 return 值存储到为名为 [=13= 的变量分配的某个存储位置].您稍后不使用 c
的事实是无关紧要的(请注意,我使用“使用”一词而不是像您那样使用“调用”一词;我们不调用变量)。
在 printf
的第二个示例中,您的函数具有非常明显的副作用(打印到控制台)。同样,在执行语句 c = printf(...)
时会出现副作用,而在稍后使用 c
时 而不是 。
您还会注意到,在以下代码片段中,getchar 仅被调用一次,无论您使用 c
的值是零次、一次、两次还是更多次:
int c;
c = getchar();
printf("%c", c);
printf("%c", c);
1 还有其他语言家族,您确实有变量引用尚未发生的计算。这样的事情经常出现在各种场景下的函数式语言中,但是C不属于那一类。
2 这个问题涉及两个有副作用的函数 and/or 是不纯的。如果您更深入地研究该语言并开始学习诸如并发编程或编译器设计之类的东西,您应该知道这些规则适用于 visible 效果,例如您观察到的副作用。如果函数仅根据其输入参数进行计算而没有外部影响(如控制台输入或读取共享内存位置)或副作用(如控制台输出或写入共享内存位置),那么会有更微妙的影响(例如编译器重新排序你看不到其影响的东西,以提高效率,同时仍然确保你可以看到的副作用遵循这里讨论的规则)
如果你有 c = &getchar
(但是 c
必须是 int (*)(void)
而不是 int
类型),它会像你描述的那样,因为那时您将在 c
中保存指向 getchar
的函数指针。之后您就可以 c()
了。
但是你这里有getchar()
,它已经是一个函数调用!因此函数在这一行被调用(使用运算符 ()
),结果存储在 c
.