Что происходит с объявленной неинициализированной переменной в C? Это имеет значение?

Вы можете сделать это с помощью одной команды:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Вы также можете добавить -nodes, если вы не хотите защищать свой закрытый ключ парольной фразой, иначе он предложит вам " как минимум 4 символа ". Параметр days (365) можно заменить любым числом, чтобы повлиять на дату истечения срока действия. Затем он предложит вам такие вещи, как «Имя страны», но вы можете просто нажать «Ввести» и принять значения по умолчанию.

Добавить -subj '/CN=localhost', чтобы подавить вопросы о содержимом сертификата (замените localhost на желаемый domain)

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

130
задан Ciro Santilli 新疆改造中心法轮功六四事件 18 April 2016 в 19:05
поделиться

5 ответов

Статические переменные (область действия файла и статическая функция) инициализируются нулем:

int x; // zero
int y = 0; // also zero

void foo() {
    static int x; // also zero
}

Нестатические переменные (локальные переменные) неопределенные . Чтение их перед присвоением значения приводит к неопределенному поведению.

void foo() {
    int x;
    printf("%d", x); // the compiler is free to crash here
}

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

Что касается того, почему это неопределенное поведение вместо простого «неопределенное / произвольное значение», существует ряд архитектур ЦП, которые имеют дополнительные биты флагов в своем представлении для различных типов. Современный пример - Itanium, у которого в регистрах есть бит «Not a Thing» ; конечно, разработчики стандарта C рассматривали некоторые более старые архитектуры.

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

179
ответ дан 24 November 2019 в 00:17
поделиться

0, если статический или глобальный, неопределенный, если класс хранения - автоматический

C всегда очень точно определял начальные значения объектов. Если глобальные или статические , они будут обнулены. Если auto , значение будет неопределенным .

Так было в компиляторах до C89 и было так указано K&R и в исходном отчете DMR на C.

Это было так. случай в C89, см. раздел 6.5.7 Инициализация .

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

Так было в C99, см. раздел 6.7.8 Инициализация .

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

Что касается того, что именно означает неопределенный , я не уверен для C89, C99 говорит:

3.17.2
неопределенное значение

либо неопределенное значение, либо ловушка представление

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

Вы можете задаться вопросом, почему это так? Другой ответ SO связан с этим вопросом, см .: https://stackoverflow.com/a/2091505/140740

57
ответ дан 24 November 2019 в 00:17
поделиться

Основной ответ - да, это не определено.

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

0
ответ дан 24 November 2019 в 00:17
поделиться

Это зависит от обстоятельств. Если это определение является глобальным (вне любой функции), тогда num будет инициализировано нулем. Если он локальный (внутри функции), то его значение не определено. Теоретически, даже попытка прочитать значение имеет неопределенное поведение - C допускает возможность битов, которые не вносят вклад в значение, но должны быть установлены определенным образом, чтобы вы даже могли получить определенные результаты от чтения переменной.

4
ответ дан 24 November 2019 в 00:17
поделиться

Зависит от продолжительности хранения переменной. Переменная со статической продолжительностью хранения всегда неявно инициализируется нулем.

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

int num;
int a = num;
int b = num;

не гарантирует, что переменные a и b получат одинаковые значения. Интересно, что это не какая-то педантичная теоретическая концепция, это легко происходит на практике как следствие оптимизации.

В общем, популярный ответ, что "

11
ответ дан 24 November 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: