我正在研究 Numerical Recipes 中的Nelder-Mead算法的变体,它允许用户指定要进行的最大目标函数调用次数。
从我的主程序,这里是我如何调用实现Nelder-Mead算法的amoeba()
函数:
amoeba(p,y,params->ndim,params->tol,params->nmax,internal_funk,&nfunc);
但这是如何实施的:
void amoeba(float **p, float y[], int ndim, unsigned nmax, float ftol, float (*funk)(float []), int *nfunk) {
....
}
请注意,我在函数调用中反转了nmax
和ftol
个参数。
令人惊讶的是,amoeba()
仍有效。在调试器中单步执行此操作可确认已将正确的值分配给nmax
和ftol
。
我的主例程#include
是一个头文件,它定义了amoeba()
例程的签名,并且编译主例程没有产生任何错误。但是,amoeaba()
源文件不包含该标题(我的错误),因此编译器也没有生成任何错误。
那么为什么我的链接程序仍然可以正常运行,即使参数没有以正确的顺序给出?
更新
@Binyamin Sharet,我在调用amoeba
之前和amoeba
之前就在这里展示了大会。它是否支持您的假设?
更新2
@Binyamin Sharet肯定,这是:
答案 0 :(得分:6)
原因可能是,因为浮点参数不是在堆栈上传递,而是在协处理器堆栈上传递,所以这两者的顺序无关紧要。
例如,函数需要这个参数顺序:
| p | |
| y | |
| ndim | |
| nmax | |
| funk | |
| nfunk | ftol |
+------------------------+-----------------------------+
| stack | coprocessor stack |
如果你切换nmax
和ftol
并不重要,因为堆栈上的顺序是相同的,当amoeba
尝试读取它们时,它没有'因同样的原因而感到困惑。
修改强>
读取反汇编显示我有点偏离,但由于SSE,用于传递float变量的指令是movss
,您可以在添加的assemblt列表中看到,一次到xmm0
注册(在调用者中),一次来自xmm0
(在被调用者中)。所以你可以用 xmm register 替换 coprocessor-stack 这个词,这就是你的情况。