Ваши две альтернативные программы не аналогичны.Во втором, который действителен, вы выделяете пространство, достаточное для хранения N
целых чисел, а затем присваиваете значения int
-размерным членам этого пространства.Однако в первом случае вы выделяете достаточно большое пространство для размещения N
указателей для аннулирования, а затем, не инициализируя эти указатели, пытаетесь присвоить значения объектам, на которые они указывают .Даже если эти указатели были инициализированы, чтобы указывать на int
объекты, существует дополнительный уровень косвенности.
Ваш первый код можно исправить, в некотором смысле, например:
void** a = malloc(sizeof(void*) * N);
for (int i =0; i < N; i++) {
a[i] = (void *) i;
}
printf("%d\n", (int) a[N-1]);
Это основано на том факте, что C допускает преобразования между указателем и целочисленным типом (хотя и не обязательно без потери данных), и обратите внимание, что существует только один уровень косвенности (индексация массива), а не два.
Поскольку поведение вашей реализации первой альтернативы не определено, мы можем только догадываться о том, почему она работает медленнее на практике.Однако, если мы предполагаем простую реализацию, такое ухудшение производительности, как вы заметили, может быть вызвано плохой локальностью кэша для всех записей массива.