首页 > 解决方案 > 根据 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?换句话说:

4)(int **)符号是什么意思?

5)程序有什么问题,如何修复它,以便在作为参数值传递给函数后获取地址px并交换?pyswap

例 2 问:

5) 关于符号,我是否理解正确,一旦我们声明该变量ip是一个指向int, via的指针int *ip,我们就不能将例如十进制值分配给ip,稍后,使用如下赋值:ip = 10;因为,之后该变量已被声明为指针,它仅用于ip以十六进制保存“指向”的其他变量的地址?

标签: clinuxpointersgdbmemory-address

解决方案


您的swap函数正在交换 and 的值,xy不是 and 的pxpy

因为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 的值pxpy则必须将其写为

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

推荐阅读