Будут ли все объявления в пределах области действия в начале функции после компиляции (в C)? - PullRequest
2 голосов
/ 02 февраля 2011

Будут ли в пределах области видимости все объявления в начале функции после компиляции (в C)? Следующие примеры показывают немного лучше, что мне интересно. Если что-то пошло не так с «ptr1», могу ли я предположить, что ptr2 был инициализирован как NULL?

int main()
{
  int ret = 0;

  void * ptr1 = NULL;
  if (ret = do_ptr_work(ptr1))
    goto done;

  void * ptr2 = NULL;
  if (ret = do_ptr_work(ptr2))
    goto done;

done:
  if (ptr1) {
    free(ptr1);
    ptr1 = NULL;
  }
  if (ptr2) {
    free(ptr2);
    ptr2 = NULL;
  }

  return ret;
}

Спасибо, Chenz

Ответы [ 2 ]

3 голосов
/ 02 февраля 2011

Нет.Инициализация определена, чтобы произойти, когда объявление достигнуто.Если вы перепрыгните через инициализацию, переменная существует, но не будет инициализирована.

Одной важной частью стандарта C является §6.2.4:

Если для объекта указана инициализация, он выполняется каждый раз, когда достигается объявление при выполнении блока;в противном случае значение становится неопределенным при каждом достижении декларации.

(обратите внимание, что этот текст применяется только к объектам с длительностью автоматического хранения ).Другой - §6.8:

Инициализаторы объектов, которые имеют автоматическую продолжительность хранения, и деклараторы массива переменной длины обычных идентификаторов с областью блока, оцениваются и значения сохраняются в объектах (включая сохранениенеопределенное значение в объектах без инициализатора) каждый раз, когда объявление достигается в порядке выполнения, как если бы оно было оператором, и внутри каждого объявления в порядке появления деклараторов.

0 голосов
/ 02 февраля 2011

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

Почему бы просто не объявить переменные в начале области? Все равно выглядит аккуратнее для моих глаз.

int main()
{
  void * ptr1 = NULL;
  void * ptr2 = NULL;
  int ret = 0;

  if (ret = do_ptr_work(ptr1))
    goto done;

  if (ret = do_ptr_work(ptr2))
    goto done;

done:
  if (ptr1) {
    free(ptr1);
    ptr1 = NULL;
  }
  if (ptr2) {
    free(ptr2);
    ptr2 = NULL;
  }

  return ret;
}

Или даже просто полностью изменить рефакторинг для удаления goto?

int main()
{
  void * ptr1 = NULL;
  void * ptr2 = NULL;

  int ret = do_ptr_work(ptr1);

  if (!ret) 
    ret = do_ptr_work(ptr2);

  // Tidy up...
  if (ptr1) {
    free(ptr1);
    ptr1 = NULL;
  }
  if (ptr2) {
    free(ptr2);
    ptr2 = NULL;
  }

  return ret;
}
...