Сочетание разыменования и декремента в C - PullRequest
0 голосов
/ 29 января 2011

Мне нужно как можно более эффективное средство для перемещения содержимого массива. Мне нужно сдвинуть содержимое каждого местоположения массива по одному вправо и игнорировать первое, чтобы я мог написать новое значение там.

Вот что у меня есть:

#define LENGTH 5

int myArray[LENGTH] = {1, 2, 3, 4, 5};

int *pa = myArray + (LENGTH - 1);

for (ushort i = 5; i > 0; i--) {
    *pa = *(pa - 1);
    pa--;
}

Я хотел бы объединить две строки цикла for в одну операцию. Что-то вроде:

*pa = *(pa--);

Однако результат этого не определен. Я застрял с тем, что я уже использую?

РЕДАКТИРОВАТЬ: я должен был уточнить, что это не фактический код, который я использую, просто быстрый пример, чтобы продемонстрировать конструкцию, которую я был после.

Ответы [ 5 ]

6 голосов
/ 29 января 2011

Если вам действительно нужно это сделать, memmove, вероятно, будет вашим лучшим выбором.

Однако, если это вообще возможно, лучше избегать его полностью.Вместо того, чтобы сдвигать текущее содержимое, чтобы освободить место для нового элемента, просто держите указатель на «самое старое» место в массиве.Когда вам нужно добавить новый элемент, сделайте что-то вроде *new_pos++ = new_item;.

Когда вам понадобится прочитать ваши данные, вы начнете с new_pos+1 и прочитаете следующие 5 элементов, но каждый разпри увеличении вы будете делать % LENGTH, поэтому, когда вы достигнете конца массива, он «обернется» к началу.

5 голосов
/ 29 января 2011

Эффективность не измеряется количеством строк, поэтому вы ничего не получите, если попытаетесь «сжать» код таким способом.

Если вы отбросите последний элемент, то я предлагаюиспользуйте круговой буфер вместо массива, чтобы вам вообще не понадобился этот сдвиг.Цена доступа к элементам немного возрастет, но при ДЛИНЕ, равной степени 2, она будет очень мала.

0 голосов
/ 29 января 2011

Вероятно, что хороший оптимизатор может позаботиться о смещении элементов в массиве целых чисел.Но вы уверены, что вам действительно нужно беспокоиться о инструкциях ассемблера?Был ли профиль и обнаружена проблема?

Если это узкое место, возможно, есть что-то, что вы можете изменить в алгоритме ... например, зачем вам нужно это переключение?если буфер имеет фиксированный размер, то почему бы не использовать его в качестве кольцевого буфера?

0 голосов
/ 29 января 2011
*pa = *(pa--);

Однако результат этого не определен. Я застрял с тем, что я уже использую?

Да. Также не позволяйте этому беспокоить вас. Ваш компилятор умен. Он найдет эффективный способ сделать это независимо от того, будет ли это в одной или двух строках.

Если вы хотите сделать что-то еще, возможно, более оптимизированное, используйте memmove вместо цикла

memmove(&myArray[1],&myArray[0],(sizeof myArray - 1)*sizeof *myArray);
0 голосов
/ 29 января 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...