Я пытаюсь понять некоторый код, который использует арифметику указателей так, как я не привык. В одном месте кода я сталкиваюсь с этим:
complex<double> **P, *p_row, result=complex<double>(0,0);
P=new complex<double>*[n];
for(i=0;i<n;i++) P[i]=new complex<double>[n];
for(i=0,p_row=*P;i<n;i++,p_row+=n) result+=log(*(p_row+i));
Если P — матрица, это выглядит как добавление логарифмов диагональных элементов P. Но оказывается, что последняя строка выше не эквивалентно
for(i=0;i<n;i++) result+=log(P[i][i]);
Я искал объяснение того, что здесь происходит, но я не могу его найти. Кроме того, рассматриваемый код, очевидно, дает правильный результат в конце (это часть Монте-Карло). Есть идеи?
Код, который вы опубликовали, неверен; это вызывает неопределенное поведение.
Например. во второй итерации, p_row
является (*P)+n
, *P
указывает на массив размера n
следовательно, когда код читает *(p_row+i)
, он читает за концом массива.
Кажется, в последней строке предполагается, что матрица хранится в одном непрерывном массиве (например, основной ряд). Однако это означает P
будет complex<double>*
инициализируется P = new complex<double>[n*n];
,
Цикл с p_row+=n
демонстрирует неопределенное поведение, поскольку предполагает, что выделения, выполняемые циклом в третьей строке, являются смежными, но почти во всех реализациях это не так.
Ваш код с P[i][i]
получает правильный результат. Вы можете исправить другой код, выделив n*n
элементы в одном кадре, а затем разложить их в p
в петле.