Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2012.02.12;
Скачать: [xml.tar.bz2];

Вниз

Особенности инициализации переменных в C#   Найти похожие ветки 

 
И. Павел ©   (2011-10-18 16:12) [0]

Есть код на C#:
string s;
for (int i = 0; i < 1; i++)
{
 s = "test";
};
Console.WriteLine(s);


При компиляции выскакивает ошибка на последней строке: переменная s не инициализированна. В книжке говорят, что так и должно быть, но как-то неубедительно аргументируют.
Зачем разработчики C# решили выбрать такой подход? В других языкая я ничего подобного не встречал.

PS: Кстати, если for заменить на простой блок {} или на блок while или do с константным выполнением 1 раз, то инициализация во внутреннем блоке засчитывается. Это только for такой особенный? Не верю, что современный компилятор не способен определить, что цикл (int i = 0; i < 1; i++) будет выполнен строго 1 раз.


 
Вася   (2011-10-18 16:21) [1]


> При компиляции выскакивает ошибка на последней строке: переменная
> s не инициализированна.

Предупреждение?


 
И. Павел ©   (2011-10-18 16:25) [2]

> Предупреждение?

Нет. Отказывается компилироваться и запускаться. В окне "список ошибок" указано, что обнаружена 1 ошибка.


 
_Юрий   (2011-10-18 16:38) [3]


> что современный компилятор не способен определить, что цикл
> (int i = 0; i < 1; i++) будет выполнен строго 1 раз.


Вряд ли современный компилятор заточен под такие бессмысленные частные случаи.
А в общем случае он совершенно прав.


 
stas ©   (2011-10-18 16:44) [4]

Я вот что-то не помню чтобы в C# за "}" ставилась ";"


 
И. Павел ©   (2011-10-18 16:49) [5]

[4] stas ©   (18.10.11 16:44)
Просто я пробовал разные циклы для этого блока. В том числе и do. Условие завершения удалил, а ";" лсталась. Все равно арят ли она останется в MSIL и уж тем более не переведется в машинный код ;)


 
Kerk ©   (2011-10-18 16:50) [6]


> stas ©   (18.10.11 16:44) [4]

Это ничего не меняет, если мне не изменяет склероз.


 
И. Павел ©   (2011-10-18 16:50) [7]

арят ли -> вряд ли


 
Kerk ©   (2011-10-18 16:50) [8]

В C точка с запятой -- statement terminator, в Pascal -- statement separator. Поэтому в Delphi их нельзя ставить просто так, а в C можно.


 
stas ©   (2011-10-18 16:54) [9]

Объявляйте так:string s="";


 
icelex ©   (2011-10-18 16:55) [10]


> И. Павел ©   (18.10.11 16:12) 

абсолютно правильно говорит: у тебя цикл может быть не выполнен ни разу и переменная не инициализируется.


 
stas ©   (2011-10-18 16:55) [11]

Вообще странно конечно почему ошибка, а не предупреждение.


 
stas ©   (2011-10-18 16:57) [12]

Kerk ©   (18.10.11 16:50) [6]
ага, считал что будет ошибка.


 
icelex ©   (2011-10-18 16:57) [13]

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


 
И. Павел ©   (2011-10-18 16:59) [14]

> [9] stas ©   (18.10.11 16:54)

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

"Здесь последнее значение, присваиваемое text в цикле, доступно и за пределами
цикла. Очевидно, что понимание данной темы требует приложения несколько  
больших усилий. На первый взгляд не совсем ясно, почему, с учетом предыдущего  
примера, у переменной text после цикла не остается в качестве значения та пустая строка,
которая была присвоена ей перед началом цикла в коде.
Причина такого поведения связана с выделением памяти для переменной text, как,
по сути, это делается для любой другой переменной. Одно лишь объявление  
переменной простого типа ни к каким особым действиям не приводит. Только при  
присваивании переменным значений для их хранения в памяти выделяется место. Когда эта
операция по выделению памяти происходит внутри цикла, значение определяется как
локальное значение и тогда за пределами цикла оно покидает свою область видимости.
Даже хотя сама переменная не ограничивается циклом, то значение, которое в ней
содержится, ограничивается им. Присваивание значения переменной за пределами
цикла, однако, делает его локальным по отношению к главному коду и при этом все
равно оставляет действительным внутри цикла. Это означает, что переменная не  
выходит за рамки области видимости до тех пор, пока не завершится выполнения  
основного блока кода, благодаря чему к содержащемуся в ней значению можно получать
доступ и за пределами цикла.
К счастью для программистов, компилятор С# обнаруживает проблемы, связанные
с областью видимости переменных, а реагирование на генерируемые им сообщения
об ошибках, действительно позволяет лучше разобраться в этой теме. "

