为啥 &a 在 main() 和其他方法中显示不同的值?
Posted
技术标签:
【中文标题】为啥 &a 在 main() 和其他方法中显示不同的值?【英文标题】:Why &a shows different values in main() and other methods?为什么 &a 在 main() 和其他方法中显示不同的值? 【发布时间】:2022-01-17 05:52:30 【问题描述】:void f(int a[]);
int main()
int a[11];
printf("1.%x ", &a);
f(a);
void f(int a[])
printf("2.%x ", &a);
输出:
1.e0de4940 2.e0de4928
但是当 & 被删除时输出将是相同的。 以及为什么不管数组大小相差12?
【问题讨论】:
您了解副本的概念吗? IE。看起来一样,但在其他地方有什么不同吗? 您正在尝试了解该语言的内部工作原理,这在很大程度上取决于您所使用的编译器和平台。基本上,你不应该担心这些事情,因为它们并不重要。无论如何,总有一天你会理解它们。 ;-) C 是按值调用。您正在将指针的副本传递给您的数组,因此您正在打印副本的位置。a
in f
是指向a
的指针的副本(即分配在不同的内存中),因此当您执行&a
时,您会看到不同的值。跨度>
如果您尝试在启用警告并将其视为错误的情况下编译此程序,您将看到此代码产生 2 个错误并拒绝编译。所以总是以这种方式编译你的程序,这会为你指明正确的方向,或者至少提供了一个提示。
【参考方案1】:
主要是printf
的调用
int a[11];
printf("1.%x ",&a);
需要使用转换说明符%p
的地方输出数组a
的地址。
在函数f
内调用printf
输出函数的局部变量(参数)a
的地址
printf("2.%x ", &a);
由于int *
类型的数组和参数a
占用的内存范围不同,所以它们的地址不同。
注意参数a
获取main
中声明的数组a
的第一个元素的地址。所以参数a
中存储的地址与main
中数组a
的地址相同。那是你可以写的
void f(int a[]);
int main()
int a[11];
printf("1.%p ", ( void * )&a);
f(a);
void f(int a[])
printf("2.%p ", ( void * )a);
结果你会得到相同的输出。
您可以简化代码,以便于理解底层内容。
考虑下面的代码sn-p
int a[11];
int *p = a;
如您所见,两个变量 a 和 p 占用不同的内存范围。所以这些 printf 调用会产生不同的结果
printf( "%p\n", &a );
printf( "%p\n", &p );
【讨论】:
【参考方案2】:在main
中,a
是一个数组,&a
是存储该数组的地址。当main
调用f
时,f(a)
中的a
会自动转换为a
的第一个元素的地址,并将该地址传递给f
。
在f
中,a
是参数,&a
是存储该参数的地址。参数a
的值设置为函数调用中传入的值,但&a
是参数的地址,是值的副本。不是main
中原来的a
。
【讨论】:
【参考方案3】:int a[]
在语法上与int* a
相同,它们都是指向整数(也称为 int 数组)的指针。因此正确的方法是没有&
void f(int a[])
printf("2.%x ", a);
int main()
int a[11];
printf("1.%x ",a);
f(a);
但是当 & 被删除时输出将是相同的。以及为什么不管数组大小相差12?
最初,您有&
,它首先打印int a[11]
的地址。
然后将该数组的地址传递给f()
,在那里它生成一个不同的指针,该指针也指向相同的地址。但是,这是两个不同的指针,因此当您打印实际指针的地址时,无论它们指向何处,它们显然都是不同的。
12
(实际上是24
,因为数字是十六进制)的区别是任意的,它只是告诉您这两个指针存储在彼此相距24
字节的地址中
【讨论】:
【参考方案4】:在您的程序中,函数f(int a[])
中只有一个小错误
void f(int a[])
printf("2.%x ", &a);
函数f
返回函数参数的地址,而不是它指向的地址。
由于掌握 C 中的指针是理解 C 语言的基本方面之一,因此不仅 C 语言本身,但机器架构和 CPU/内存功能的基础知识。
因此,在指针算术和搜索/调试中出错甚至可以驱动 经验丰富的 C 程序员为之疯狂,毫不奇怪,他们在 C++ 中被利用 static_cast、dynamic_cast 关键字,并在随后的计算机语言中完全删除(隐藏,即..)。
所以,我更进一步,重新编写了您的代码,更好地解释了该错误。
#include <stdio.h>
void f(int b[])
printf("\n func call. print address: %x", &b);
void f2(int b[])
printf("\n func call. print address(2): %x", b);
int main()
int *j, a[11];
j = a; // load address of 'a' array to int pointer 'j'
// pointer 'j'
// j = address of an array 'a'
// &j = address of 'j' !!
*j = 1; // value of any 'int' that 'j'
// points to is 1,so the value
// of a[0]= 1
// ______ print values of 'j', 'a' ______
// value is from address 'a'
printf("\n1.) value of number (j)= %d", *j);
// int value of address 'a'
printf("\n1.) value of number (a)= %d", a[0]);
// ______ print addresses of 'j', 'a' ______
// address of int variable 'j' that
// holds pointer to 'a'
printf("\n\n2.) addr of number (j)= %x", &j);
// address of 'a' array
printf("\n2.) addr of number (a)= %x", &a);
// ______ all of following adressess are the same ______
// actual pointer (points to 'a' now)
printf("\n\n3.) addr of 'j' = %x", j);
// address od an array 'a'
printf("\n3.) addr of 'a' = %x", a);
// address of first int member in array a
printf("\n3.) addr of 'a[0]'= %x\n", &a[0]);
// ______ print them from function ______ (yours) ..
f(&j); f(a); // outputs an address of an argument passed to a function !!!
// ______ print them from function ______ (changed) ..
f2(&j); f2(a); // outputs an address that an argument points to !!
// (holds address of)
return 0;
函数f
和f2
中的int b[]
是有意 而不是int a[]
,因此很明显,参数是压入堆栈的变量的副本 - 不是实际变量 a
.
程序输出:
1.) value of number (j)= 1
1.) value of number (a)= 1
2.) addr of number (j)= 5f826328
2.) addr of number (a)= 5f826330
3.) addr of 'j' = 5f826330
3.) addr of 'a' = 5f826330
3.) addr of 'a[0]'= 5f826330
func call. print address: 5f826308
func call. print address: 5f826308
func call. print address(2): 5f826328
func call. print address(2): 5f826330
【讨论】:
【参考方案5】:原因是 main()
和 f()
将本地参数 a
放在内存中的不同位置,因为在某些时候,main()
和 f()
都在它们的执行中间,并且作为这两个参数都是它们各自定义的函数的局部变量,它们确实是不同的变量(尽管它们的名称相同)
【讨论】:
【参考方案6】:当您编写int a[]
时,您指的是指针,因为数组是指针。
要引用a
指向的位置,您只需写a
。当你写&a
时,你指的是指针本身的内存地址。指针本身的内存地址是不同的,因为您是按值传递指针(内存地址本身),这意味着它们在每个函数中都有一个副本。
【讨论】:
"数组是指针" - 数组是数组,但是数组的名称可以衰减为指针。见1、2。以上是关于为啥 &a 在 main() 和其他方法中显示不同的值?的主要内容,如果未能解决你的问题,请参考以下文章