Порядок переменных определяется стандартом? - PullRequest
2 голосов
/ 08 декабря 2010

См. Следующее:

static char start_marker;
static int var_1;
static int var_2;
/* ... */
static int var_n;
static char end_marker;

Я хочу инициализировать все переменные в разделе.Допустим ли следующий код?

memset(&start_marker, 0, &end_marker-&start_marker);

Обратите внимание, что я не могу использовать struct здесь, потому что эти поля используются препроцессором db2 в качестве так называемых переменных хоста.

Ответы [ 6 ]

4 голосов
/ 08 декабря 2010

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

2 голосов
/ 08 декабря 2010

Первый - по Си стандартные статические переменные предварительно инициализируются нулями - почти ЧАВО, Инициализация статической переменной?

Если все, что вам нужно, это статические данные с нулевой инициализацией, то вам ничего не нужно делать.

Если вы хотите либо обнулить целую партию статических переменных в более поздний момент времени за один раз, и / или требовать преинициализации указанного пакета для конкретных других значений, вы должны указать linker ( не компилятор), чтобы поместить эти переменные в конкретно известные адреса. Это называется «разделом», и куда они идут, могут контролироваться сценариями компоновщика.
Смотрите пример здесь:

http://www.math.utah.edu/docs/info/ld_3.html#SEC18

Это показывает, как работает код инициализации по умолчанию.

Вы можете даже заставить компоновщик создать / заполнить символ (указатель) адресом, если это ваш специальный раздел. В вашем коде C / C ++ вы должны сделать extern void* varblkaddr; extern size_t varblksize, и на самом деле скрипт компоновщика создаст переменные с этими именами, инициализированные для выбранных вами адресов.

На самом деле, stackoverflow - замечательный ресурс. Это должно помочь:

Фиксированная переменная адреса в C

1 голос
/ 08 декабря 2010

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

Если вы хотите иметь возможность сбросить их все на ноль как группу позже, используя memset, вам нужно поставить их всев struct.В противном случае их местоположение является независимым.

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

1 голос
/ 08 декабря 2010

Ваш код рассчитан не только на порядок, но и на смежность: здесь у меня нет никаких гарантий.

Однако вам, вероятно, следует рассмотреть возможность группировки всех этих переменных в struct.

0 голосов
/ 08 декабря 2010

Не делайте этого, в общем, это просто бесполезно и подвержено ошибкам. Переменные со статическим распределением инициализируются до 0 с самого начала. Нет необходимости их инициализировать. Кроме того, для этого компилятор выбирает правильный 0, например, 0.0 для значений типа double или константу нулевого указателя для указателей и т. Д.

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

static int var_1 = { 0 };

Этот резервный инициализатор всегда должен работать. Еще лучше, если у вас есть C99-совместимый компилятор, есть назначенные инициализаторы:

static int arr[3] = { [0] = 0, [1] = 42,  };

Поля, которые не упомянуты в инициализаторе, снова по умолчанию инициализируются на 0, например, здесь элемент arr[2].

Вся эта явная инициализация работает для статически распределенных переменных или для переменных стека (auto). memset используется часто для этой цели. Просто позвольте компилятору сделать это за вас. В худшем случае он просто сделает memset, но часто у него есть более умный способ сделать это.

0 голосов
/ 08 декабря 2010

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

Если вы хотите их инициализировать, используйте:

void initVars() {
    start_marker = 0;
    var_1 = 0;
    var_2 = 0;
    /* ... */
    var_n = 0;
    end_marker = 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...