Книга называется "Visual C# Базовый курс"


 
DiamondShark ©   (2011-10-18 17:12) [15]


> stas ©   (18.10.11 16:55) [11]
> Вообще странно конечно почему ошибка, а не предупреждение.

Потому что использование неинициализированной переменной -- грубая ошибка.


 
euru ©   (2011-10-18 20:03) [16]


> И. Павел ©   (18.10.11 16:12) 
> Зачем разработчики C# решили выбрать такой подход?

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


> PS: Кстати, если for заменить на простой блок {} или на
> блок while или do с константным выполнением 1 раз, то инициализация
> во внутреннем блоке засчитывается.

Поведение для while такое же, как и для for.
string s;
int i = 0;
while (i < 1)
{
  s = "test";
  i++;
}

Также выдаётся сообщение об ошибке.

Для цикла do сообщения не будет, если внутри него не будет команды выхода из цикла до инициализации переменной.
string s;
int i = 0;
do
{
  // if (i > 0) break; <-- убрать комментарий - появится соообщение
  s = "test";
  // if (i > 0) break; <-- не влияет на компиляцию
  i++;
} while (i < 1);


 
Sha ©   (2011-10-18 20:18) [17]

> И. Павел ©   (18.10.11 16:12)  
> При компиляции выскакивает ошибка на последней строке: переменная s не инициализированна.

Ты радоваться должен. Серьезно.

> Kerk ©   (18.10.11 16:50) [8]
> В C точка с запятой -- statement terminator, в Pascal -- statement separator.
> Поэтому в Delphi их нельзя ставить просто так, а в C можно.

Просто как?
Можно пример, что нельзя?


 
Kerk ©   (2011-10-18 20:30) [18]


> Sha ©   (18.10.11 20:18) [17]
> Просто как?
> Можно пример, что нельзя?

Например:
begin
 ...
end;;


Разве можно? Честно говоря, лень проверять :)


 
Sha ©   (2011-10-18 20:41) [19]

> Kerk ©   (18.10.11 20:30) [18]

Можно везде где допустим пустой оператор.


 
И. Павел ©   (2011-10-18 20:43) [20]

Всем спасибо!
То есть получается, что компилятор ругается просто из-за того, что не понимает, что цикл выполнится хотя бы один раз?

А то, судя по тому, что написано в книге, можно решить, что после выхода из блока все значения, присвоенные в этом блоке переменным, объявленным во внешних блоках, очищаются. Такого или подобного сюрприза в C# быть не может?

Вот это место в книге:

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


 
Kerk ©   (2011-10-18 21:02) [21]


> Sha ©   (18.10.11 20:41) [19]
>
> > Kerk ©   (18.10.11 20:30) [18]
>
> Можно везде где допустим пустой оператор.

Вот за что я люблю этот форум, так за то, что к киевскому дядьке разговор сводится моментально :)


 
Sha ©   (2011-10-18 21:12) [22]

> Kerk ©   (18.10.11 21:02) [21]

ты же не хотел написать

pro;ce;dure

правда?


 
Kerk ©   (2011-10-18 21:20) [23]


> Sha ©   (18.10.11 21:12) [22]

Если ты перечитаешь посты [8] и [18], ты сразу поймешь, что я хотел, а что нет. И какой нюанс в различиях языков хотел подчеркнуть.

:)


 
Kerk ©   (2011-10-18 21:22) [24]

Лучше даже начать с постов [4] и [6]


 
Sha ©   (2011-10-18 21:34) [25]

> Kerk

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


 
Kerk ©   (2011-10-18 21:51) [26]


> Sha ©   (18.10.11 21:34) [25]

