c - 根据 K&R,我正在努力可视化指向变量的指针
问题描述
无法弄清楚 C 编译器显示的特定变量的地址与实际底层硬件之间的依赖关系。
考虑示例 1,在使用 编译此代码cc t2.c
并执行它之后,它看起来,它没有按预期工作,并且无论出于何种原因,地址px
和地址py
都没有互换。
示例 1:
#include <stdio.h>
void swap(int *,int *);
int main(){
int x=3;
int y=2;
int *px;
int *py;
px=&x;
py=&y;
printf("px = %x\npy = %x\n",&px,&py);
swap(px,py);
printf("After the swap\npx = %x\npy = %x\n",&px,&py);
}
void swap(int *px,int *py){
int temp;
temp=*px;
*px=*py;
*py=temp;
}
示例 1 的 gdb:
6 int x=3;
(gdb) n
7 int y=2;
(gdb) n
10 px=&x;
(gdb) p x
$1 = 3
(gdb) p &x
$2 = (int *) 0x7efff5cc
(gdb) p px
$3 = (int *) 0x0
(gdb) p &px
$4 = (int **) 0x7efff5d4
(gdb) n
11 py=&y;
(gdb) p px
$5 = (int *) 0x7efff5cc
(gdb) p &px
$6 = (int **) 0x7efff5d4
……
pi@readonly:~/new$ cc t2.c
pi@readonly:~/new$ a.out
px = 7ea765fc
py = 7ea765f8
After the swap
px = 7ea765fc
py = 7ea765f8
示例 2:
int x = 1, y = 2 ;int *ip; /* ip is a pointer to an int */
ip = &x; /* ip now points to x */
y = *ip; /* y is now 1 */
*ip = 10; /* x is now 10 */
*ip = *ip + 1; /* x is now 11 */
*ip += 1; /* x is now 12 */
++*ip; /* x is now 13 */
(*ip)++; /* x is now 14, parentheses are required */
前 1 问:
1) 我是否理解正确,从$5
, px
- 开始,与 完全相同的变量x
,只是它的值设置为0x7efff5cc
十六进制,这只是x
内存中变量的地址?
2)如果我们使用int *ip
声明,是否意味着该变量ip
的值等于地址int
?那么,int
十六进制的 , 的地址是什么?
3)变量的地址是什么意思,这是什么0x7efff5cc
?换句话说:
我知道,CPU、ROM 有 RAM、L2、L3、L1 缓存。那么,这个数字代表哪个特定内存的地址?
有多少这样
0x7efff5cc
可以容纳那些特定类型的内存?或者,我在哪里可以在 Linux 系统上查看它?
4)(int **)
符号是什么意思?
5)程序有什么问题,如何修复它,以便在作为参数值传递给函数后获取地址px
并交换?py
swap
例 2 问:
5) 关于符号,我是否理解正确,一旦我们声明该变量ip
是一个指向int
, via的指针int *ip
,我们就不能将例如十进制值分配给ip
,稍后,使用如下赋值:ip = 10;
因为,之后该变量已被声明为指针,它仅用于ip
以十六进制保存“指向”的其他变量的地址?
解决方案
您的swap
函数正在交换 and 的值,x
而y
不是 and 的px
值py
。
因为px == &x
,这意味着*px == x
,同样适用于py
。
对于将新值写入参数的函数,您必须将指针传递给参数:
void foo( T *ptr )
{
*ptr = new_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
T var; // for any non-array type T
foo( &var ); // write a new value to var
...
}
这适用于任何非数组类型T
,包括指针类型。让我们T
用指针类型替换P *
,所以现在的代码
void foo( P **ptr )
{
*ptr = new_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new value to var
...
}
语义完全一样,只是类型改变了。如果我们想写入一个非数组对象,我们传递一个指向该对象的指针。如果我们想写入一个指针对象,我们将一个指针传递给该指针对象。
因此,如果您希望函数交换 and 的值px
,py
则必须将其写为
void swap( int **ppx, int **ppy )
{
int *tmp = *ppx; // int * = int *
*ppx = *ppy; // int * = int *
*ppy = tmp; // int * = int *
}
并称为
px = &x;
py = &y;
swap( &px, &py );
推荐阅读
- mysql - 是否可以以自上而下的格式组合 MySQL 中的列?
- asp.net-core - 将 NSwag 与 .NET 5 一起使用时如何显示完整的招摇界面?
- node.js - Forge 内部发生未处理的拒绝:错误:在 devDependencies 中找不到任何电子包
- node.js - Aws Image rekognition that Detecting inappropriate images with node js
- java - 如何在 Java 中对构建器模式中的诱惑步骤进行分组?
- python - 如何使用 Python 在不同文件夹中移动相同数量的文件
- safari - Flutter Web -Wakelock 在 iOS Safari 上不起作用
- python - 从打开函数访问文件而不调用它
- javascript - react 如何知道这个组件将被卸载?
- excel - 访问 Excel TextToColumns 的 Word 宏