#c# #.net #c#-3.0
#c# #.net #c #-3.0
Вопрос:
Почему использование адреса переменной устраняет ошибку «Использование неназначенной локальной переменной»?
(Почему мы можем взять адрес без инициализации в первую очередь?)
static unsafe void Main()
{
int x;
int* p = amp;x; //No error?!
x = 2; //No error?!
}
Комментарии:
1. Заголовок не для тегов, вы знаете, не так ли?:)
2. @abatishchev: Да, я знаю, но я подумал, что это было бы полезно в любом случае. Хотя, тем не менее, спасибо за редактирование. 🙂
3. Вторая часть вашего вопроса, почему мы можем использовать адрес, проста: потому что переменная имеет адрес, независимо от того, присвоили вы ей значение или нет. Но интересно, что компилятор затем считает
x
инициализированным…4. Мне кажется, это код C , а не C#
5. @Flawless если бы C требовал, чтобы вы сообщали, когда вы были
unsafe
тогда программы на C были бы намного длиннее 🙂
Ответ №1:
Спецификация языка C #, раздел 18.5.4:
amp;
Оператор не требует, чтобы его аргумент был определенно назначен, но послеamp;
операции переменная, к которой применяется оператор, считается определенно назначенной в пути выполнения, в котором выполняется операция. Программист несет ответственность за то, чтобы в этой ситуации действительно выполнялась правильная инициализация переменной.
…
Существуют правила определенного присвоения для оператора amp;, позволяющие избежать избыточной инициализации локальных переменных. Например, многие внешние API принимают указатель на структуру, которая заполняется API. Вызовы таких API обычно передают адрес локальной переменной структуры, и без правила потребовалась бы избыточная инициализация переменной структуры.
Комментарии:
1. О.М.Г … значит, они не шутили насчет «небезопасности» в
unsafe
блоках!2. Я должен отметить: при дальнейшем рассмотрении разборки кажется, что CLR все равно инициализирует переменную с помощью
.locals init
. Так что, может быть, это не так уж и небезопасно в конце концов…3. @Mehrdad: Похоже, я недостаточно глубоко прочитал; спецификация действительно дает обоснование правилу. Смотрите абзац, который я добавил.
4. @Gabe: Интересно. Но теперь возникает вопрос, ну и что? Что не так с избыточной инициализацией?
5. @Mehrdad: Что с этим не так? Ну, это избыточно. И всего избыточного можно и нужно избегать 🙂 Когда вы программируете на родных языках, таких как C и C , вы учитесь не использовать то, что вам не нужно. Или как говорится в C .. вы платите только за то, что используете.
Ответ №2:
Я думаю, потому что, как только вы взяли указатель на переменную, у компилятора нет возможности проанализировать, присвоено ли значение с помощью этого указателя, поэтому оно исключается из анализа определенного присвоения.
Комментарии:
1. @Damien: Хорошо, конечно, но почему это не заставляет меня сначала инициализировать ее? Разве это не лучше, чем потом сожалеть?
2. @Merhdad — потому что вы едете по бездорожью с небезопасным кодом — возможно, вам нужна каждая унция производительности из этого фрагмента кода — поэтому компилятор, заставляющий вас выполнять дополнительную работу, был бы плохим.
3. @Rick: Разве компилятор C не выдает ошибку, когда видит
unsafe
?4. @Gabe: Я спросил себя, если теория Дэмиена верна, то эквивалентный код C также не выдаст предупреждение компилятором C . У него также возникает та же проблема после получения адреса. Итак, основной код — это часть с отступом. Это то, что я тестировал.