Продолжай, не буду мешать.


 
euru ©   (2011-10-18 22:44) [27]


> И. Павел ©   (18.10.11 20:43) [20]
> То есть получается, что компилятор ругается просто из-за
> того, что не понимает, что цикл выполнится хотя бы один
> раз?

А компилятор и не пытается понять. Потому что в общем случае невозможно гарантировать инициализацию во вложенном уровне видимости.

http://blogs.msdn.com/b/ruericlippert/archive/2009/10/12/9929757.aspx
http://blogs.msdn.com/b/ruericlippert/archive/2011/03/05/never-say-never-part-two.aspx


 
Pavia ©   (2011-10-18 23:02) [28]

По поводу кода в 1 посте. Этот код будет ругаться в C# 3 версии.
Потому что начиная с этой версии если компилятор может распознать тип переменной по строки инициализации то он это делает. Поэтому в данном коде есть две переменные c одним именем "s". Первая переменная объявлена в не цикла вторая в цикле.

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


 
Игорь Шевченко ©   (2011-10-18 23:11) [29]


> Потому что начиная с этой версии если компилятор может распознать
> тип переменной по строки инициализации то он это делает.
>  Поэтому в данном коде есть две переменные c одним именем
> "s". Первая переменная объявлена в не цикла вторая в цикле.
>  


А можно еще раз и помедленнее, для бестолковых ? :)


 
DiamondShark ©   (2011-10-18 23:44) [30]


> Pavia ©   (18.10.11 23:02) [28]

Вы бредите.


 
Kerk ©   (2011-10-18 23:54) [31]

Попробую угадать. Речь про вывод типов?


 
Pavia ©   (2011-10-18 23:59) [32]

Первая стадия компилятора лексический анализ. Вторая стадия грамматический анализ.
Третья стадия семантический анализ.
Часто работа в компиляторе построена по принципу конвейера.
Это значит что семантический анализ начинается когда грамматический закончил делать некоторую часть, не всю обработка теста.
Так вот прежде чем проверять допустимость применения переменных в операциях надо пройтись и найти эти самые переменные.
Объявлять переменные можно 2 способами.
string s;
..
s="...";
int i=5;

и второй способ

s="..."
i=5;

В том же паскале константы можно объявлять без указания типа. Компилятор сам справится с присвоением нужного типа.
Но в отличии от паскаля в Cи и С# переменные можно объявлять внутри statements.

> Не верю, что современный компилятор не способен определить,
>  что цикл (int i = 0; i < 1; i++) будет выполнен строго
> 1 раз.

Как раз таки компилятор правильно определяет. Цикл может выполниться 0 раз, а может бесконечно много. Это легко доказать. На это есть 2 причины.
Первая причина компьютере есть несколько ядер и  они могут работать параллельно. Это значит что переменная "i" может быть изменена во время выполнения.
Вторая причина это организация цикла.
Что тут записано.
(int i = 0; i < 1; i++) Эти строки надо трактовать как.
int i = 0; - то что выполняется до начала цикла.
i < 1; - то что выполняется в первой строчке цикла.
i++ - то что выполняется в последней строчки цикла.

Другими словами.


> for (int i = 0; i < 1; i++)
> {
>   s = "test";
> };

Трактуется как.

int i = 0;  i++)
{if (i < 1) breack;
 s = "test";
i=i++
};

Отсюда видно что если переменная i в силу работы второго ядра изменится, то до строчки s = "test"; выполнение не дойдёт.
Вот если бы вы записали цикл иначе.
for (int i = 0; i++; i < 1; )
{
  s = "test";
};
То тут гарантированно бы выполнился один раз. Так как условие выхода находиться в конце цикла.

Теперь ясно почему в первом случае компилятору правильнее считать s двумя разными переменными.

Вопрос как второе ядро может достучатся до переменной "i"? Ведь переменная имеет очень маленькую зону видимости. На самом деле это не совсем не верно.
Дело в том что C# является  интерпретируемым языком. А значит любая функция может получить доступ скажем к байт-коду который описывает эту программу. И как следствие может получить доступ к переменной i. Есть механизмы расширения кода основанные на delegate и тому подобное.


 
Pavia ©   (2011-10-19 00:04) [33]

Печатался, слегка.
Вместо

> Трактуется как.
>
>  int i = 0;  i++)
> {if (i < 1) breack;
>   s = "test";
>  i=i++
> };


Трактуется как.

int i = 0;
{if (i < 1) break;
 s = "test";
i=i++;};


 
Игорь Шевченко ©   (2011-10-19 00:24) [34]

Pavia ©   (18.10.11 23:59) [32]

Феерично!


> Цикл может выполниться 0 раз, а может бесконечно много.
> Это легко доказать. На это есть 2 причины.
> Первая причина компьютере есть несколько ядер и  они могут
> работать параллельно. Это значит что переменная "i" может
> быть изменена во время выполнения.


Дважды феерично!

Вам, сударь, книжки надо писать, Фленова за пояс заткнете. Только пунткуацию подтянуть.


 
Игорь Шевченко ©   (2011-10-19 00:24) [35]


> пунткуацию


пунктуацию


 
Джо ©   (2011-10-19 01:19) [36]

Ой-вей, зачем я это на ночь прочитал? Проснусь совсем больной и разбитый %)


 
Германн ©   (2011-10-19 01:23) [37]


> Вам, сударь, книжки надо писать

Лучше фантастику, если воображения хватит.


 
И. Павел ©   (2011-10-19 09:12) [38]

Что-то я запутался совсем…

В общем: уважаемые C# программисты, подскажите, пожалуйста, то, что написано на стр. 140, 141 в главе “Variable Scope in Other Structures” этой книги: http://www.fayloobmennik.net/1083499 - это ошибка авторов (которые предположение компилятора, что не будет ни одной итерации, приняли за какую-то проблему с областью видимости), или же тут есть какой-то хитрый смысл?

Судя по [28] хитрый смысл есть, но я так и не въехал в раздвоение переменной (авторы книги, кстати, тоже пишут про какое-то раздвоение, правда там все еще более изощренно)…

В английском тексте книги нового издания (2010г.) эта глава переписана без изменений… Т.е. никто из читателей не жаловался. А мне важно до сути докопаться: люблю, когда все в новом изучаемом языке ясно.


 
И. Павел ©   (2011-10-19 09:50) [39]

> [38] И. Павел ©   (19.10.11 09:12)

Вот ссылка на нужную главу книги, чтобы не скачивать с файлообменника: http://flylib.com/books/en/3.459.1.44/1/


 
icelex ©   (2011-10-19 11:14) [40]


> И. Павел ©   (19.10.11 09:12) [38]

нет там ничего про раздвоение
просто в цикле компилятор может быть уверен, что переменная инициализирована, т.к. использование переменной идет уже после инициализации
за пределами цикла нельзя быть уверенным, что переменная инициализирована внутри цикла
псмотри, например, на такой код
string s;
int x=0;
if (x==0)
{
s = "test";
}
Console.WriteLine(s);

у тебя возникнет та же ошибка

но стоит изменить его на
string s;
int x=0;
if (x==0)
{
s = "test";
}
else
{
s="test2";
}
Console.WriteLine(s);


как все встает на свои места


 
oxffff ©   (2011-10-19 12:14) [41]

http://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D1%84_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0_%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F


 
И. Павел ©   (2011-10-20 14:53) [42]

> [40] icelex ©   (19.10.11 11:14)

Спасибо. В принципе, по логике все понятно: можно считать, что переменная является локальной для того блока, в котором она инициализируется (если только на компилятор не нападет редкое прозрение, как в примере с if/else из [40]). Видимо, это сделали для того, чтобы GC мог удалить ненужные объекты, не дожидаясь того, когда закончится вся функция, в которой они объявлены. В Delphi и C++ это все, конечно, реализовано, проще. В JAVA, по моему, тоже.

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


 
И. Павел ©   (2011-10-20 14:54) [43]

> Подскажите, пожалуйста, правильно ли я понимаю, что компилятор
> сразу вернет ошибку и не допустит такого случая, когда переменная
> все еще доступна по имени, а ее значение уже нет (вышло
> из области видимости или что-то еще)? Т.е. об этом всегда
> будет заботиться компилятор, выдавая ошибку?

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


 
oxffff ©   (2011-10-20 15:06) [44]


