我一直搞不清楚关于c语言关于函数调用和栈的两类题,快要考试,我很紧张,希望大家帮帮我,有点复杂,

有点复杂,但程序很简单的,谢谢了
一、关于函数调用
有以下程序
# include <stdio.h>
void exch( int t )
{ t[0] = t[5]; }
main( )
{ int x[10] = {1,2,3,4,6,7,8,9,10},i=0;

while ( i<=4 ) { exch( &x[i]); i++; }
for (i=0; i<5; i++) printf("%d ",x[i]);
printf( "\n" ); }
程序运行后的输出结果是 A)2 4 6 8 10 B)1 3 5 7 9 C)1 2 3 4 5 D)6 7 8 9 10

答案选D 可是我不明白,这里没有返回值,形参值又不能传递给实参,那为什么结果会改变?
下面这道却对输出值没影响

void fun(int *a,int *b)
{
int *c;
c=a;a=b;b=c;
}
main()
{
int x=3,y=5,*p=&x,*q=&y;
fun(p,q); printf("%d,%d,",*p,*q);
fun(&x,&y); prin"%d,%d\n",*p,*q);
}

二、关于栈
设栈的存储空间为S(1 : 40),初始状态为bottom=0,top=0。现经过一系列入栈与出栈运算后,top=20,则当前栈中有多少个元素?
答案是20个,我不明白为啥不是21?40-20+1=21,不是吗

就像下面这道题:假设一个长度为50的数组(数组元素的下标从0到49)作为栈的存储空间,栈底指针bottom指向栈底元素,栈顶指针top指向栈顶元素,如果bottom=49,top=30(数组下标),则栈中具有多少个元素。
答案是:49-30+1=20

第一个问题是抄错了,
应该是void exch( int* t ){ t[0] = t[5]; }吧

指针的用法:

*p : 指针值所代表的地址里的值,和 p[0]的意思一样。
p[i] :把指针当数组用,因为数组名其实就是指针;
p[i]=*(p+i);
while ( i<=4 ) { exch( &x[i]); i++; }
和while ( i<=4 ) { exch( x+i); i++; }
是一个意思,其实就是for(i=0;i<5;i++)x[i]=x[i+5];

void fun(int *a,int *b)
{
int *c;
c=a;a=b;b=c;
这里交换了两个指针的值,可是这两个指针也是局部参数,
C语言值传递,只改变了,堆栈中复制的指针的值,相应地址中的值丝毫没有改变
}
2)

问题:
问题(1)设栈的存储空间为S(1 : 40),初始状态为bottom=0,top=0。现经过一系列入栈与出栈运算后,top=20,则当前栈中有多少个元素?
答案是20个,我不明白为啥不是21?40-20+1=21,不是吗

问题(2)就像下面这道题:假设一个长度为50的数组(数组元素的下标从0到49)作为栈的存储空间,栈底指针bottom指向栈底元素,栈顶指针top指向栈顶元素,如果bottom=49,top=30(数组下标),则栈中具有多少个元素。
答案是:49-30+1=20

解答:
堆栈是有生长方向的,正常的堆栈向下生长,指针逐渐减小;
但是,也可能会反向生长,这样的话,指针逐渐增大。

问题(1)的堆栈,是反常堆栈,堆栈向上生长,指针逐渐增大,所以元素个数n=top - bottom=top;
top =40 栈满 ----->| ---------- 40 -----------------| 第40个元素
| |
压入第n个数据 ----->|-----------top=20-------------| 第20个元素

↑ | ------ 。。。。。 。 -----| ↑
↑ |------ 。。。。。。 ----- | 第2个元素
压入第1个数据 top ------> | ---------First= 1 ---------- | 第1个元素
开始top= bottom =0 top ------->| -------- bottom =0 ------ | top指向栈底元素的位置-1
压栈出栈算法
push(x) {S[++ top]=x;}
pop() { --top;}

问题(2)的堆栈, 是正常堆栈,堆栈向下生长,指针逐渐减小;
所以元素个数n=bottom - top;
开始top,bottom指向栈底元素 ----->|-----------bottom=49-------------| 第1个元素
压入第1个数据 top ------>| ------ 。。。。。。。。-----| 第2个元素

↓ |------ 。。。。。。。。----- | ↓
↓ | ------------------------------------ | 第n个元素
压入第n个数据 top -------->| ---------top=49-n ------------ |

