В C, приведение указателя имеет накладные расходы? - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть некоторый код, который выглядит ужасно, и, думая про себя, мне никогда не придется ни видеть его, ни отлаживать его снова (он будет скрыт совершенно другим языком программирования), есть ли у него издержки на приведение таким образом?

void SubtractFloat (void *in, void *out){

    int* a = (int*)in;
    int* b = a++;

    float c = * (float*)a;
    float d = * (float*)b;

    float* e = (float*)out;

    *e = c - d;
}

(да, я понимаю невероятные нарушения кода, но необходимо перевести ответственность за тип вверх)

* в примечании, можно ли это сделать чище?(Я даже приму предложения ассемблера)

1 Ответ

0 голосов
/ 06 декабря 2018

В большинстве современных реализаций C преобразование указателя одного типа в указатель другого типа приводит к нулевым или незначительным затратам производительности.Более серьезной проблемой будет перемещение данных между регистрами общего назначения и регистрами с плавающей запятой.

Как вы заметили, код в вашем вопросе имеет нарушения строгих правил псевдонимов C, хотя ваша реализация C может его поддерживать.Тем не менее, есть две альтернативы:

Если обстоятельства in, out и ваша реализация C поддерживают доступ к содержимому как float, используйте:

float *fin = in, *fout = out;
fout[0] = fin[1] - fin[0];

Еслидоступ к данным как float не поддерживается, затем используйте:

char *p = in;
float c, d, e;
memcpy(&d, p, sizeof d);
memcpy(&c, p + sizeof d, sizeof c);
e = c - d;
memcpy(out, &e, sizeof e);

Обратите внимание, что хотя memcpy номинально хуже в абстрактной машине C (он копирует байты один за другим), хорошая реализация Cоптимизирует этот код.(Если выравнивание in и out не является проблемой, то для типичных процессоров хороший компилятор должен генерировать две нагрузки, вычитание и хранилище. Если выравнивание является соображением, некоторая форма невыровненных загрузок и хранилищможет понадобиться. Но они понадобятся в любом случае.)

...