> Подскажите, пожалуйста, правильно ли я понимаю, что компилятор
> сразу вернет ошибку и не допустит такого случая, когда переменная
> все еще доступна по имени, а ее значение уже нет (вышло
> из области видимости или что-то еще)? Т.е. об этом всегда
> будет заботиться компилятор, выдавая ошибку?


Если переменная доступна по имени и она является rvalue, значит ее значение тоже доступно.


 
И. Павел ©   (2011-10-20 15:11) [45]

> rvalue

"rvalue" т.е. значение переменной "читают" (т.е. она стоит справа или передается как параметр в функцию и т.д.). А если пишут - то это уже может быть вторая переменная, т.к. раз в нее пишут, то ее старое значение, в принципе, и не нужно? Я правильно понял?


 
oxffff ©   (2011-10-20 15:19) [46]


> И. Павел ©   (20.10.11 15:11) [45]


http://www.rsdn.ru/article/cpp/lvalue.xml


 
И. Павел ©   (2011-10-20 15:26) [47]

> [46] oxffff ©   (20.10.11 15:19)

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


 
oxffff ©   (2011-10-20 15:33) [48]


> И. Павел ©   (20.10.11 15:26) [47]


В чем запутался?
Если переменная вышла из области видимости, значит не доступна она ни как lvalue, ни как rvalue. То есть ее больше нет.
Место для это переменной может быть удалено сразу, позже, reuse для других целей.


 
И. Павел ©   (2011-10-20 15:39) [49]

> [48] oxffff ©   (20.10.11 15:33)

Ясно, спасибо. Просто в книге начали отделать термен "область видимости переменной" от "области видимости значения переменной", вот я и подумал, что эти две вещи могут иметь разные области видимости. Запутался, проще говоря. Думаю, просто сменю книгу на Троелсена.


 
И. Павел ©   (2011-10-20 15:39) [50]

> отделать

отделять


 
icelex ©   (2011-10-20 16:01) [51]


> И. Павел ©   (20.10.11 15:39) [49]
> Думаю, просто сменю книгу на Троелсена.

у Троелсена этого нет, это основы. Но и нет запуток, которые можно разбирать только тогда, когда есть база.


 
Inovet ©   (2011-10-20 16:14) [52]

int a;
{
 a = 1;
 int b = 2;
}
// b уже нет
// a == 1

или по-другому

int a = 1;
{
 int a = 2;
}
// второй a == 2 уже нет
// a == 1


 
И. Павел ©   (2011-10-20 16:20) [53]

> // второй a == 2 уже нет

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

Т.е., подытожив, я ведь могу сказать, что компилятор и не позволит мне обратиться к переменной, значение которой уже вышло из области видимости/пропало?


 
Юрий Зотов ©   (2011-10-20 17:04) [54]

> Kerk

Ты неправ, Юпитер. В коде сабжа искомая точка с запятой будет распознана компилятором именно как пустой оператор (потому что концом оператора цикла будет распознана закрывающая фигурная скобка). Синтаксис здесь примерно такой:

пустой_оператор ::= ;
оператор_for ::= for заголовок_цикла оператор
оператор ::= блок_операторов | простой_оператор
простой_оператор ::= оператор_for | пустой_оператор | и т.д.
блок_операторов ::= { пусто | список_операторов }
список_операторов ::=  оператор | оператор ; список_операторов

Отсюда и видно, что точка с запятой ПОСЛЕ закрывающей фигурной скобки будет расценена, как пустой оператор, СЛЕДУЮЩИЙ ЗА блоком. И никакие терминаторы-сепараторы тут ни при чем.


 
George ©   (2011-10-20 17:54) [55]

За оффтоп мож и потрут, но так и тянет в название темы вставить "национальной" :)


 
Юрий Зотов ©   (2011-10-20 18:25) [56]

> Kerk

Кстати о терминаторах-сепараторах. В классическом Паскале точка с запятой - это действительно statement separator - то есть, РАЗДЕЛИТЕЛЬ ПРЕДЛОЖЕНИЙ. Поэтому он может ставиться только МЕЖДУ предложениями, а вот на такую конструкция компилятор классического Паскаля уже ругнется:
begin
 a := 3 ;
