鱼C论坛

 找回密码
 立即注册
查看: 2141|回复: 13

鱼油们帮个忙,这个我想了很长时间,总是想不通。

[复制链接]
发表于 2014-6-2 10:06:05 | 显示全部楼层 |阅读模式
20鱼币
本帖最后由 风之残月 于 2014-11-10 10:24 编辑

鱼油们帮个忙,这个我想了很长时间,总是想不通。
2014-6-2 10:03


#include <stdio.h>

void reserve(int *x, int n);   /*形参x为指针变量*/

void main()
{
      int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};

      printf("The original array:\n");

      for( i=0; i < 10; i++)
      {
            printf("%d ", a[i]);
      }
      printf("\n");

      reserve(a, 10);

      printf("The array has benn inverted:\n");

      for( i=0; i < 10; i++)
      {
            printf("%d ", a);
      }
      printf("\n");
}

void reserve(int *x, int n)   /*形参x为指针变量*/
{
      int *p, temp, *i, *j, m;

      m = (n-1)/2;
      i = x;         //i指向数组的第一个元素
      j = x-1+n;     //j指向的是数组的最后一个元素
      p = x+m;       //指向中间,配对……

      for( ; i <= p; i++, j--)
      {
            temp = *i;
            *i = *j;
            *j = temp;
      }
}
先看一下这个程序,它是正确的,其目的是将数组中的数字进行前后对换,但是我想不通,为什么,将数组的第一个,最后一个,中间一个分别将他们的地址给了指针i、j、p然后进行交换,可是你们换就换呗,跟原来的数组已经没有关联了,因为它的地址已经传递给那些指针了呀,怎么运行过后,将原数组的地址都改变了呀。
[/i]

最佳答案

查看完整内容

reserve(a, 10); //传参时,这里是把a的地址复制给形参x,人家复制的是地址,而不是把整个a数组重新复制一篇给x,所以指针a与指针x指向的地址相同,即指向同一块内存。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 10:06:06 | 显示全部楼层
reserve(a, 10);  //传参时,这里是把a的地址复制给形参x,人家复制的是地址,而不是把整个a数组重新复制一篇给x,所以指针a与指针x指向的地址相同,即指向同一块内存。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 11:14:28 | 显示全部楼层
这个函数void reserve(int *x, int n) 执行之后并不会修改数组的地址。
如果你还是有怀疑,你可以把函数执行前后的数组(或者把每个元素)的地址打印出来,如printf("a: %p\n",&a[0]);

还有:打印数组元素
for( i=0; i < 10; i++)
{
      printf("%d ", a[i]);  // 是上传出错,还是你本来就是printf("%d ", a);  这打印的是数组a的地址

}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 12:17:53 | 显示全部楼层

那个是上传错了,不过我想问的的是,你也说了原数组内部相应的数字地址没变,那为什么,经过函数void reserve(int *x, int n) 后,    reserve(a, 10);

      printf("The array has benn inverted:\n");

      for( i=0; i < 10; i++)
      {
            printf("%d ", a【i】);
      }
      printf("\n");
}这个程序就能将原来数调换,还是原来的数组呀,相应地址也没变呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 14:40:16 | 显示全部楼层
逆流杀 发表于 2014-6-2 12:17
那个是上传错了,不过我想问的的是,你也说了原数组内部相应的数字地址没变,那为什么,经过函数void res ...

void reserve(int *x, int n)   /*形参x为指针变量*/
{
      int *p, temp, *i, *j, m;  // 这些是函数里面的局部变量,函数执行完就不存在了

      m = (n-1)/2;
      i = x;           //i指向数组的第一个元素,x也指向数组第一个元素,
                        //此时他们指向的元素是相同,但是后面就不一定了
      j = x-1+n;     //j指向的是数组的最后一个元素
      p = x+m;       //指向中间,配对……

      for( ; i <= p; i++, j--) // i++,i初始化的时候指向数组第一个元素,
                                     // i++执行后,就执行数组的下一个元素了,
                                     // 但是x没有++,所以x还是指向第一个数组元素
      {
            temp = *i;  // 这三个语句,进行交换操作,但是他们交换的是i指向的元素的值,而不是地址
            *i = *j;
            *j = temp;
// 为什么是定义i指向第一个元素,j指向最后一个,p指向中间元素。
// 这是因为位置的对换次数跟数组元素个数的特殊关系决定的。对换次数=元素个数的一半
// 因此本函数也可修改为:不使用p作为循环判断的条件,而是用m进行判断
// for(int nLoop=0; nLoop<m; nLoop++)
//{
//     temp = *(i+nLoop);
//     *(i+nLoop)+ =*(j+nLoop);
//     *(j+nLoop) = temp;
//}
      }
}

评分

参与人数 1鱼币 +5 贡献 +3 收起 理由
逆流杀 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 14:44:52 | 显示全部楼层
在 reserve 函数里,通过 指针 x 获取原数组基址,即可索引到整个数组元素。
取出 数组头尾中的元素地址后,用 * 操作符获取地址的数据,temp为这些数据的缓冲区,
reserve 改变的是 地址的数据,原数组的地址还是一直不变。

评分

参与人数 1鱼币 +5 贡献 +2 收起 理由
逆流杀 + 5 + 2 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 15:35:20 | 显示全部楼层
本帖最后由 santaclaus 于 2014-6-2 15:41 编辑

