对不起,可能我没表达清楚,我想问,数组作为参数传入子函数为什么不是作为形式参数传入,请你看程序运行结果,如果数组作为形式参数传入子函数,那么形式参数的值并不会影响原来main函数中的值,但是实际上,main函数中数组原来的值已经被修改了,这是因为数组传入的是地址(指针),我的问题就在这里,传入的是指针为什么不是用完就扔的形式参数。
这与c语言的设计有关是吗?内部有什么机制吗?
对不起,可能我没表达清楚,我想问,数组作为参数传入子函数为什么不是作为形式参数传入,请你看程序运行结果,如果数组作为形式参数传入子函数,那么形式参数的值并不会影响原来main函数中的值,但是实际上,main函数中数组原来的值已经被修改了,这是因为数组传入的是地址(指针),我的问题就在这里,传入的是指针为什么不是用完就扔的形式参数。
这与c语言的设计有关是吗?内部有什么机制吗?
首先提一下std C 调用约定,参数的传递使用栈。
在传递时首先将参数按照反序压栈,比如你有四个int参数 arg1 arg2 arg3 arg4,那么他们会按照4 - 1的顺序入栈。
接着将返回地址(当前pc值)入栈,然后将当前的辅助栈指针(ebp)入栈,接着设置辅助栈指针为当前栈指针 ebp = esp。
接着在子例程的内部使用ebp作为基准寻址参数。
接下来按照编译器的设计会先为局部变量流出空间或者将会用到的寄存器入栈。
然后子例程的栈架构就建立了。这是寻址参数可以使用 ebp
栈的结构如下:
栈历史 (地址高位)
arg4
arg3
arg2
arg1
pc
ebp
eax
ebx
ecx
...
为局部变量保存的空间
... (esp)(内存低地址)
寻址第一个变量就是在位置 ebp + 4 的位置上(arg1), 同理 arg2 --> ebp + 8, arg3 --> ebp + 12, arg4 --> ebp +16
再回来说数组为什么不采用按值传递的问题。如果一个数组采用按值传递,将会在栈上为这个数组分配大量的空间,而栈空间是非常宝贵且有限的。
但是按引用传递就没有这个问题。不论数组有多长,都只需要传递一个地址。栈空间内只需要保留一个地址的空间(4或8字节)即可。
特别是在单栈结构的处理器上,系统栈和进程栈使用同一个栈指针,按值传递将会很快耗尽栈空间,导致系统崩溃。
在双栈设计的处理器上这个问题会好一些,但是也会导致当前进程崩溃。
对于一些安全性较差的系统,栈的溢出可能导致补课预料的读写了其他进程的空间,甚至是系统区。将会导致不可预知的后果。