end

поскольку end - это не предложение, а закрывающая скобка (то есть, ПЕРЕД end точка с запятой стоять не может никогда - точно так же, как и в естественных языках).

Но в Delphi от строгости классического Паскаля несколько ушли и та же самая конструкция в Delphi проходит без проблем. Вообще говоря, в Delphi точка с запятой скорее используется так же, как в C, чем как в Паскале. То есть, именно как терминатор и как пустой оператор.


 
Kerk ©   (2011-10-20 18:36) [57]


> Юрий Зотов ©   (20.10.11 18:25) [56]
> Вообще говоря, в Delphi точка с запятой скорее используется
> так же, как в C, чем как в Паскале. То есть, именно как
> терминатор и как пустой оператор.

Различия все еще остаются. Например:

if (a == 1)
 b = 2;
else
 b = 3;

В C-подобных языках и

if a = 1 then
 b := 2
else
 b := 3;

в паскале-подобных.

Не знаю насколько заметно оно выделится, так что уточню, что речь о ";" перед else.


 
Kerk ©   (2011-10-20 18:49) [58]

Но синтаксис сделали менее строгим, это да. В изначальном посте я это упустил.


 
_Юрий   (2011-10-20 19:26) [59]


> Т.е., подытожив, я ведь могу сказать, что компилятор и не
> позволит мне обратиться к переменной, значение которой уже
> вышло из области видимости/пропало?
>
>


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


 
DiamondShark ©   (2011-10-20 19:34) [60]


> Юрий Зотов ©   (20.10.11 18:25) [56]
> > KerkКстати о терминаторах-сепараторах. В классическом
> Паскале точка с запятой - это действительно statement separator
> - то есть, РАЗДЕЛИТЕЛЬ ПРЕДЛОЖЕНИЙ. Поэтому он может ставиться
> только МЕЖДУ предложениями, а вот на такую конструкция компилятор
> классического Паскаля уже ругнется:begin  a := 3 ; endпоскольку
> end - это не предложение, а закрывающая скобка (то есть,
>  ПЕРЕД end точка с запятой стоять не может никогда - точно
> так же, как и в естественных языках).

Открываем книжку К.Йенсен, Н.Вирт "Pascal User Manual and Report", рус. пер. Д.Б.Подшивалова, М. "Финансы и статистика", 1989.
Самый классический Паскаль из всех паскалей. Смотрим Синтаксические диаграмы:

30. Составной оператор == "begin" Последовательность операторов "end"
31. Последовательность операторов == Оператор {";" Оператор}
32. Оператор == [Метка ":"] (Простой оператор | Сложный оператор)
33. Простой оператор == Пустой оператор | Оператор присваивания | Оператор процедуры | Оператор перехода
...
37. Пустой оператор ==

конструкция:
begin
 a := 3 ;
end


Даёт дерево разбора:


Составной оператор
"begin"
 Последовательность операторов
   Оператор
     Простой оператор
       Оператор присваивания
         "a := 3"
   ";"
   Оператор
     Простой оператор
       Пустой оператор
"end"


Никогда в жизни классический Паскаль на подобную конструкцию не ругался, это абсолютно синтаксически корректная конструкция.


 
Sha ©   (2011-10-20 19:35) [61]

> Юрий Зотов ©   (20.10.11 18:25) [56]
> а вот на такую конструкция компилятор классического Паскаля уже ругнется:
> begin
>   a := 3 ;
> end


А как же тогда вписать пустой оператор между присваиванием и end"ом?


 
Inovet ©   (2011-10-20 19:39) [62]

> [32] Pavia ©   (18.10.11 23:59)
> Первая причина компьютере есть несколько ядер и  они могут
> работать параллельно. Это значит что переменная "i" может
> быть изменена во время выполнения.

Может ты имел ввиду изменения значения переменной всякими потусторонними силами аппаратуры? Для вступления в сговр с тёмными придумано заклинание
volatile


 
DiamondShark ©   (2011-10-20 19:56) [63]


> Но в Delphi от строгости классического Паскаля несколько
> ушли


Ни от какой "строгости" (формальная грамматика либо "строгая", либо она не формальная) никто никуда не уходил. Продукция "Пустой оператор" как была с самого начала, так и есть.