数组的地址没变,当然每个元素的地址就没变。但是元素的值变了。逆序过来了,为什么?
就这是指针发挥威力了。从void reserve(int *x, int n)这个函数声明看,传的是数组的地址进去,相当于数组亲自跑进reserve这个函数里面了。
    int *p, temp, *i, *j, m;
     m = (n-1)/2;
      i = x;         //注意,i是个指针,指向首元素
      j = x-1+n;    //j是个指针,指向最后一个元素
      p = x+m;       //p也是指针,指向中间元素

      for( ; i <= p; i++, j--)
      {
            temp = *i;   //取出i指针指向的元素。
            *i = *j;   //右值*j表示取j指针指向的元素,左值*i表示把前述元素的值放到i指向的内存空间里去。从而交换了i与j指向的元素。
            *j = temp; //同理左值*j表示把temp的值放到j指向的内存。
      }

综上:右值*i 和左值*i表示的含义可这样理解:
         右值*i:eg.   int a=*i,表示是取i指针指向的内存空间里面的值,赋给a变量。
         左值*i:eg.  *i=10是指把10放进i指针指向的那片空间。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 15:44:05 | 显示全部楼层
HHR 发表于 2014-6-2 14:44
在 reserve 函数里,通过 指针 x 获取原数组基址,即可索引到整个数组元素。
取出 数组头尾中的元素地址后 ...

我的意思是这样的,打个比方A当中有许多数据【相当于题中的数组a】,然后B将啊所有的东西都复制/(传递)下来的(什么地址呀,数据,)接着B经过一个程序将里面的数据对换了一下【相当于这里的reserve程序,B相当于这里的i,j,p,他们只不过是分别传递过来数组a的地址,数据,而已】,最后计算机重新输出A的值,此时数组A的值就变了,这是什么原因,从头到尾,变得是B呀,跟A没关系呀,他只是将本身的数值,地址给了别人而已,我就郁闷在这。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 15:45:59 | 显示全部楼层
苹果沃珂 发表于 2014-6-2 14:40
void reserve(int *x, int n)   /*形参x为指针变量*/
{
      int *p, temp, *i, *j, m;  // 这些是函数 ...

首先表示感谢,你写了这么详细,但我不是想讨论这个。
我的意思是这样的,打个比方A当中有许多数据【相当于题中的数组a】,然后B将啊所有的东西都复制/(传递)下来的(什么地址呀,数据,)接着B经过一个程序将里面的数据对换了一下【相当于这里的reserve程序,B相当于这里的i,j,p,他们只不过是分别传递过来数组a的地址,数据,而已】,最后计算机重新输出A的值,此时数组A的值就变了,这是什么原因,从头到尾,变得是B呀,跟A没关系呀,他只是将本身的数值,地址给了别人而已,我就郁闷在这
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-2 15:52:25 | 显示全部楼层
本帖最后由 santaclaus 于 2014-6-2 15:57 编辑

都说了,传过去的是数组的地址,就是相当于操作数组本身了,比如a数组存于的内存地址0x0000 0001开始的几个单元。你传指针进去,到了reserve函数里,就是复制了这个地址一遍给你所谓的b(注意:这里复制的是地址给b,而不是复制整个数组),也是b指向的还是0x0000 0001开始的这块内存,a与b指向的都是同一块内存,所以你操作b也就等于动了a。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 16:07:49 | 显示全部楼层
santaclaus 发表于 2014-6-2 15:52
都说了,传过去的是数组的地址,就是相当于操作数组本身了,比如a数组存于的内存地址0x0000 0001开始的几个 ...

额好像懂了,它们都指向那个栈,然后reserve把栈中的东西变了,导致后来指向该栈的数组数据变了;
谢了啊,不过我没评分的权利了,全给前面两位了,抱歉了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 16:09:35 | 显示全部楼层
santaclaus 发表于 2014-6-2 16:03
reserve(a, 10);  //传参时,这里是把a的地址复制给形参x,人家复制的是地址,而不是把整个a数组重新复制一 ...

是我理解的不深,你讲的对,高手,谢谢了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-2 16:14:32 | 显示全部楼层
santaclaus 发表于 2014-6-2 15:35
数组的地址没变,当然每个元素的地址就没变。但是元素的值变了。逆序过来了,为什么?
就这是指针发挥威力 ...

刚才没看到这上面,难怪你讲“都说了”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-6-22 15:37:25 | 显示全部楼层

#include <stdio.h>

void reserve(int *x, int n);   /*形参x为指针变量*/

void main()
{
      int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};

      printf("The original array:\n");

      for( i=0; i < 10; i++)
      {
            printf("%d ", a[i]);
      }
      printf("\n");

      reserve(a, 10);

      printf("The array has benn inverted:\n");

      for( i=0; i < 10; i++)
      {
            printf("%d ", a[i]);
      }
      printf("\n");
}

void reserve(int *x, int n)   /*形参x为指针变量*/
{
      int *p, temp, *i, *j, m;

      m = (n-1)/2;
      i = x;         //i指向数组的第一个元素
      j = x-1+n;     //j指向的是数组的最后一个元素
      p = x+m;       //指向中间,配对……

      for( ; i <= p; i++, j--)
      {
            temp = *i;
            *i = *j;
            *j = temp;
      }
}


楼主 ,我只改了你两个地方就实现了你那个首先按顺序输出数组,调用函数后,逆序输出,

你看看

      for( i=0; i < 10; i++)
      {
            printf("%d ", a[i]);
      }

      for( i=0; i < 10; i++)
      {
            printf("%d ", a[i]);
      }

看看你原来写的

      for( i=0; i < 10; i++)
      {
            printf("%d ", a);
      }

      for( i=0; i < 10; i++)
      {
            printf("%d ", a);
      }
看出哪里不一样了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-28 04:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表