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

Материал из Deeptown Manual
Перейти к: навигация, поиск
(Bmw 325Xi Lease, http://pwwdqcvz.bloguez.com/pwwdqcvz/5523070/Christian-Louboutin-Replica-Shoes Christian Louboutin Replica Shoes, 8958, http://jjvkmgnuao.blogger.hu/2012/07/22/london-2012-environmen)
 
(не показаны 178 промежуточных версий 36 участников)
Строка 1: Строка 1:
 
__TOC__
 
__TOC__
svUZeJ  <a href="http://uyxnwekuxamm.com/">uyxnwekuxamm</a>, [url=http://pbszeqhhnnnt.com/]pbszeqhhnnnt[/url], [link=http://omlneqivybqs.com/]omlneqivybqs[/link], http://lwabxnxcbsrf.com/
+
== Понятие переменной, тип переменной ==
  
Suzuki Gs1000, http://www.alreadyfamouslive.com/blog/view/27720/electronic-cigarette-negative-effects Electronic Cigarette Negative Effects, 4697, http://www.alreadyfamouslive.com/blog/view/29642/electronic-cigarette-buy-manila Electronic Cigarette Buy Manila, 06717, http://www.alreadyfamouslive.com/blog/view/29548/life-form-fat-replica Life Form Fat Replica, 570802, http://www.alreadyfamouslive.com/blog/view/28541/beanpot-trophy-replica Beanpot Trophy Replica, 6753, http://www.alreadyfamouslive.com/blog/view/29246/tubular-chassis-replica Tubular Chassis Replica,  hcaa, http://www.alreadyfamouslive.com/blog/view/27547/replica-coach-purses-for-sale Replica Coach Purses For Sale, mlyw, http://www.alreadyfamouslive.com/blog/view/27562/antique-statue-replica Antique Statue Replica, =-[[[, http://www.alreadyfamouslive.com/blog/view/28592/cyprus-job-vacancies Cyprus Job Vacancies, spojm, http://www.alreadyfamouslive.com/blog/view/28641/electronic-cigarette-lafayette-la Electronic Cigarette Lafayette La,  mgp, http://www.alreadyfamouslive.com/blog/view/28890/spear-of-destiny-replica Spear Of Destiny Replica,  cyssoc, http://www.alreadyfamouslive.com/blog/view/27480/e-cigarette-murfreesboro E Cigarette Murfreesboro,  %-OOO, http://www.alreadyfamouslive.com/blog/view/27787/electronic-cigarette-on-sale-houston Electronic Cigarette On Sale Houston,  aij, http://www.alreadyfamouslive.com/blog/view/27740/master-replicas-sw108 Master Replicas Sw108,  %PP, http://www.alreadyfamouslive.com/blog/view/28379/e-cigarette-online-australia E Cigarette Online Australia,  8-], http://www.alreadyfamouslive.com/blog/view/28387/microphone-replicas Microphone Replicas,  %-PPP, http://www.alreadyfamouslive.com/blog/view/27468/glock-airsoft-replica Glock Airsoft Replica,  oqc, http://www.alreadyfamouslive.com/blog/view/29303/reduce-gum-swelling Reduce Gum Swelling,  ekzlb, http://www.alreadyfamouslive.com/blog/view/28226/replica-swiss Replica Swiss,  >:]]], http://www.alreadyfamouslive.com/blog/view/27712/electronic-cigarette-with-flavor-drops Electronic Cigarette With Flavor Drops,  >:OO, http://www.alreadyfamouslive.com/blog/view/29109/best-electronic-cigarette-of-2012-groupon Best Electronic Cigarette Of 2012 Groupon,  >:PPP, http://www.alreadyfamouslive.com/blog/view/28377/neyland-stadium-replica Neyland Stadium Replica,  139, http://www.alreadyfamouslive.com/blog/view/28192/ford-truck-16-steel-replica-rims Ford Truck 16 Steel Replica Rims,  oqwlgo, http://www.alreadyfamouslive.com/blog/view/28508/noahs-ark-replica-kit Noahs Ark Replica Kit,  >:),
+
В классических книгах по программированию, под переменными понимают некоторую поименованную область памяти, либо регистр процессора. В нашем же случае, мы имеем дело с виртуальной машиной, соответственно ни регистров, ни памяти в обычном понимании у нас нет. Все, с чем мы имеем дело, это с объектами в "сознании" виртуальной машины. Так или иначе, но и там и тут переменные служат для одной цели: для хранения некоторой информации. Ей могут быть и исходные данные программы, и некоторые промежуточные значения, или же результаты выполнения программы. Впрочем, некоторые программы могут не иметь исходных данных (например, генератор текстур), другие же могут не производить никакого вывода, так что все это довольно условно.
  
Zhu Zhu Babies, http://jccrpnicb.bloguez.com/jccrpnicb/5519798/Replica-Vette-Body Replica Vette Body, kpq, http://qyinzssbfr.bloguez.com/qyinzssbfr/5523541/Tag-Heuer-Swiss-Replicas Tag Heuer Swiss Replicas, 8P, http://lejjghawc.bloguez.com/lejjghawc/5528331/Joye-Electronic-Cigarette-Review Joye Electronic Cigarette Review, xpmcvn, http://bdkavbxajx.bloguez.com/bdkavbxajx/5528931/Napco-Siding-World Napco Siding World,  188, http://qctvslmtp.bloguez.com/qctvslmtp/5524932/Replica-Red Replica Red,  lshdm, http://hurlccmad.bloguez.com/hurlccmad/5525350/Discounted-Rolex-Replicas-With-Free-Shipping Discounted Rolex Replicas With Free Shipping,  %-O, http://dcafrfvfpf.bloguez.com/dcafrfvfpf/5527274/Jobs-Detroit-Vacancies-Michigan-Nurse-Practitioner Jobs Detroit Vacancies Michigan Nurse Practitioner,  dba, http://bzqmmytq.bloguez.com/bzqmmytq/5527452/Graphite-Fish-Replica Graphite Fish Replica,  7029, http://owhumqomk.blogger.hu/2012/07/22/olympic-games-2016-lula Olympic Games 2016 Lula,  8-[[[, http://rpmxzzxaa.bloguez.com/rpmxzzxaa/5526364/E-Cigarette-Myths E Cigarette Myths,  7693, http://rbknfpvqen.blogger.hu/2012/07/22/android-spaghetti-marshmallow-cheat Android Spaghetti Marshmallow Cheat,  469, http://bmssgwqqz.bloguez.com/bmssgwqqz/5519389/Estudiante-Cojiendo Estudiante Cojiendo,  out, http://sicmxcanh.bloguez.com/sicmxcanh/5532848/Louie-Vouton-Replica-Bags Louie Vouton Replica Bags,  %[, http://ewsqcvichn.blogger.hu/2012/07/22/view-tube-olympics-london View Tube Olympics London,  >:-], http://pkdtvcyb.blogger.hu/2012/07/22/neice-quotes Neice Quotes,  :DDD, http://ddowdehzou.bloguez.com/ddowdehzou/5531084/Kirkham-Replicas Kirkham Replicas,  ztucjx, http://bzgaijbho.bloguez.com/bzgaijbho/5519541/Job-Vacancies-In-Wolverhampton Job Vacancies In Wolverhampton,  =-[[, http://dgxpenee.blogger.hu/2012/07/22/2012-olympics-citizenship 2012 Olympics Citizenship,  =-], http://iliedykwz.blogger.hu/2012/07/22/vancouver-olympic-games-opening-ceremony-video Vancouver Olympic Games Opening Ceremony Video,  hrxyfj, http://jwtuxikb.bloguez.com/jwtuxikb/5522266/Electronic-Cigarette-Marijuana Electronic Cigarette Marijuana,  47136, http://xyndbnidiz.blogger.hu/2012/07/22/where-can-i-find-icarly-fakes Where Can I Find Icarly Fakes,  xlq, http://lizjskhw.bloguez.com/lizjskhw/5526558/Build-A-Laverda-750-Sfc-Replica Build A Laverda 750 Sfc Replica,  8-PP, http://pymxflvzn.bloguez.com/pymxflvzn/5528507/E-Cigarette-Menthol-Juice E Cigarette Menthol Juice,  =)),
+
Поэтому, будем считать проще, что переменная это просто некоторая сущность, некоторый объект, способный хранить данные. Под данными мы будем понимать любую информацию, которую возможно представить в цифровом виде.
  
Bmw 325Xi Lease, http://pwwdqcvz.bloguez.com/pwwdqcvz/5523070/Christian-Louboutin-Replica-Shoes Christian Louboutin Replica Shoes,  8958, http://jjvkmgnuao.blogger.hu/2012/07/22/london-2012-environmental London 2012 Environmental,  cxzm, http://tmszldmqz.blogger.hu/2012/07/22/olympic-games-2014-logo Olympic Games 2014 Logo,  yav, http://tuntchvurv.bloguez.com/tuntchvurv/5523397/Electronic-Cigarette-Buy-510-Tank Electronic Cigarette Buy 510 Tank,  msx, http://ykmkajbx.blogger.hu/2012/07/22/chanel-cc-boyfriend Chanel Cc Boyfriend,  986, http://opxxupmu.bloguez.com/opxxupmu/5524848/Rachel-Steele-Videos-Online Rachel Steele Videos Online,  %-((, http://krrjnrsvxn.bloguez.com/krrjnrsvxn/5533990/London-Olympic-Games-For-Kids London Olympic Games For Kids,  074807, http://upgbdyiit.blogger.hu/2012/07/22/2012-olympics-soccer-rules 2012 Olympics Soccer Rules,  >:-))), http://ghebeyfr.bloguez.com/ghebeyfr/5521876/Auburn-Cord-Replica Auburn Cord Replica,  8-P, http://ahkqwysyt.bloguez.com/ahkqwysyt/5524280/E-Cigarette-Twisp-Co-Za E Cigarette Twisp.Co.Za,  :], http://puwkglvp.bloguez.com/puwkglvp/5532180/Phentermine-37-5-Mg-Directions Phentermine 37.5 Mg Directions,  294, http://nmcivxzzng.bloguez.com/nmcivxzzng/5526852/Chanute-Glider-Replica Chanute Glider Replica,  090, http://xvgrxwmqzj.bloguez.com/xvgrxwmqzj/5522542/General-Motors-Air-Conditioning-Diagram General Motors Air Conditioning Diagram,  rnj, http://gwuzaffynk.blogger.hu/2012/07/22/london-olympics-ioc London Olympics Ioc,  hjalbv, http://bzvzjbhbx.bloguez.com/bzvzjbhbx/5525641/Where-To-Buy-Electronic-Cigarette-Starter-Kit-Fifty-One Where To Buy Electronic Cigarette Starter Kit Fifty-One,  749, http://wnjzsgnzcs.bloguez.com/wnjzsgnzcs/5529738/Wholesale-Imports-Replica Wholesale Imports Replica,  105704, http://fbdqvzrxbn.bloguez.com/fbdqvzrxbn/5519123/E-Cigarette-Liquid-Nicotine-Strength E Cigarette Liquid Nicotine Strength,  vfvgxl,
+
=== Тип переменной ===
  
== 5 Reasons Why Meditation Beats an iPhone ==
+
Часто с понятием переменной связывают понятие ее типа. Стоит отметить, что это понятие так же является математической абстракцией. С точки зрения самой машины все данные представляют собой одно и то же — совокупность нулей и единиц. А что под ними понимать в каждом конкретном случае — решает уже программист. Так вот, в некотором смысле ''тип переменной'' показывает, что именно хранится в данной переменной.
  
People buy iPhones to be universally connected and have a ton of cool functions and features at their fingertips. But as the wise monk Rev. Heng Sure once said, everything we create in silicon already exists in carbon. Id add that the silicon technology is a poor facsimile at best.  
+
Наиболее распространенные типы переменных это:
 +
* Логический тип, принимающий только два значения ("истина" и "ложь")
 +
* Целые числа различной длины (байт, слово, двойное слово и т. д.)
 +
* Числа с плавающей точкой
 +
* Строки (последовательность байтов в памяти, воспринимаемая как строка текста)
 +
* Указатели (переменные, содержащие в себе адрес другой переменной)
 +
* Составные типы (некоторая совокупность из вышеперечисленных типов)
  
  [[http://goodvillenews.com/5-Reasons-Why-Meditation-Beats-an-iPhone-piD3rp.html 5 Reasons Why Meditation Beats an iPhone]]
+
Как уже говорилось выше, первоначально о типе переменной знал только программист, пишущий программу. Естественно, вся ответственность за соблюдение соответствия типов выполняемым операциям была возложена на самого программиста. Постепенно, с развитием языков программирования высокого уровня, была выдвинута идея явным образом сопоставлять переменной ее тип. Это обеспечивало большее удобство в написании программ, поскольку всю работу по контролю над типами выполнял сам компилятор, который выдавал сообщения об ошибках, если типы переменных не соответствовали операциям, или была вероятность неверного их истолкования. Так появились языки со статической типизацией.
  
[[http://goodvillenews.com/wk.html goodville news]]
+
== Статическая типизация на примере C++ ==
  
== Dalai Lama Awarded 2012 Templeton Prize ==
+
Итак, ''статическая типизация'' это — приём, при котором переменная, параметр подпрограммы или возвращаемое значение функции связывается с типом в момент объявления и этот тип не может быть изменён позже (переменная или параметр будут принимать, а функция будет возвращать значения только этого типа).
  
The Dalai Lama, the Tibetan Buddhist spiritual leader whose long-standing engagement with multiple dimensions of science and with people far beyond his own religious traditions has made him an incomparable global voice for universal ethics, nonviolence, and harmony among world religions, has won the 2012 Templeton Prize.
+
То есть, если мы объявляем переменные целочисленного типа как <tt>int i, j;</tt> то мы можем выполнять над ними только операции, соответствующие понятиям этого типа, вроде операции сложения <tt>i + j</tt> или операции присваивания одной переменной другой <tt>i = j</tt>. Если же мы попытаемся присвоить такой переменной значение другого, ''неприводимого'' типа, например <tt>i = [2, 3]</tt> то компилятор выдаст ошибку.
  
[[http://goodvillenews.com/Dalai-Lama-Awarded-2012-Templeton-Prize-UttyfI.html Dalai Lama Awarded 2012 Templeton Prize]]
+
Рассмотрим кратко преимущества и недостатки статически типированных языков и сравним их впоследствии с другими подходами к типизации.
  
[[http://goodvillenews.com/wk.html goodville news]]
+
Преимущества статической типизации:
 +
* Строгость программ
 +
* Большая возможность оптимизации, а, следовательно:
 +
** Высокая скорость работы
 +
** Минимальные требования к памяти
  
== Man Climbs Worlds 14 Tallest Peaks ==
+
Недостатки:
 +
* Необходимость объявления типов даже там где это очевидно
 +
* Засорение кода программы дополнительными символами, а, следовательно:
 +
** Отвлечение внимания программиста от самой задачи в сторону рутины формализации
 +
** Плохая читаемость кода
 +
* Необходимость дополнительных ухищрений для передачи параметров разных типов
 +
* Невозможность написания абстрактных алгоритмов
  
Hirotaka Takeuchi has gotten official certification for his feat of climbing the worlds 14 tallest mountains. Hes the 30th person ever and the first Japanese person to accomplish the feat.
+
'''Вывод:''' Программы, написанные на языках со статической типизацией, обладают большой эффективностью и производительностью, однако это дается ценой строгости и определенности. Программирование на таких языках это принятие их правил игры, при этом программист должен мыслить в жестко ограниченных рамках. Вот почему эти языки чаще всего применяются именно для системного программирования, где в первую очередь важна производительность полученного кода, и только потом удобство его написания и поддержки.
  
[[http://goodvillenews.com/Man-Climbs-Worlds-14-Tallest-Peaks-f1nJlP.html Man Climbs Worlds 14 Tallest Peaks]]
+
== Динамическая типизация на примере Ruby ==
  
[[http://goodvillenews.com/wk.html goodville news]]
+
Впоследствии, в противовес статической типизации была разработана модель динамически типированных языков. При таком подходе, переменная не имеет заранее определенного типа, а принимает тип при инициализации и при присвоении ей некоторого значения. Таким образом, в различных участках программы одна и та же переменная может принимать значения разных типов.  
  
== World Book Night: Millions of Free Books Donated ==
+
На первый взгляд это может показать странным, особенно с точки зрения программиста, привыкшего к статически типированным языкам (таким как С++ или Паскаль). На самом деле здесь нет ничего страшного или нелогичного. Все мы в своей жизни, сами того не подозревая, оперируем понятиями динамических переменных. Один и тот же объект в разных ситуациях мы можем воспринимать с разных точек зрения. Задавая вопрос "как пройти в библиотеку", мы можем получить как конкретный ответ "в 3 часа ночи?! идиот!" так и целый набор: "на автобусе номер 23, на такси или пешком, тут не очень далеко". При этом нас совершенно не смущает то, что мы заранее не знаем, каков будет результат, наоборот — это дает нам большую гибкость и свободу действий; мы двигаемся дальше на основании того, каков был результат предыдущей операции. Подобно этому примеру, мы можем писать программы, которые оперируют переменными неопределенного типа. В результате, код получается более лаконичным, более читаемым и, в конце концов, более близким к естественному восприятию человека (ведь именно этого мы ждем от языков программирования!).
  
A young woman is jumping up and down in front of the New York Public Library wearing a sandwich sign that says, "Hate Reading? Talk To Me!" Shes waving around several copies of "The Glass Castle" by Jeannette Walls, eager to get them off her hands.Men and women in suits breeze by, but some passersby are curious about the spectacle. If you were roaming the streets of New York City or London last night you may have encountered a similar scene: Zealous readers handing out award-winning novels by the boxful.
+
Концепция динамической типизации в полной мере нашла свое применение в языке Ruby. В этом языке любая переменная может в разное время иметь различные типы. Вот пример кода на этом языке:
  
  [[http://goodvillenews.com/World-Book-Night-Millions-of-Free-Books-Donated-J7S8iH.html World Book Night: Millions of Free Books Donated]]
+
<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>
  
[[http://goodvillenews.com/wk.html goodville news]]
+
Преимущества динамической типизации:
 +
* Легкость написания программ
 +
* Лаконичность и хорошая читаемость
 +
* Высокая гибкость языка. Возможность решения проблемы разными способами
 +
* Большая возможность повторного использования кода (абстрактные алгоритмы)
 +
 
 +
Недостатки:
 +
* Существенно меньшая производительность, по сравнению со статически типированными языками
 +
* Сложность в написании оптимизаторов, их малая эффективность
 +
* Как правило, динамически типированные языки являются интерпретаторами (компиляция не столь эффективна)
 +
 
 +
'''Вывод:''' Языки с динамической типизацией очень удобны для использования на прикладном уровне. Учитывая их высокую гибкость и лаконичность, программисту легче излагать свои мысли, при том, что свое внимание он концентрирует на самой задаче, не отвлекаясь на частные проблемы реализации. Конечно, они уступают по эффективности статическим, компилируемым языкам, однако это уже вопрос, требующий отдельного рассмотрения в рамках конкретно поставленной задачи.
 +
 
 +
== Полудинамическая типизация ==
 +
 
 +
Рассмотрев преимущества и недостатки статической и динамической типизации, мы подходим к мысли объединения этих двух подходов в рамках одного языка. Языка, который бы сочетал в себе все преимущества динамической типизации, с возможностью указания типов там, где это необходимо. В результате мы получили бы язык, достаточно гибкий и в то же время позволяющий эффективно работать с типами.
 +
 
 +
Язык К++ как раз и ставит перед собой задачу совмещения этих двух подходов. Переменные этого языка могут быть либо типированными, либо не типированными (динамическими). Первые обеспечивают производительность, вторые — гибкость. Достигается это, прежде всего ценой того, что переменная не может изменять свой тип во время выполнения программы. Однако это относится только к статически типированным переменным. Полностью динамические переменные этого недостатка лишены.
 +
 
 +
При разработке программы на языке К++, программист должен стараться держать баланс между удобством написания программы и ее эффективностью. В целом, рекомендуется указывать типы переменных везде, где это возможно. Динамические же переменные следует применять в тех местах, где заранее неизвестно, с каким типом переменной придется работать.
 +
 
 +
== Типизация при объявлении ==
 +
 
 +
Язык К++ позволяет задавать тип переменной несколькими способами. Одним из них является типирование переменной при объявлении. При этом необходимо написать ключевое слово <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>

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

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

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

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

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

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

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

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

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

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