我想交换两个变量的内存地址,如下所示:
#include<stdlib.h>
#include<stdio.h>
void main() {
int a = 5;
int b = 10;
int temp;
temp = &a;
&a = &b;
&b = temp;
}
但是编译器不允许它。有什么理由不允许这样做吗?
我知道变量只是代表内存位置的名称。当您访问一个变量时,您只是访问一个内存位置,为什么不能只将这些名称换成内存位置?在C#中你可以用这种方式交换对象名,那你为什么不能用C做呢?
C标准中是否存在禁止两个变量名称指向同一地址的内容?
答案 0 :(得分:4)
在C中,您可以使用指针执行此操作:
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
int *temp;
*a = 5;
*b = 10;
temp = a;
a = b;
b = temp;
这类似于在C#中执行相同操作时实际发生的情况,除了C#没有像C那样公开指针语法。
答案 1 :(得分:2)
在C语言中,名称在翻译时消失。 (在典型的C实现中,名称仅在运行时保留用于符号调试等功能,或者可能是共享库的动态链接。)
名称不是程序可以操作的运行时实体。即使您在运行时以某种方式访问符号表(通过某些编译器或库扩展),这样您不仅可以访问b
之类的符号,还可以更改条目以使其具有不同的值,这样的更改不会传播回已编译的程序,其中b
不再存在,因为它已被机器语言指令所取代,这些指令以数字方式而非符号方式访问该存储器位置。 C程序中的符号更改通常需要重新编译程序源代码。
最后,您的程序根本不是有效的C,因为在表达式中:
temp = &a;
作业的左侧temp
的类型为int
,而&a
的类型为int *
。您将指针值分配给整数。
您尝试用来表示名称操作的语法根本不表示名称操作;它表示别的东西:将指针转换为整数。
如果没有强制转换操作符,则该转换需要诊断。使用强制转换运算符,它会生成一个实现定义的整数值。
编程语言不像人类语言;机器对你的真实含义毫无直觉。您的程序不会被拒绝,理由是机器理解您的真实含义,而是根据语言的真实规则对您的意图进行完全不同的解释。
换句话说,您的程序并未显示C在运行时不支持符号操作,因为您的程序不以任何方式编码对此类事物的请求。
什么表明C在运行时不支持符号操作,这是ISO C标准中缺少这种特征的任何描述。这意味着如果存在这样的特征,它只能作为编译器理解的特定C语言的本地扩展。在这种情况下,您可以在编译器的手册中找到它,并且该文档将向您显示正确的语法。
答案 2 :(得分:1)
代码:
&a = &b;
尝试更改变量a的地址。这在C中根本不允许。同样适用于:
&b = temp;
相反,要交换值,请执行以下操作:
temp=a;
a=b;
b=temp;
另一种方法是将a和b声明为指针。然后你可以交换每个点的位置:
int a = 5;
int b = 10;
int *ap = &a;
int *bp = &b;
int *temp;
temp = ap;
ap = bp;
bp = temp;
printf("*ap[%d]\n", *ap); // output: '*ap[10]'
printf("*bp[%d]\n", *bp); // output: '*bp[5]'
答案 3 :(得分:1)
您可能希望阅读最新C language standard的第6.2.4节。
请注意,您可以将多个指针解析为同一地址:
int a;
int *p = &a;
int *q = &a;
int *r = p;
在这种情况下,表达式 a
,*p
,*q
和*r
都会解析到相同的内存位置,因此< / p>
a = 1;
与
具有相同的效果*p = 1;
与
具有相同的效果*q = 1;
与
具有相同的效果*r = 1;
您无法更新&a
的结果,因为该操作是无意义的(它等同于编写1 = 2
之类的内容)。