微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一个常量被分配给另一个没有错误的常量

如何解决一个常量被分配给另一个没有错误的常量

我目前正在学习指针和值传递的概念,我有这个 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 赋给变量 bb 具有自动存储,这是另一回事

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;
}

现在你会得到第三行的错误:

错误:左值需要作为赋值的左操作数
5 = 6;

参考lvalues and rvalues

,

我决定将 5 = 6; 放在 main() 中。它产生了一个类似于 Python 中的编译错误,Johnny Mopp 和 Martin James 的评论现在有意义了。

b 确实是一个变量而不是实际的常量。我的印象是传值是只传递变量所包含的内容,并且完全不考虑 b 是一个变量的想法,认为该函数只允许整数,而 {{1} } 只不过是一个占位符,不同于变量。

我的印象是 b完全 b,而不是变量分配5

我目前在脑海中看到的是:

  • 整数 5 被赋值为 a
  • 由于 C 是严格按值传递的,因此 5
  • doSomething(a) == doSomething(5) 在调用 b 时被赋予值 5
  • doSomething(5) 按照行 b 分配了值 6
  • ...等等等等。

感谢大家的评论和回答!

,

C 2018 标准在 6.5.2.2 4 中说明了如何执行函数调用:

在准备调用函数时,会评估参数,并为每个参数分配相应参数的值……

这意味着,在带有 void doSomething(int b) 的函数定义中,b 本身被定义为一个变量(技术上是一个对象),并且当函数使用 {{ 1}} 或 doSomething(a)doSomething(5)a 的值被分配给 5,就像您执行了 bb = a。这只是一项任务;它不会在 b = 5ba 之间建立任何持久的联系。

在函数内部,5是一个变量,所以当然可以执行赋值b。这只是将 b = 6 分配给变量 6

这里有更多关于参数如何成为它们自己的变量。 3.16 定义参数为:

…作为函数声明或定义的一部分声明的对象,在函数入口处获取值,…

6.9.1 9 说:

每个参数都有自动存储时长;它的标识符是一个左值……

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。