top=-1是栈满
top=bottom=49 时栈空 n=bottom-top

压栈出栈算法
push(x) {S[ top--]=x;}
pop() { top++;}

top=30时 n=49-30 =19 个元素。
那个 “答案是:49-30+1=20”,是错误的!
温馨提示:内容为网友见解,仅供参考
第1个回答  2013-02-21
首先,第一个问题是一个错误,你抄错功能,两种方法的地址传递和按值传递的参数传递,传递的值不会改变参数的值,并通过该地址可能会改变,传递的地址是真实的参数传递给形式参数的内存地址,引用和指针两种方式
(<=){EXCH(&X [I]);我+ +;}

这里&X [I],参考符号(&),拥有的元素的地址传递给函数,所以操作的功能会改变值的数组。

无效EXCH(T)
{T [0] = T [5];}
诠释* T;
这样类型相匹配。
第二个问题:
无效的乐趣(*,诠释* B)
{
诠释* C;
C = A,A = B,B = C;
}

虽然你的地址传递,但仍然遵循的原则,函数的参数,始终是一个复制的说法,你的地址传递,它会复制地址,即A = P,B = Q,注意参数P,Q,不会改变,或p =&XQ = &y;

在这种情况下,在有趣的(), b的地址互换,A = Q = Y,B = P =&X,但要注意参数p,q,或者没有改变的,上面说的A,B,就像P,Q,复制,他们改变,P,Q,当然并没有改变,输出为3,5;
例如
诠释x = 3,y = 5;
,INT * p =&X * Q = &y;
假设现在的p = 0x10时,Q = 0×14;

的乐趣(P,Q);无效的乐趣(诠释*,诠释* B) BR /> {
诠释* C; / / = P = 0X10; B = Q = 0x14的;
.....互换
= 0x14的;
B =为0x10;
函数结束。
但是现在,B代表地址交换,P,Q,或P = 0X10 =&X,Q = 0×14 = &y;

}
了解,A,B的值确实已经改变,但不影响的p,q表示;
没有改变,因为该地址所指向的P,Q,和在地址中的值没有改变,或3,5的;
如果你想改变,因此
无效(*,诠释* B)
{
诠释; / /虽然A,B,或部分地址复制P,Q,不改变

C = * A / /但A,B点的地址值互换,即内容为0x10和0x14的互换
* = * b ;/ /即使p = 0X10,但现在为0x10单元的内存值是5,而不是3。 。 。 * B = C;

}
参考,不说和指针效果。

栈,你看这部分的数据结构里面的内容,了解实现的堆栈,然后就可以了解它是如何工作的,而不是通过死记硬背。 。检查,但是,也可以返回计算式中的元素的数量。 。 。 。追问

谢谢你,栈的问题我明白了,只是第一题我还是不太懂,还请您再给我讲讲好吗

void fun(int *a,int *b)
{
int *c;
c=a;a=b;b=c;
}
main()
{
int x=3,y=5,*p=&x,*q=&y;
fun(p,q); printf("%d,%d,",*p,*q);
fun(&x,&y); prin"%d,%d\n",*p,*q);
}
这个程序调用的p,q,&x,&y,不都代表了地址吗,为什么还是对输出没影响?
上面那个exch的程序之所以有效,不就是因为调用的是地址吗

本回答被网友采纳
第2个回答  2013-02-22
首先,第一个问题是错误的,你抄错通过两种方法来解决,并通过值参数传递,传递的值不会改变参数的值,并可能更改地址,送货地址是真正的参数传递给形式参数的内存地址,引用和指针两种方式
(<=){EXCH(&X [I]); i + +;}
此处&X [Ⅰ]中,参考符号(&)的元素的地址传递给函数,这样的操作的功能将改变值的数组。

无效EXCH(T)
{T [0] = T [5];}
* T;
这种类型的比赛。
第二个问题:
无效的乐趣(*,诠释* B)
{
解释* C;
C = A,A = B,B = C; BR />}

虽然通过你的地址,但仍然遵循的原则,函数的参数是副本的声明,把你的地址,将复制的地址,即时,A = P,B = Q时,注意参数P,Q,也不会改变,或p =&XQ = &y;

有趣的(),b从地址在这种情况下,在互换,A = Q = Y,B = P =&X,但要注意的参数p,q,或者没有改变的,上面说的A,B,P,Q,复制像,他们的变化,P ,Q,当然,不改变输出到3,5;
例如,
诠释x = 3,y = 5;
INT * P = E&XIT * Q = &y;现在
假设P = 0X10当Q = 0×14;无效的乐趣(*解释* B)BR /> {
诠释乐趣

/>(P,Q); * C / / = P = 0X10; B = Q = 0x14的;
.....互换
= 0x14的;
B =为0x10;
函数年底。
但是现在,代表的B类地址交换,P,Q,或P = 0X10 =&X,Q = 14 = &y;

}
了解A,B的值,它已经改变,但不影响P,Q;
没有改变,因为该地址指向P,Q,在不改变地址值,或3,5
如果你想改变,所以
无效(*,诠释* B)
{
解释; / /复制P,Q,A,B,或部分

C = A / / A,B点的地址值的交换,0x10和0x14的互换
* = * B ;/ / P = 0X10和0x10单元存储器地址不会改变值是5,而不是3。 。 。 * B = C;

}
参考,不说和指针的效果。

堆栈,你看这部分的数据结构里面了解实现栈,那么你就可以了解它是如何工作的,而不是通过死记硬背的内容。 。检查,但它也可以在计算公式中的元素数返回。 。 。 。
第3个回答  2013-02-21
首先 第一个题有错误,是不是你抄错了,函数传参有 两种方式,传地址和传值, 传值不会改变参数的值,而传地址可能会改变,传地址就是把实参的内存地址传给形参, 有引用和指针两种方法,
while ( i<=4 ) { exch( &x[i]); i++; }

这里 &x[i], 引用符号&,已经吧元素的地址传给函数了, 所以函数的操作会改变数组的值。因此
void exch( int t )
{ t[0] = t[5]; }
应该是 int *t;
这样才能把类型 匹配。

第二题:
void fun(int *a,int *b)
{
int *c;
c=a;a=b;b=c;
}

虽然你传的是地址, 但是,还是遵循函数形参的原则,即总是拷贝一份实参, 你传地址,它同样也会拷贝一份地址, 即 a=p, b=q; ,注意实参 p ,q,未改变,还是 p=&x ,q=&y;
此时 ,在fun()中把 a ,b 的地址互换,a= q=&y, b=p=&x ,但注意,此时 实参 p,q,还是未改变,上面说了 a,b,只是p,q,的拷贝,他们怎么变, p ,q,没变当然输出的还是 3,5;
举个例子吧
int x=3 , y=5;
int * p=&x, *q=&y;
假设 现在 p=0x10; q=0x14;
那么 fun(p,q);
void fun(int *a,int *b)
{
int *c; //a = p =0x10; b=q=0x14;
.....互换
a =0x14;
b= 0x10;
函数结束。
但是现在 a,b代表的地址互换了,但是 p,q,呢,还是 p=0x10=&x,q=0x14=&y;

}
明白了吧,a,.b的值确实变了,但是不影响 p,q;
因为 p,q 所指向的地址没变, 而地址中的数值也没变,还是3,5,;
如果想要改变,可以这样
void (int *a, int *b)
{
int c; //虽然现在 a,b还是一份地址拷贝 p,q,不会改变
c = *a; //但是 吧 a,b所指向的地址中的值互换了,即 0x10 和 0x14中的内容互换了,
*a = *b;//即使 p = 0x10 ,但现在 内存中0x10单元的值 为5 了,而不是3。。。
*b =c;

}
引用就不说了,和指针效果一样。

栈的问题你还是看看数据结构里面的 这部分内容, 明白了栈的实现方式,那么就能理解它是怎样工作的 ,不要死记硬背。。不过为了考试,也可以背一下计算 元素个数的公式。。。。
第4个回答  2013-03-04
void fun(int *a,int *b)
{
int *c;
c=a;a=b;b=c;
}
main()
{
int x=3,y=5,*p=&x,*q=&y;
fun(p,q); printf("%d,%d,",*p,*q);
fun(&x,&y); prin"%d,%d\n",*p,*q);
}

其他的你好像都知道了,就说说这个吧

在这个题中,传递的参数是指针,其实指针本身就是一个变量,当你传递指针进去之后,这个指针就是形参,函数结束后并不会影响指针的指向,明白了么
相似回答