Конечно, её наличие приводит к тому, что синтаксически корректными становятся весьма экзотические конструкции:

if 1=2 then else write("kuku")

begin ;;;;;;;; end

Но без неё не была бы синтаксически корректной, минимальная программа:

program P;
begin
end.

или, например, пустой цикл:

repeat until false


 
Marser ©   (2011-10-21 03:11) [64]


> stas ©   (18.10.11 16:54) [9]
>
> Объявляйте так:string s="";

string.Empty тогда уж :-)


 
jack128_   (2011-10-21 19:21) [65]


> string.Empty тогда уж :-)

а чем смысл??  чем string.Empty очевиднее "" ??


 
Marser ©   (2011-10-27 02:55) [66]


> jack128_   (21.10.11 19:21) [65]
>
>
> > string.Empty тогда уж :-)
>
> а чем смысл??  чем string.Empty очевиднее "" ??

Как минимуму, читается лучше.
У одного реального гуру в С++ коде видел константу и на -1.


 
jack128_   (2011-10-27 11:15) [67]


>
> Как минимуму, читается лучше.

э-э-э. Ну видимо у нас совсем разные представления о читабельности.


 
Ega23 ©   (2011-10-27 11:19) [68]


>  видел константу и на -1.


Я такие завожу. Для default-значения очень удобно. Мало ли потом default поменяется?


 
Бездомный   (2011-10-27 11:52) [69]


> Мало ли потом default поменяется?

Часто менялся?


 
Ega23 ©   (2011-10-27 11:54) [70]


> Часто менялся?


Бывало.
В принципе, это достаточно, чтобы константу объявить.


 
euru ©   (2011-10-27 14:42) [71]


> Ega23 ©   (27.10.11 11:19) [68]
> Я такие завожу. Для default-значения очень удобно. Мало ли потом default поменяется?

Вряд ли значению String.Empty грозят какие-либо изменения. :)


 
Kerk ©   (2011-10-27 14:59) [72]


> euru ©   (27.10.11 14:42) [71]

Так же в 95 году думали те, кто писал 1 вместо SizeOf(Char) :)

Но вообще, до фанатизма и правда не стоит доводить.


 
Ega23 ©   (2011-10-27 15:00) [73]


> Вряд ли значению String.Empty грозят какие-либо изменения.
>  :)


String.Emty - не грозит, да.


> У одного реального гуру в С++ коде видел константу и на  -1.


А вот тут вполне может и того.


 
Ega23 ©   (2011-10-27 15:00) [74]


> Так же в 95 году думали те, кто писал 1 вместо SizeOf(Char)
> :)


Они даже 1 не писали. :)


 
Компромисс   (2011-10-27 19:04) [75]

Marser ©   (27.10.11 02:55) [66]


> У одного реального гуру в С++ коде видел константу и на
> -1.


Я, конечно, не гуру, но искренне считаю всех, кто не следует данному правилу, не слишком хорошими программистами.
Есть как минимум 3 достоинства у данного подхода:
1) читабельность/документируемость
Ср. variable = -1; и variable = NOT_FOUND;
2) безопасность. Если вдруг выяснится, что -1 не подходит и надо исправить всюду на -2, то придется проверять все случаи использования -1, чтобы понять, относится ли данное использование к NOT_FOUND или это вообще из другой оперы.
Например,
variable1 = -1;
variable2 = -1;
Вполне возможно, что одна из них должна остаться -1
3) явные зависимости - среда легко покажет, в каких местах используется NOT_FOUND
3)



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2012.02.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.68 MB
Время: 0.004 c
1-1283530198
pushkin42
2010-09-03 20:09
2012.02.12
Зависание IDE при компиляции


15-1319639915
dreamse
2011-10-26 18:38
2012.02.12
Настройка интерфейса IDE Вудзрш 2005 - 2009


15-1319574602
Юрий
2011-10-26 00:30
2012.02.12
С днем рождения ! 26 октября 2011 среда


15-1319187613
George
2011-10-21 13:00
2012.02.12
Расчет индекса Хирша


2-1320428134
tcjkjl
2011-11-04 20:35
2012.02.12
окружность колца





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский