Почему этот вызов функции работает, хотя я инвертировал два параметра? - PullRequest
4 голосов
/ 22 февраля 2012

Я работаю над вариантом алгоритма Нелдера-Мида из Числовые рецепты , который позволил бы пользователю указать максимальное количество вызовов целевой функции, которое будет сделано.

Из моей основной процедуры, вот как я вызываю функцию amoeba(), которая реализует алгоритм Nelder-Mead:

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 d файл заголовка, который определяет сигнатуру подпрограммы amoeba(), и компиляция основной подпрограммы не дала ошибок. Однако исходный файл amoeaba() не содержал этого заголовка (моя ошибка), поэтому компилятор также не генерировал никаких ошибок.

Так почему же моя связанная программа по-прежнему функционирует так, как и должна, даже если аргументы указаны не в правильном порядке?

UPDATE

@ Binyamin Sharet, я показываю здесь сборку прямо перед звонком на amoeba и в amoeba. Поддерживает ли это вашу гипотезу?

imageamoeba">

imageamoeba">

ОБНОВЛЕНИЕ 2

@ Биньямин Шарет уверен, вот оно:

enter image description here

1 Ответ

6 голосов
/ 22 февраля 2012

Причина, вероятно, в том, что параметры с плавающей запятой передаются не в стек, а в стек сопроцессора, поэтому порядок этих двух значений не имеет значения.

Например, функция ожидает следующий порядок аргументов:

   |         p              |                             |
   |         y              |                             |
   |         ndim           |                             |
   |         nmax           |                             |
   |         funk           |                             |
   |         nfunk          |          ftol               |
   +------------------------+-----------------------------+
   |        stack           |        coprocessor stack    |

Неважно, если вы переключите nmax и ftol, потому что порядок стеков будет одинаковым, и когда amoeba попытается их прочитать, он не запутается для того же причина.


Редактировать

Чтение разборки показывает, что я был немного выключен, но из-за SSE инструкция для передачи переменной с плавающей запятой - movss, которую вы можете увидеть в оба списка сборок, которые вы добавили, один раз в xmm0 регистр (в вызывающем) и один раз из xmm0 (в вызываемом). так что вы можете заменить слова стек сопроцессора на xmm регистров и это ваша ситуация.

...