Ускоряет ли создание итератора указатель на цикл C? - PullRequest
2 голосов
/ 05 сентября 2010

Я запустил следующее:

#include <stdio.h>
typedef unsigned short boolean;

#define false 0
#define true (!false)
int main()
{
    int STATUS = 0;
    int i = 0;
    boolean ret = true;
    for(i = 0; i < 99999; i++)
    {
        ret = ret && printf("Hello, World.");
    }
    if(!ret)
    {
        STATUS = -1;
    }

    return STATUS;
}

Это завершается буквально за секунду.Обычно 0,9 - 0,92.

Затем я изменил int i = 0; на int *i = 0;, и теперь у меня время выполнения меньше 0,2 секунды.Почему скорость меняется?

Ответы [ 5 ]

10 голосов
/ 05 сентября 2010

Время выполнения зависит от времени, необходимого для печати на консоль. i ++ в int * будет увеличивать указатель на размер указателя. Это будет 4 или 8 в зависимости от вашего компьютера и настроек компилятора. Основываясь на числах, которые вы сообщаете, предположительно это будет 4. Таким образом, printf выполняется только в четверть раза.

2 голосов
/ 05 сентября 2010

Ваш комментарий к ответу nos подтвердил мое подозрение: это арифметика указателя.Когда вы увеличиваете указатель int с помощью ++, он не просто добавляет единицу к числу, но на самом деле увеличивается на размер целого числа, которое обычно составляет 4 (байта).Так что i++ фактически добавляет 4 к числовому значению i.

Точно так же, если вы используете += для указателя, например i += 5, он не просто добавит 5 (или что-то еще) к числовому значению i, оно будет увеличиваться на i на размер этого целого числа, поэтому в этом случае 5 * 4 = 20 байт.

Причина этого заключается в том, что если выу вас есть часть памяти, которую вы рассматриваете как массив,

int array[100]; // for example

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

int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }

и вы выиграли 'вам придется переписать цикл, если вы используете тип данных другого размера.

2 голосов
/ 05 сентября 2010

Как правило, печать на консоль будет на несколько порядков больше, чем любое усиление с микрооптимизацией, которое вы могли бы сделать с таким циклом.

Вы действительно уверены, что ваша вторая версия печатает привет мир также 99999 раз?

Когда вы делаете for(int *i = 0; i++ ; i < 99999 ), вы проверяете, если значение указателя (адрес) меньше 99999, что обычно не имеет большого смысла.Увеличение указателя означает, что вы повышаете его до указателя на следующий элемент, и, поскольку у вас есть int *, вы будете увеличивать указатель на sizeof (int) байтов.

Вы просто повторяете 99999 / sizeof(int) раз.

1 голос
/ 05 сентября 2010

Причина в том, что приращение действует по-разному для указателей.

На входах i++ увеличивается i на 1.

Для указателей i++ увеличивается на размер указываемого объекта, который будет 4 или 8 в зависимости от вашей архитектуры.

Таким образом, ваш цикл выполняется только для 1/4 или 1/8 числа итераций, когда i является указателем, тогда как i является целым.

1 голос
/ 05 сентября 2010

Правильный способ сделать этот тест с указателем будет что-то вроде:

int i;
int *i_ptr = &i; 

for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
    ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...