Будет ли компилятор C оптимизировать разыменование в цикле?

Представьте, что у меня есть такая структура:

struct GayClub { 
  ...
  int ndrinks;
  ...
}

И теперь я перебираю вот так:

// my struct
struct GayClub gc;

//....

// my loop
int i = 0;
for (; i < gc.ndrinks; ) {
  ...
  // no modifications on gc.ndrinks
  ...
  i++;
}

Вопрос в том, будет ли компилятор C, такой как GCC, cLang или Rusc? оптимизировать это так? Это быстрее, потому что я не удаляю ссылку на память.

// trick
int tmpNDrinks = gc.ndrinks;
// my za-loop-a
for (; i < tmpNDrinks; ) {
  ...
  // no modifications on gc.ndrinks
  ...
  i++;
}

Опять же, я спрашиваю об этом, потому что НЕ хочу каждый раз извлекать ограничения для отдельной переменной, если компилятор уже делает это за меня.

В обоих случаях предел цикла находится в памяти, но при предполагаемой оптимизации вы потратили время и пространство, копируя его из одной области памяти в другую. Пожалуйста, посмотрите Действительно ли преждевременная оптимизация является корнем всех зол? Если вы считаете, что могут возникнуть проблемы с производительностью, профилируйте код, но такая микрооптимизация редко бывает необходима.

Weather Vane 01.09.2024 19:40

Кроме того: вы использовали синтаксис цикла for как цикл while, что делает код немного сложнее для чтения. Вы могли бы правильно соединить петлю for, как for (int i = 0; i < gc.ndrinks; i++). Это зависит от того, что вам понадобится i после цикла в невидимом коде.

Weather Vane 01.09.2024 19:44

@WeatherVane: Re: «В вашей предполагаемой оптимизации вы потратили время и пространство, копируя его из одного места памяти в другое»: Нет, предполагаемая оптимизация не тратит зря время и пространство. Стандарт C ничего не говорит о фактическом времени или пространстве, которые будут использоваться этой оптимизацией. int tmpNDrinks = gc.ndrinks; создает новый объект, используя пространство и копируя память только внутри абстрактной машины, описанной стандартом C. Эта абстрактная машина существует только для того, чтобы определить семантику программы, а не для того, чтобы требовать фактического использования времени или пространства.

Eric Postpischil 01.09.2024 19:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это зависит от множества факторов, в том числе:

  • Будь то хороший компилятор.

  • Включили ли вы оптимизацию в компиляторе.

  • Видно ли компилятору, что объект не будет изменен другими способами.

Например, предположим, что тело цикла использует некоторый int *p, который передается в качестве параметра или загружается из структуры данных. Если тело цикла содержит *p, как компилятор узнает, указывает p на gc.ndrinks или нет? Если компилятор не может знать в качестве математического доказательства, что p не указывает на gc.ndrinks, тогда он должен генерировать код так, как если бы p мог указывать на gc.ndrinks.

Ваш пример неполон, поэтому читателю неясно, определен ли gc внутри функции и имеет ли автоматическая продолжительность хранения. Если да, то компилятор может предположить, что параметр gc не указывает на gc, поскольку int *p не существовало во время вызова функции. Однако если gc не является параметром или если p определен вне функции, компилятор может оказаться не в состоянии определить, что gc.ndrinks не может указывать на int *p.

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

Другие вопросы по теме