为什么我不能交换两个变量的内存地址?

时间:2014-05-20 21:37:16

标签: c

我想交换两个变量的内存地址,如下所示:

#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标准中是否存在禁止两个变量名称指向同一地址的内容?

4 个答案:

答案 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之类的内容)。