提问人:corvelk 提问时间:1/28/2021 最后编辑:John Kugelmancorvelk 更新时间:1/28/2021 访问量:69
将一个常量无误地分配给另一个常量
A constant being assigned to another constant without errors
问:
我目前正在学习指针和按值传递的概念,我有这个 C 代码块:
void doSomething(int b){
b = 6;
printf("%d", b);
}
int a = 5;
int main(void){
doSomething(a);
printf("%d",a);
return 0;
}
我应该得到在编译和执行时都没有错误的输出。通过跟踪代码,以下是我的看法:65
- 整数被赋值 。
a
5
- 由于 C 是严格按值传递的,因此 .
doSomething(a) == doSomething(5)
现在在运行该行之前,我相当确定.因此,通过运行该行,程序可以有效地读取:b = 6;
b == 5
5 = 6;
一个常量(因为我缺乏更好的术语)被分配给另一个常量。在 Python 中,这会因语法错误而失败,并且出现错误是有道理的。为什么它不会引发语法错误?
答:
如果你在调试器中查看,你会看到这里有两个变量在起作用,一个是代码中的全局变量,另一个是函数的本地变量。a
b
doSomething()
这是两个完全独立的变量。调用该函数时,请想象发生以下情况:doSomething()
stack_push(a);
call(doSomething);
编译器内部的其中执行如下操作:doSomething()
int b = stack_pop();
...
这就是“副本”的制作方式。
请注意,这个用于考虑变量的模型是一个近似值,只要达到相同的结果,优化编译器可能会做一些完全不同的事情,就像 C 规范一样。
5 = 6;
不一样b = 6;
b = 6;
将值 6 分配给变量,具有自动存储,这是另一回事b
b
5 = 6;
不是一个有效的表达式,你误解了这个概念,认为两者都是一样的。
运行以下程序以查看错误:C
void doSomething(int b){
b = 6;
5 = 6;
printf("%d", b);
}
int a = 5;
int main(void){
doSomething(a);
printf("%d",a);
return 0;
}
现在,您将收到第 3 行的错误:
错误:需要左值作为赋值
5 = 6 的左操作数;
引用左值和右值
我决定把.它产生了类似于 Python 中的编译错误,Johnny Mopp 和 Martin James 的评论现在有意义了。5 = 6;
main()
b
确实是一个变量,而不是一个实际的常量。我的印象是,按值传递是只传递变量包含的内容,而忽略了变量的想法,认为函数只允许整数,而这只不过是一个占位符,与变量不同。b
b
我的印象是,正是 ,而不是分配值的变量。b
5
5
我目前在脑海中看到的是:
- 整数被赋值 。
a
5
- 由于 C 是严格按值传递的,因此 .
doSomething(a) == doSomething(5)
b
在调用 时分配了值。5
doSomething(5)
b
根据行分配值。6
b = 6;
- ...依此类推。
感谢大家的评论和回答!
以下是 C 2018 标准在 6.5.2.2 4 中执行函数调用的方式:
在准备调用函数时,将对参数进行计算,并为每个参数分配相应参数的值...
这意味着,在函数定义中,with 被定义为一个变量(技术上是一个对象),并且,当函数被 with 或 调用时,or 的值被赋值给 ,就好像你做了 or 一样。这只是一项任务;它不会在 和 或 之间建立任何持久的连接。void doSomething(int b)
b
doSomething(a)
doSomething(5)
a
5
b
b = a
b = 5
b
a
5
函数内部,是一个变量,所以你当然可以执行赋值。这只需分配给变量 。b
b = 6
6
b
以下是有关参数如何成为其自身变量的更多信息。3.16 将参数定义为:
...作为函数声明或定义的一部分声明的对象,该声明或定义在进入函数时获取值,...
6.9.1 9说:
每个参数都有自动存储持续时间;它的标识符是左值...
上一个:无法修改函数内的数组
评论
b
不是一个常数。它是一个变量。 完全没问题。b = 6;
doSomething()
void
int c = 5; c = 6;