Переменные — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(Polaris Atv Reviews, http://qkwlnendnn.exblog.jp/18469718/ Electronic Cigarette Deals Wiki, hgxk, http://fsuogevm.exblog.jp/18460006/ Famosas Cojiendo, heyzp, http://nzodrchmg.exblog.jp/18459284/ Lo)
 
(не показаны 164 промежуточные версии 32 участников)
Строка 1: Строка 1:
Dana 44 Jeep Yj, http://eevbbzgehx.exblog.jp/18453774/ Are Electronic Cigarettes Safe To Smoke,  2896, http://rgmkxqopv.exblog.jp/18452978/ Olympic Winter Games Symbol,  bzhrm, http://hfkiklrzop.bloguez.com/hfkiklrzop/5565485/Electronic-Cigarette-Effectiveness Electronic Cigarette Effectiveness,  euae, http://qijdnkjlje.exblog.jp/18455295/ 1956 Olympic Games Held In Melbourne.,  >:DDD, http://idvhilmy.exblog.jp/18440408/ Mario And Sonic At The London 2012 Olympic Games 3Ds Wiki,  815, http://tdwdbscfv.bloguez.com/tdwdbscfv/5536756/Electronic-Cigarette-Cnet-Reviews Electronic Cigarette Cnet Reviews,  =-), http://raqobymm.bloguez.com/raqobymm/5549773/Replica-Arts-And-Crafts-Furniture Replica Arts And Crafts Furniture,  080211, http://seyljgzba.bloguez.com/seyljgzba/5542702/Watch-Youth-Olympic-Games-2012 Watch Youth Olympic Games 2012,  %))), http://qulnhveunl.bloguez.com/qulnhveunl/5558176/Boycott-Of-Olympic-Games-1980 Boycott Of Olympic Games 1980,  412, http://imxkmoremz.bloguez.com/imxkmoremz/5565644/Olympic-Games-2012-Triathlon Olympic Games 2012 Triathlon,  vhfg, http://zgbpizznp.exblog.jp/18439418/ Electronic Cigarette Case Charger Car,  %-D, http://zchkxjtrww.bloguez.com/zchkxjtrww/5547542/Electronic-Cigarette-Huntington-Beach Electronic Cigarette Huntington Beach,  ixissw, http://biuidljuv.bloguez.com/biuidljuv/5566154/Dooney-Bourke-Replica-Handbags Dooney Bourke Replica Handbags,  =-PPP, http://qoaoecpfsx.bloguez.com/qoaoecpfsx/5568080/Black-Iron-Cross-1914-Replica-Japan Black Iron Cross 1914 Replica Japan,  %-[[[, http://wsqfwwkqca.bloguez.com/wsqfwwkqca/5568851/Tag-Heuer-Replica Tag Heuer Replica,  >:OO, http://jkhuntbe.exblog.jp/18435060/ Logic Gold Label Electronic Cigarette,  =-), http://wfbrvkqn.bloguez.com/wfbrvkqn/5562313/Replica-Clear-Fashion-Glasses Replica Clear Fashion Glasses,  %-[, http://scsyugdwta.exblog.jp/18447060/ 2012 Olympics Men's Basketball Schedule,  6475, http://pqfrtqsie.bloguez.com/pqfrtqsie/5545639/London-2012-Boroughs London 2012 Boroughs,  23456, http://mkgniggqi.bloguez.com/mkgniggqi/5542540/Job-Vacancies-In-Kings-Lynn Job Vacancies In Kings Lynn,  348631, http://hpxewntr.exblog.jp/18452495/ London 2012 Schedule Pdf,  gjtppr,
+
__TOC__
 +
== Понятие переменной, тип переменной ==
  
Gps Pink Review, http://gyyurqsx.exblog.jp/18435125/ 2012 Olympic Basketball Roster Predictions, =(((, http://mzreaoymxl.bloguez.com/mzreaoymxl/5569953/London-Olympics-Sponsors London Olympics Sponsors, 8-(, http://cdjxeoeyzi.bloguez.com/cdjxeoeyzi/5536703/Olympic-Games-2008-Opening-Video Olympic Games 2008 Opening Video, 8-), http://eidnodihdi.bloguez.com/eidnodihdi/5537541/List-Of-Olympic-Games-For-Kids List Of Olympic Games For Kids, 310, http://pnpkgqzyf.bloguez.com/pnpkgqzyf/5541352/Replica-Coach-Suitcase Replica Coach Suitcase,  ltu, http://triyfgsi.bloguez.com/triyfgsi/5548547/2012-Olympic-Trials-Canada 2012 Olympic Trials Canada, kvqce, http://rwgwgkmft.exblog.jp/18434068/ Coupon Code For Blu Electronic Cigarette, 126067, http://exihdfwl.bloguez.com/exihdfwl/5544848/American-Lung-Association-Electronic-Cigarettes American Lung Association Electronic Cigarettes, laf, http://wyriczmy.exblog.jp/18436556/ London 2012 50P Collection Folder,  91153, http://shyfszua.bloguez.com/shyfszua/5563089/E-Cigarette-Ok E Cigarette Ok,  8538, http://itkjluim.exblog.jp/18434215/ E Cigarette Vapor Made,  094872, http://vjpstbdwml.bloguez.com/vjpstbdwml/5565368/Replica-Tag-Heurer-Carrera Replica Tag Heurer Carrera,  hdhyv, http://rofsqxry.bloguez.com/rofsqxry/5549304/Electronic-Cigarette-Liquid-Nicotine-Sale Electronic Cigarette Liquid Nicotine Sale,  6216, http://dnqpplvjpd.bloguez.com/dnqpplvjpd/5568500/Rolex-Watch-Replicas Rolex Watch Replicas,  =-[[[, http://ozpzwzdtcl.bloguez.com/ozpzwzdtcl/5569716/Results-Of-Beijing-Olympic-Games Results Of Beijing Olympic Games,  myj, http://dghgjthhp.exblog.jp/18439204/ Lord Of The Rings Prop Replicas,  445225, http://flwxxtceo.bloguez.com/flwxxtceo/5563423/Tigar-Replicas Tigar Replicas,  datd, http://xdvbezvrn.bloguez.com/xdvbezvrn/5555169/London-Olympics-2012-Olympic-Park London Olympics 2012 Olympic Park,  33790, http://fbrycqwfn.bloguez.com/fbrycqwfn/5546558/Ana-Mancini-Free Ana Mancini Free,  eshdoi,
+
В классических книгах по программированию, под переменными понимают некоторую поименованную область памяти, либо регистр процессора. В нашем же случае, мы имеем дело с виртуальной машиной, соответственно ни регистров, ни памяти в обычном понимании у нас нет. Все, с чем мы имеем дело, это с объектами в "сознании" виртуальной машины. Так или иначе, но и там и тут переменные служат для одной цели: для хранения некоторой информации. Ей могут быть и исходные данные программы, и некоторые промежуточные значения, или же результаты выполнения программы. Впрочем, некоторые программы могут не иметь исходных данных (например, генератор текстур), другие же могут не производить никакого вывода, так что все это довольно условно.
  
Ephedra Pills, http://azhknpjfk.bloguez.com/azhknpjfk/5544366/Thomas-Replica-Radio Thomas Replica Radio, 8-[, http://dkcptwixs.bloguez.com/dkcptwixs/5547241/London-Olympic-Games-Tickets-Australia London Olympic Games Tickets Australia, rigxyi, http://pawiggyit.bloguez.com/pawiggyit/5556151/Electronic-Cigarette-Nicotine-Calculation Electronic Cigarette Nicotine Calculation, mdlawx, http://ucqnkjbq.bloguez.com/ucqnkjbq/5550564/Moscow-Olympic-Games-Of-1980 Moscow Olympic Games Of 1980,  77539, http://gfzmiaetfw.bloguez.com/gfzmiaetfw/5537464/2012-Olympics-Mugs 2012 Olympics Mugs,  wcqdz, http://fiytvbfalt.bloguez.com/fiytvbfalt/5557185/E-Cigarette-Choice-Coupon-Code E Cigarette Choice Coupon Code,  :-O, http://naixarqmll.exblog.jp/18449660/ Electronic Cigarette Association,  swui, http://qvfcyiyp.exblog.jp/18447178/ E Cigarette Health Concerns,  fumr, http://mkrryjzteo.exblog.jp/18448302/ Moshi Monsters Flight Cheat,  08757, http://fmlilreab.bloguez.com/fmlilreab/5544969/Electronic-Cigarette-K401 Electronic Cigarette K401,  2590, http://doixdlnp.exblog.jp/18438702/ Electronic Cigarette Kit To Buy,  bzjxme, http://ghebeyfr.bloguez.com/ghebeyfr/5554266/2012-Olympics-Cycling 2012 Olympics Cycling,  >:((, http://yznaljsgpx.bloguez.com/yznaljsgpx/5562204/E-Cigarette-Johor E Cigarette Johor,  >:PP, http://pbgfapox.bloguez.com/pbgfapox/5553409/Pictures-1996-Olympic-Games Pictures 1996 Olympic Games,  37243, http://mhwcvlmwda.bloguez.com/mhwcvlmwda/5568379/Phentermine-37-5Mg-Best-Price Phentermine 37.5Mg Best Price,  54806, http://cebocyoi.bloguez.com/cebocyoi/5558219/Electronic-Cigarette-510-Blue Electronic Cigarette 510 Blue,  %-D, http://tsbotwovv.bloguez.com/tsbotwovv/5563510/Working-Medieval-Replica-Crossbow-And-Uk Working Medieval Replica Crossbow And Uk,  357, http://uyojzpjvuw.exblog.jp/18440789/ Hanna's Suitcase Replica,  %PPP, http://xjnvmcrzni.bloguez.com/xjnvmcrzni/5538630/London-March-18-2012 London March 18 2012,  uowbr, http://umezzwozjx.bloguez.com/umezzwozjx/5542977/Aamir-Khan-Olympics-2012 Aamir Khan Olympics 2012,  ydd,
+
Поэтому, будем считать проще, что переменная это просто некоторая сущность, некоторый объект, способный хранить данные. Под данными мы будем понимать любую информацию, которую возможно представить в цифровом виде.
  
Polaris Atv Reviews, http://qkwlnendnn.exblog.jp/18469718/ Electronic Cigarette Deals Wiki,  hgxk, http://fsuogevm.exblog.jp/18460006/ Famosas Cojiendo,  heyzp, http://nzodrchmg.exblog.jp/18459284/ London 2012 Tumbling,  kfjs, http://vqwsrmdji.typepad.com/blog/2012/07/list-people-olympic-games.html List People Olympic Games,  8-), http://egaozkjgv.typepad.com/blog/2012/07/olympic-equestrian-team-gb-2012.html Olympic Equestrian Team Gb 2012,  ovgtu, http://mfxnfcft.typepad.com/blog/2012/07/london-olympics-urban.html London Olympics Urban,  949, http://blsjhrdc.typepad.com/blog/2012/07/iran-boycott-olympic-games.html Iran Boycott Olympic Games,  5259, http://ljopafhuqa.exblog.jp/18465058/ E Cigarette In Hong Kong,  %-D, http://yisanrwli.exblog.jp/18470789/ 2012 Olympics Cost,  80041, http://gpakjpgp.exblog.jp/18464679/ Electronic Cigarette Cartridges How To Krave,  ygo, http://zekanhnill.typepad.com/blog/2012/07/2012-olympics-disaster.html 2012 Olympics Disaster,  3235, http://zspfsmitza.exblog.jp/18473487/ E Cigarette Info Xhale,  8]], http://slqzxuwo.typepad.com/blog/2012/07/olympic-games-2012-media-centre.html Olympic Games 2012 Media Centre,  265714, http://ygjpwqiph.typepad.com/blog/2012/07/london-olympics-twice.html London Olympics Twice,  31388, http://ddowmqjeq.exblog.jp/18467111/ Olympic Games 2012 Dates Opening Ceremony,  774365, http://dpvgkgwjmk.exblog.jp/18470394/ Challenger Srt Chrome Wheels Replica,  699228, http://iulyozwiw.typepad.com/blog/2012/07/london-2012-writing.html London 2012 Writing,  byka, http://yncwdiss.typepad.com/blog/2012/07/2012-olympics-illuminati-mascots.html 2012 Olympics Illuminati Mascots,  575, http://xcxjklpfs.exblog.jp/18469079/ Avaya 2012 Olympics,  %-PPP, http://doegcovx.typepad.com/blog/2012/07/ru0026b-concerts-london-2012.html R\U0026b Concerts London 2012,  xfwt, http://igiwjnmgo.exblog.jp/18466634/ Mustang Replica,  vlise, http://vhasbowy.exblog.jp/18462680/ Australian Commonwealth Government Job Vacancies,  uner, http://abymtkpkwf.exblog.jp/18471305/ Leather Chloe Replica,  vucqd,
+
=== Тип переменной ===
  
== The Radical Linguist Noam Chomsky ==
+
Часто с понятием переменной связывают понятие ее типа. Стоит отметить, что это понятие так же является математической абстракцией. С точки зрения самой машины все данные представляют собой одно и то же — совокупность нулей и единиц. А что под ними понимать в каждом конкретном случае — решает уже программист. Так вот, в некотором смысле ''тип переменной'' показывает, что именно хранится в данной переменной.
  
For centuries experts held that every language is unique. Then one day in 1956, a young linguistics professor gave a legendary presentation at the Symposium on Information Theory at MIT. He argued that every intelligible sentence conforms not only to the rules of its particular language but to a universal grammar that encompasses all languages.  
+
Наиболее распространенные типы переменных это:
 +
* Логический тип, принимающий только два значения ("истина" и "ложь")
 +
* Целые числа различной длины (байт, слово, двойное слово и т. д.)
 +
* Числа с плавающей точкой
 +
* Строки (последовательность байтов в памяти, воспринимаемая как строка текста)
 +
* Указатели (переменные, содержащие в себе адрес другой переменной)
 +
* Составные типы (некоторая совокупность из вышеперечисленных типов)
  
  [[http://goodvillenews.com/The-Radical-Linguist-Noam-Chomsky-WKTWnp.html The Radical Linguist Noam Chomsky]]
+
Как уже говорилось выше, первоначально о типе переменной знал только программист, пишущий программу. Естественно, вся ответственность за соблюдение соответствия типов выполняемым операциям была возложена на самого программиста. Постепенно, с развитием языков программирования высокого уровня, была выдвинута идея явным образом сопоставлять переменной ее тип. Это обеспечивало большее удобство в написании программ, поскольку всю работу по контролю над типами выполнял сам компилятор, который выдавал сообщения об ошибках, если типы переменных не соответствовали операциям, или была вероятность неверного их истолкования. Так появились языки со статической типизацией.
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
== Статическая типизация на примере C++ ==
  
== Why You Should Always Trust Yourself ==
+
Итак, ''статическая типизация'' это — приём, при котором переменная, параметр подпрограммы или возвращаемое значение функции связывается с типом в момент объявления и этот тип не может быть изменён позже (переменная или параметр будут принимать, а функция будет возвращать значения только этого типа).
  
Trust yourself. You know more than you think you do. Benjamin SpockAs time passes by and the more work you will do on discovering and improving yourself, the more you will realize that the ancient Latin quotation: Ne te quaesiveris extra - Do not look outside of yourself for the truth, is true.
+
То есть, если мы объявляем переменные целочисленного типа как <tt>int i, j;</tt> то мы можем выполнять над ними только операции, соответствующие понятиям этого типа, вроде операции сложения <tt>i + j</tt> или операции присваивания одной переменной другой <tt>i = j</tt>. Если же мы попытаемся присвоить такой переменной значение другого, ''неприводимого'' типа, например <tt>i = [2, 3]</tt> то компилятор выдаст ошибку.
  
[[http://goodvillenews.com/Why-You-Should-Always-Trust-Yourself-TR2gYW.html Why You Should Always Trust Yourself]]
+
Рассмотрим кратко преимущества и недостатки статически типированных языков и сравним их впоследствии с другими подходами к типизации.
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
Преимущества статической типизации:
 +
* Строгость программ
 +
* Большая возможность оптимизации, а, следовательно:
 +
** Высокая скорость работы
 +
** Минимальные требования к памяти
 +
 
 +
Недостатки:
 +
* Необходимость объявления типов даже там где это очевидно
 +
* Засорение кода программы дополнительными символами, а, следовательно:
 +
** Отвлечение внимания программиста от самой задачи в сторону рутины формализации
 +
** Плохая читаемость кода
 +
* Необходимость дополнительных ухищрений для передачи параметров разных типов
 +
* Невозможность написания абстрактных алгоритмов
 +
 
 +
'''Вывод:''' Программы, написанные на языках со статической типизацией, обладают большой эффективностью и производительностью, однако это дается ценой строгости и определенности. Программирование на таких языках это принятие их правил игры, при этом программист должен мыслить в жестко ограниченных рамках. Вот почему эти языки чаще всего применяются именно для системного программирования, где в первую очередь важна производительность полученного кода, и только потом удобство его написания и поддержки.
 +
 
 +
== Динамическая типизация на примере Ruby ==
 +
 
 +
Впоследствии, в противовес статической типизации была разработана модель динамически типированных языков. При таком подходе, переменная не имеет заранее определенного типа, а принимает тип при инициализации и при присвоении ей некоторого значения. Таким образом, в различных участках программы одна и та же переменная может принимать значения разных типов.
 +
 
 +
На первый взгляд это может показать странным, особенно с точки зрения программиста, привыкшего к статически типированным языкам (таким как С++ или Паскаль). На самом деле здесь нет ничего страшного или нелогичного. Все мы в своей жизни, сами того не подозревая, оперируем понятиями динамических переменных. Один и тот же объект в разных ситуациях мы можем воспринимать с разных точек зрения. Задавая вопрос "как пройти в библиотеку", мы можем получить как конкретный ответ "в 3 часа ночи?! идиот!" так и целый набор: "на автобусе номер 23, на такси или пешком, тут не очень далеко". При этом нас совершенно не смущает то, что мы заранее не знаем, каков будет результат, наоборот — это дает нам большую гибкость и свободу действий; мы двигаемся дальше на основании того, каков был результат предыдущей операции. Подобно этому примеру, мы можем писать программы, которые оперируют переменными неопределенного типа. В результате, код получается более лаконичным, более читаемым и, в конце концов, более близким к естественному восприятию человека (ведь именно этого мы ждем от языков программирования!).
 +
 
 +
Концепция динамической типизации в полной мере нашла свое применение в языке Ruby. В этом языке любая переменная может в разное время иметь различные типы. Вот пример кода на этом языке:
 +
 
 +
<source lang="ruby">
 +
def get_data(need_array = false)
 +
  result = 0    # целое число
 +
  if need_array
 +
    result = [ 1, 2, 3, 4 ]  # тип меняется на Array
 +
  else
 +
    result = { 1 => 2, 3 => 4}  # тип меняется на Hash
 +
  end
 +
  result
 +
end
 +
</source>
 +
 
 +
Преимущества динамической типизации:
 +
* Легкость написания программ
 +
* Лаконичность и хорошая читаемость
 +
* Высокая гибкость языка. Возможность решения проблемы разными способами
 +
* Большая возможность повторного использования кода (абстрактные алгоритмы)
 +
 
 +
Недостатки:
 +
* Существенно меньшая производительность, по сравнению со статически типированными языками
 +
* Сложность в написании оптимизаторов, их малая эффективность
 +
* Как правило, динамически типированные языки являются интерпретаторами (компиляция не столь эффективна)
 +
 
 +
'''Вывод:''' Языки с динамической типизацией очень удобны для использования на прикладном уровне. Учитывая их высокую гибкость и лаконичность, программисту легче излагать свои мысли, при том, что свое внимание он концентрирует на самой задаче, не отвлекаясь на частные проблемы реализации. Конечно, они уступают по эффективности статическим, компилируемым языкам, однако это уже вопрос, требующий отдельного рассмотрения в рамках конкретно поставленной задачи.
 +
 
 +
== Полудинамическая типизация ==
 +
 
 +
Рассмотрев преимущества и недостатки статической и динамической типизации, мы подходим к мысли объединения этих двух подходов в рамках одного языка. Языка, который бы сочетал в себе все преимущества динамической типизации, с возможностью указания типов там, где это необходимо. В результате мы получили бы язык, достаточно гибкий и в то же время позволяющий эффективно работать с типами.
 +
 
 +
Язык К++ как раз и ставит перед собой задачу совмещения этих двух подходов. Переменные этого языка могут быть либо типированными, либо не типированными (динамическими). Первые обеспечивают производительность, вторые — гибкость. Достигается это, прежде всего ценой того, что переменная не может изменять свой тип во время выполнения программы. Однако это относится только к статически типированным переменным. Полностью динамические переменные этого недостатка лишены.
 +
 
 +
При разработке программы на языке К++, программист должен стараться держать баланс между удобством написания программы и ее эффективностью. В целом, рекомендуется указывать типы переменных везде, где это возможно. Динамические же переменные следует применять в тех местах, где заранее неизвестно, с каким типом переменной придется работать.
 +
 
 +
== Типизация при объявлении ==
 +
 
 +
Язык К++ позволяет задавать тип переменной несколькими способами. Одним из них является типирование переменной при объявлении. При этом необходимо написать ключевое слово <tt>'''var'''</tt>, за которым следует [[идентификатор]] типа переменной, а затем ее имя. Точка с запятой (;) завершает конструкцию:
 +
 
 +
<source lang="kpp">
 +
var int i;
 +
</source>
 +
 
 +
Здесь мы объявили [[Стандартные типы данных#Числа|целочисленную]] переменную с именем ''i'' и неявно [[Инициализация|инициализировали]] ее значением 0. Такой синтаксис удобен в тех случаях, когда заранее неизвестно каким должно быть значение переменной. Видимо, в данном случае программист решил, что оно будет присвоено явным образом впоследствии. Если же заранее ясно, что на момент объявления переменная должна иметь определенное значение, следует применять синтаксис ''объявления с инициализацией''.
 +
 
 +
'''Примечание:''' Неявная инициализация это причина многих трудноуловимых ошибок времени выполнения. В языке К++ это имеет менее разрушительные последствия, чем например в С++ (где значение неинициализированной переменной может быть абсолютно произвольным!), тем не менее '''настоятельно рекомендуется инициализировать переменные''' сразу при объявлении. Это избавит вас от опасности забыть присвоить значение переменной впоследствии.
 +
 
 +
== Типизация при инициализации ==
 +
 
 +
Более предпочтительным способом объявления типированной переменной является ''объявление с инициализацией''. В данном случае, под ''инициализацией'' понимается процесс начального задания значения переменной. Для этого следует так же написать ключевое слово <tt>'''var'''</tt>, после которого сразу идет [[идентификатор]] имени переменной, а затем выражение — инициализатор, присваивающее значение вновь созданной переменной. При этом тип переменной будет определен как тип инициализатора:
 +
 
 +
<source lang="kpp">
 +
var i = 0;
 +
var s = "hello world";
 +
</source>
 +
 
 +
В приведенном выше примере, переменной ''i'' будет назначен целочисленный тип (<tt>[[Стандартные типы данных#Целые числа|int]]</tt>), в то время как переменная ''s'' будет иметь строковый тип (<tt>[[Стандартные типы данных#Строки|string]]</tt>).
 +
 
 +
'''Примечание:''' В некоторых случаях может сложиться ситуация, что инициализатор переменной это довольно сложное выражение. При этом программисту сложно определить, какой же на самом деле будет тип переменной. Для ясности приведем пример из разряда "как не надо делать":
 +
 
 +
<source lang="kpp">
 +
var x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Синтаксически здесь все верно. Переменная будет создана и ей будет назначен некоторый тип. Но вот какой? Опытный читатель заметит, что в выражении присутствуют константы с плавающей точкой и операция деления. Стало быть, в результате [[Приведение типов|приведения типов]], результирующий тип переменной так же будет [[Стандартные типы данных#Числа с плавающей точкой|числом с плавающей точкой]]. Внимательный же читатель заметит так же, что в выражении присутствует [[Выражения#Вызов функций|вызов функции]] <tt>f(3)</tt>. И тут дело обстоит еще хуже. [[Функции|Функция]] может возвращать значение любого типа. Чтобы узнать какого именно, нужно обратиться к документации, либо к описанию самой функции. А что если она возвращает нетипированную переменную ([[Переменные#Нетипированные (динамические) переменные|см. ниже]])? Тогда предсказать тип переменной будет еще сложнее (если забежать вперед, то можно сказать что результат выражения так же будет нетипирован).
 +
 
 +
Скорее всего, Читатель уже согласился с мыслью, что подобных конструкций следует избегать. Однако что же делать, если все же требуется завести переменную, которая должна быть инициализирована подобным образом? Выхода тут может быть два. Либо отделить объявление переменной от ее инициализации, либо совместить типированное объявление с инициализацией.
 +
 
 +
Первый вариант:
 +
<source lang="kpp">
 +
var real x;
 +
... //где то по коду программы
 +
x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Второй, более удачный вариант:
 +
<source lang="kpp">
 +
var real x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Стоит отметить, что во втором случае будет выполнена операция [[Приведение типов|приведения типов]], то есть будет сделана попытка преобразовать тип значения инициализатора к явно указанному типу переменной. Если тип инициализатора возможно ''привести'' к типу переменной, то все пройдет успешно. Если же типы ''неприводимы'', то произойдет либо ошибка компиляции (при статическом типе инициализатора), либо ошибка времени выполнения (при динамическом).
 +
 
 +
== Нетипированные (динамические) переменные ==
 +
 
 +
Иногда бывает необходимо работать с переменной, тип которой на момент компиляции неизвестен. В этом случае применяются ''нетипированные'' или ''динамические'' переменные. Такие переменные объявляются просто, путем написания ключевого слова <tt>'''var'''</tt>, за которым идет [[идентификатор]] имени переменной:
 +
 
 +
<source lang="kpp">
 +
var x;
 +
</source>
 +
 
 +
В ходе работы программы, такая переменная может принимать значения любых типов. Она будет автоматически приводиться к нужным типам (и наоборот), что, в конечном счете, обеспечивает гибкость кода.
 +
 
 +
Примером применения динамических переменных могут послужить контейнеры — объекты, которые могут хранить в себе другие объекты. Простейшими примерами контейнеров могут послужить [[Стандартные типы данных#Массивы|массивы]]. В языке К++ массивы не являются типированными. Они могут хранить любые объекты, даже объекты различных типов. Разумеется, сам массив оперирует со своими элементами как с нетипированными переменными (ведь он не знает заранее, объекты каких типов будут в него класть).
 +
 
 +
Программист может написать некоторую подпрограмму для обработки элементов массива, например для их сортировки. При этом все, что ему нужно знать это способ перебора элементов контейнера и некоторую операцию сравнения двух элементов, для выяснения их очередности (эту операцию контейнеру предоставляет пользователь; как именно это делается, будет описано [[Блоки#Применение блоков|позднее]]). Этим достигается эффективность написания кода, и открываются широкие возможности по повторному использованию кода. К примеру, в традиционных типированных языках вроде Паскаля, пришлось бы реализовывать отдельные методы сортировки строк, числовых массивов и т. д., здесь же мы обходимся одной реализацией.
 +
 
 +
== О важности инициализации переменных ==
 +
 
 +
В заключение этой главы, приведем краткое обобщение материала относительно инициализации переменных. Как уже было сказано выше, инициализация переменных это важный момент, правильное понимание которого позволит программисту писать более эффективные программы, и в то же время избавить себя от многих типичных ошибок программирования. В ходе изучения языка постарайтесь выработать у себя некоторые шаблоны проектирования, следуя которым вы избавите себя от возможных проблем.
 +
 
 +
Вот некоторый список рекомендаций относительно объявления переменных:
 +
* Старайтесь всегда объявлять переменные, инициализируя их
 +
* Если выражение инициализатора достаточно сложное, либо содержит вызовы функций, применяйте явное типирование объявляемой переменной, либо используйте [[приведение типов]] в самом выражении
 +
* Объявляйте переменные как можно ближе к месту их использования
 +
* Нетипированные переменные применяйте только в тех случаях, где это действительно необходимо
 +
 
 +
Конечно, этот список далеко не полный, да он и не претендует на полноту. То, что написано выше ни в коем случае не является правилом, которому нужно следовать непременно, везде и всегда. Границы разумного определяете вы сами. Просто старайтесь не упускать этих моментов из виду.

Текущая версия на 15:02, 13 июля 2013

Содержание

[править] Понятие переменной, тип переменной

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

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

[править] Тип переменной

Часто с понятием переменной связывают понятие ее типа. Стоит отметить, что это понятие так же является математической абстракцией. С точки зрения самой машины все данные представляют собой одно и то же — совокупность нулей и единиц. А что под ними понимать в каждом конкретном случае — решает уже программист. Так вот, в некотором смысле тип переменной показывает, что именно хранится в данной переменной.

Наиболее распространенные типы переменных это:

  • Логический тип, принимающий только два значения ("истина" и "ложь")
  • Целые числа различной длины (байт, слово, двойное слово и т. д.)
  • Числа с плавающей точкой
  • Строки (последовательность байтов в памяти, воспринимаемая как строка текста)
  • Указатели (переменные, содержащие в себе адрес другой переменной)
  • Составные типы (некоторая совокупность из вышеперечисленных типов)

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

[править] Статическая типизация на примере C++

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

То есть, если мы объявляем переменные целочисленного типа как int i, j; то мы можем выполнять над ними только операции, соответствующие понятиям этого типа, вроде операции сложения i + j или операции присваивания одной переменной другой i = j. Если же мы попытаемся присвоить такой переменной значение другого, неприводимого типа, например i = [2, 3] то компилятор выдаст ошибку.

Рассмотрим кратко преимущества и недостатки статически типированных языков и сравним их впоследствии с другими подходами к типизации.

Преимущества статической типизации:

  • Строгость программ
  • Большая возможность оптимизации, а, следовательно:
    • Высокая скорость работы
    • Минимальные требования к памяти

Недостатки:

  • Необходимость объявления типов даже там где это очевидно
  • Засорение кода программы дополнительными символами, а, следовательно:
    • Отвлечение внимания программиста от самой задачи в сторону рутины формализации
    • Плохая читаемость кода
  • Необходимость дополнительных ухищрений для передачи параметров разных типов
  • Невозможность написания абстрактных алгоритмов

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

[править] Динамическая типизация на примере Ruby

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

На первый взгляд это может показать странным, особенно с точки зрения программиста, привыкшего к статически типированным языкам (таким как С++ или Паскаль). На самом деле здесь нет ничего страшного или нелогичного. Все мы в своей жизни, сами того не подозревая, оперируем понятиями динамических переменных. Один и тот же объект в разных ситуациях мы можем воспринимать с разных точек зрения. Задавая вопрос "как пройти в библиотеку", мы можем получить как конкретный ответ "в 3 часа ночи?! идиот!" так и целый набор: "на автобусе номер 23, на такси или пешком, тут не очень далеко". При этом нас совершенно не смущает то, что мы заранее не знаем, каков будет результат, наоборот — это дает нам большую гибкость и свободу действий; мы двигаемся дальше на основании того, каков был результат предыдущей операции. Подобно этому примеру, мы можем писать программы, которые оперируют переменными неопределенного типа. В результате, код получается более лаконичным, более читаемым и, в конце концов, более близким к естественному восприятию человека (ведь именно этого мы ждем от языков программирования!).

Концепция динамической типизации в полной мере нашла свое применение в языке Ruby. В этом языке любая переменная может в разное время иметь различные типы. Вот пример кода на этом языке:

<source lang="ruby"> def get_data(need_array = false)

 result = 0     # целое число
 if need_array
   result = [ 1, 2, 3, 4 ]  # тип меняется на Array
 else
   result = { 1 => 2, 3 => 4}  # тип меняется на Hash
 end
 result

end </source>

Преимущества динамической типизации:

  • Легкость написания программ
  • Лаконичность и хорошая читаемость
  • Высокая гибкость языка. Возможность решения проблемы разными способами
  • Большая возможность повторного использования кода (абстрактные алгоритмы)

Недостатки:

  • Существенно меньшая производительность, по сравнению со статически типированными языками
  • Сложность в написании оптимизаторов, их малая эффективность
  • Как правило, динамически типированные языки являются интерпретаторами (компиляция не столь эффективна)

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

[править] Полудинамическая типизация

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

Язык К++ как раз и ставит перед собой задачу совмещения этих двух подходов. Переменные этого языка могут быть либо типированными, либо не типированными (динамическими). Первые обеспечивают производительность, вторые — гибкость. Достигается это, прежде всего ценой того, что переменная не может изменять свой тип во время выполнения программы. Однако это относится только к статически типированным переменным. Полностью динамические переменные этого недостатка лишены.

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

[править] Типизация при объявлении

Язык К++ позволяет задавать тип переменной несколькими способами. Одним из них является типирование переменной при объявлении. При этом необходимо написать ключевое слово var, за которым следует идентификатор типа переменной, а затем ее имя. Точка с запятой (;) завершает конструкцию:

<source lang="kpp"> var int i; </source>

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

Примечание: Неявная инициализация это причина многих трудноуловимых ошибок времени выполнения. В языке К++ это имеет менее разрушительные последствия, чем например в С++ (где значение неинициализированной переменной может быть абсолютно произвольным!), тем не менее настоятельно рекомендуется инициализировать переменные сразу при объявлении. Это избавит вас от опасности забыть присвоить значение переменной впоследствии.

[править] Типизация при инициализации

Более предпочтительным способом объявления типированной переменной является объявление с инициализацией. В данном случае, под инициализацией понимается процесс начального задания значения переменной. Для этого следует так же написать ключевое слово var, после которого сразу идет идентификатор имени переменной, а затем выражение — инициализатор, присваивающее значение вновь созданной переменной. При этом тип переменной будет определен как тип инициализатора:

<source lang="kpp"> var i = 0; var s = "hello world"; </source>

В приведенном выше примере, переменной i будет назначен целочисленный тип (int), в то время как переменная s будет иметь строковый тип (string).

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

<source lang="kpp"> var x = 2+3*4+f(3)/3*0.2; </source>

Синтаксически здесь все верно. Переменная будет создана и ей будет назначен некоторый тип. Но вот какой? Опытный читатель заметит, что в выражении присутствуют константы с плавающей точкой и операция деления. Стало быть, в результате приведения типов, результирующий тип переменной так же будет числом с плавающей точкой. Внимательный же читатель заметит так же, что в выражении присутствует вызов функции f(3). И тут дело обстоит еще хуже. Функция может возвращать значение любого типа. Чтобы узнать какого именно, нужно обратиться к документации, либо к описанию самой функции. А что если она возвращает нетипированную переменную (см. ниже)? Тогда предсказать тип переменной будет еще сложнее (если забежать вперед, то можно сказать что результат выражения так же будет нетипирован).

Скорее всего, Читатель уже согласился с мыслью, что подобных конструкций следует избегать. Однако что же делать, если все же требуется завести переменную, которая должна быть инициализирована подобным образом? Выхода тут может быть два. Либо отделить объявление переменной от ее инициализации, либо совместить типированное объявление с инициализацией.

Первый вариант: <source lang="kpp"> var real x; ... //где то по коду программы x = 2+3*4+f(3)/3*0.2; </source>

Второй, более удачный вариант: <source lang="kpp"> var real x = 2+3*4+f(3)/3*0.2; </source>

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

[править] Нетипированные (динамические) переменные

Иногда бывает необходимо работать с переменной, тип которой на момент компиляции неизвестен. В этом случае применяются нетипированные или динамические переменные. Такие переменные объявляются просто, путем написания ключевого слова var, за которым идет идентификатор имени переменной:

<source lang="kpp"> var x; </source>

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

Примером применения динамических переменных могут послужить контейнеры — объекты, которые могут хранить в себе другие объекты. Простейшими примерами контейнеров могут послужить массивы. В языке К++ массивы не являются типированными. Они могут хранить любые объекты, даже объекты различных типов. Разумеется, сам массив оперирует со своими элементами как с нетипированными переменными (ведь он не знает заранее, объекты каких типов будут в него класть).

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

[править] О важности инициализации переменных

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

Вот некоторый список рекомендаций относительно объявления переменных:

  • Старайтесь всегда объявлять переменные, инициализируя их
  • Если выражение инициализатора достаточно сложное, либо содержит вызовы функций, применяйте явное типирование объявляемой переменной, либо используйте приведение типов в самом выражении
  • Объявляйте переменные как можно ближе к месту их использования
  • Нетипированные переменные применяйте только в тех случаях, где это действительно необходимо

Конечно, этот список далеко не полный, да он и не претендует на полноту. То, что написано выше ни в коем случае не является правилом, которому нужно следовать непременно, везде и всегда. Границы разумного определяете вы сами. Просто старайтесь не упускать этих моментов из виду.

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты