标题:【求助】形参与实参的传值和传址问题!
只看楼主
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
结帖率:90.24%
已结贴  问题点数:20 回复次数:8 
【求助】形参与实参的传值和传址问题!
#include<stdio.h>
#include<string.h>

int main()
{
    void print(char *p[],int n);
    void convert(char *p[],int n);
    char *p[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer design"};
    puts("________The Origin following is:________\n");
    print(p,5);
    convert(p,5);
    puts("________The Turned following is:________\n");
    print(p,5);
    return 0;
}

void print(char *p[],int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        puts(p[i]);
        putchar('\n');
    }
}

void convert(char *p[],int n)   //指向指针的数组。。。
{
    int i,j;
    char x[100];
    char *q;
    q=x;
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-1-i;j++)
        {
            if(strcmp(p[j],p[j+1])>0)
            {

                q=p[j];
                p[j]=p[j+1];
                p[j+1]=q;                          //我感觉此处相当于给形参数据回传给了实参。。。
            }
        }
    }
}

//为什么这个字符串排序的程序可以正确排序。我感觉这个函数是值传递而非地址传递~~  应该形参的排序应该无法影响形参才对。但是它确实起作用了,请解释一下哦!
搜索更多相关主题的帖子: 网店 return include convert following 
2015-04-07 20:47
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
得分:0 

既然还有不甘心
就还没到放弃的时候~
2015-04-07 20:52
longwu9t
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:732
专家分:2468
注 册:2014-10-9
得分:20 
char *p[] = {"Follow me", "BASIC", "Great Wall", "FORTRAN", "Computer design"};
这是个指针数组
每个元素都是个char* 指向一个字符串的首个字符的地址

void convert(char *p[],int n);
这个函数是对p这个指针数组所指向的字符串进行比较
冒泡排序后交换的是指向每个字符串的指针地址
改变的是指针数组中每个指针的排序
而不是改变了每个字符串常量的位置

这好比一条街道的入口处
门牌号排序变了
而房子的位置没变

如果不理解以上说明
可以尝试一下使用 char (*)s[N]这种定义来与 char *s[N}来比较
以增进了解

Only the Code Tells the Truth             K.I.S.S
2015-04-07 21:05
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
得分:0 
回复 3楼 longwu9t
thank you !

既然还有不甘心
就还没到放弃的时候~
2015-04-08 14:46
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
得分:0 
嗯,楼上解释得非常棒。我看了楼主原帖里的一些问句,想对楼主说:

认真地去调查形参还是实参的作风非常好,但请牢牢记住:形参、实参仅仅只在参数传递给函数时发生,等参数进入函数后,函数体里是没有形参、实参的说法的。

唉,感觉这里是哪个学校的专业课论坛吧?我误打误撞进来了

参数传递,在机器码来看,有二种方法(MOV 方法和 LEA方法):
1)mov ax, Value ,这个指令是让 Value 这个值放入 AX 寄存器,明显可以看到,这个动作只是把一个具体的值放入 AX,以后操作 AX,不会改变原先的值,只是 AX 在改变。当函数调用过程中,编译器如果把参数用这种方法放进函数,然后执行的话,是不会修改原先的变量的。这也是 C 的缺省方法。

2) lea ax, Value , 这个指令是让 Value 所在的地址放入 AX 寄存器,而不是 Value 这个值,这时候,后续对 Value 这个值的操作,在汇编里都要加个中括号,以取得存放地址里具体的值。

从上面可以看出,如果我们还是在使用汇编写代码的话,是无所谓形参还是实参的,我只要改变一下伪指令,就可以对同一个值,采取不同的访问策略。但我们使用 C 来写的时候,编译器人家已经写好,默认就是 mov,那么当需要实参传递的时候,我们无法改变编译器的默认行为,变通的做法,就是直接把地址当做变量传给函数,那么 C 还用默认方法(mov)处理参数的时候,就达到了我们用汇编写 lea 的目的了。

为了区分这二种不同目的的访问方法,人们专门分别给了名字,叫实参传递、形参传递。
2015-04-10 10:37
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
回复 5楼 AleTiff
参数传递好像不能这样讲吧。
在机器代码里,参数都是通过栈传递过去的,在call函数前会将函数需要的参数通过push指令压入栈中,如何使用这些数据取决于函数本身,比如函数使用这类指令:
mov si,bp+4
mov ax,[si]
inc ax  
mov [si],ax
这几条指令会把栈里第一个参数的数据加1(前4字节是主函数call指令的下一条指令的地址),改变的只是栈中数据,这可以理解为主函数是传值进来的;如果函数是使用这类指令:
mov si,[bp+4]
mov ax,[si]
inc ax
mov [si],ax
这几条指令会先将栈里第一个参数值送进si,以si作为间址寄存器给ax赋值,最后修改的是si指向的位置处的值,不是堆栈中的值(其实还是栈,只是可能是调用函数使用的栈段),这可以理解为当作传地址处理了。

能编个毛线衣吗?
2015-04-10 11:42
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
再就是形参和实参也不是这样讲的,你编写函数时使用的参数为形参,而调用函数使用的参数为实参。

能编个毛线衣吗?
2015-04-10 11:48
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
得分:0 
嗯,是的。

我上面写的是机器码操作,就是通常所说的直接手工用汇编写。

在高级语言里,编译器通常不会像手工写汇编那样,想写什么写什么,而是通过所谓的“调用约定”。

调用约定目前常见的有 cdecl、fastcall、stdcall、pascal 等几种,不同的约定,并不是都是压栈处理,通常,每种语言对于要传递的参数数量小于4个时,都会考虑利用寄存器,哪个寄存器传递哪个参数由各自语言设计者前置定义。但,当参数超过4个时,无一例外都是利用压栈传参。
2015-04-10 12:12
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
得分:0 
噢。我百度了一下。

原来教学界现在把形参和实参定义为你说的那样了。,好像现在小学都说 0 是自然数了一样。

嗯,好吧,尊重教学理论,作为名词解释来看吧。
2015-04-10 12:16



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-443672-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.228929 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved