Почему вы должны указывать тип данных при объявлении переменных?

41

В большинстве языков программирования (если не во всех) вам нужно объявлять переменные. Например, в C #, если это числовое поле, то

int PhoneNumber

Если я использую нормальный английский язык, мне не нужно указывать, PhoneNumberкак intего использовать. Например, если я попрошу моего друга Сэма дать мне свой номер телефона, я скажу:

"Сэм, дай мне номер телефона"

Я бы не сказал

"Char (20) Сэм, дай мне номер телефона"

Почему мы вообще должны указывать тип данных?

Дик Смит
источник
83
Это потому, что в английском есть неявная типизация - так что yourPhoneNumber неявно печатается как PhoneNumber - у людей также есть динамическое распределение памяти ...;)
HorusKol
28
Вы и Сэм знаете, что номер телефона состоит из цифр, и вы будете удивлены, обнаружив в нем письмо. Компьютеры не делают и должны быть сказаны.
Торбьерн Равн Андерсен
16
И когда я слышу цифры вроде 1-800-JIMBO в фильмах, у меня возникает мысль: как это число ? Оо
Муру
103
Вы не должны объявлять phoneNumber как int. В большинстве языков программирования это приведет к удалению начальных нулей.
Aron_dc
25
@HorusKol: у людей есть не только динамическое распределение памяти, но и очень неконсервативный сборщик мусора ...
leftaroundabout

Ответы:

79

В большинстве языков программирования (если не во всех) вам нужно объявлять переменные.

[...]

Почему мы вообще должны указывать тип данных?

Это два независимых вопроса:

  • Почему мы должны объявлять переменные?
  • Почему мы должны объявлять типы?

Кстати, ответ на оба вопроса: мы не делаем.

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

Например, в Scala вы можете сказать

val age: Int = 23

или вы могли бы просто сказать

val age = 23

Они в точности эквивалентны: компилятор выведет тип Intиз выражения инициализации 23.

Аналогично, в C♯ вы можете сказать любое из этих двух слов, и оба они означают одно и то же:

int age = 23;
var age = 23;

Эта функция называется выводом типов , и многие языки, кроме Scala и C♯, имеют ее: Haskell, Kotlin, Ceylon, ML, F♯, C ++, как вы ее называете. Даже Java имеет ограниченные формы вывода типов.

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

Например, в ECMAScript:

const age = 23;
let age = 23;

И, наконец, во многих языках вам даже не нужно объявлять переменные вообще. например, в Ruby:

age = 23

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

Так,

  • даже в статически типизированных языках, где переменные имеют типы, вам не обязательно объявлять их,
  • в динамически типизированных языках переменные не имеют типов, поэтому, очевидно, вы даже не можете объявить их,
  • во многих языках вам даже не нужно объявлять переменные
Йорг Миттаг
источник
2
Плюс один для объяснения как вывода типа, так и динамической типизации (позднее связывание)
dcorking
36
Это отличная информация о неправильных представлениях, стоящих за вопросом, но все же оставляет вопрос без ответа. Правильнее, вопрос в том, почему мы должны указывать тип данных при объявлении переменных в языках, которые требуют этого? Почему они были разработаны таким образом? На этот вопрос есть хорошие ответы, и хотя разработка альтернатив расширяет кругозор ОП и является очень хорошей, мне это не кажется полным.
KRyan
7
@KRyan: если вы хотите знать, почему определенный языковой дизайнер сделал определенный выбор языкового дизайна, вам, наверное, придется спросить этого языкового дизайнера. Я не могу сказать вам, почему дизайнеры C♯ решили отказаться от вывода типа, и я не могу сказать вам, почему они позже передумали. Языковой дизайн в значительной степени самоуверен и часто сводится к вкусу. Если, OTOH, вы хотите знать о конкретных компромиссах, ответом будет в основном переиздание типов и языков программирования профессора Пирса, которое слишком широк для Stack Exchange.
Йорг Миттаг
2
JörgWMittag: как уже сказал @KRyan, ответ «вам не нужно» не очень интересен (он очевиден - многие языки позволяют опускать объявления типов в некоторых случаях). Вопрос «почему вы хотите объявить типы» гораздо интереснее и лучше отражает дух первоначального вопроса (ваш ответ напоминает мне шутку: «где мы?» - «вы находитесь на воздушном шаре»). ! " ). Вам не нужно знать, что разработчик определенного языка думал в то время, чтобы предоставить веские причины в пользу объявления типа.
JFS
1
@Zaibis: auto i = 1 // i is inferred to type int, vector<int> vec; auto itr = vec.iterator(); // itr is inferred to type vector<int>::iteratorи так далее. Если вы хотите знать, как именно это работает, вы можете посмотреть это в спецификации.
Jörg W Mittag
53

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

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

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

Это правда, что (многие) люди легко различают европейские, американские и международные номера телефонов. Однако компьютер на самом деле не «думает» и, если ему скажут, наберет номер телефона США в Европе или наоборот. Например, типы - это хороший способ различать эти случаи, без необходимости учить компьютер «думать». На некоторых языках мы можем получить ошибку времени компиляции при попытке смешать европейский номер телефона в американской телефонной системе. Эта ошибка говорит нам о том, что нам нужно изменить нашу программу (возможно, путем преобразования телефонного номера в международную последовательность набора или вместо использования номера телефона в Европе), прежде чем мы даже попытаемся запустить программу.

Кроме того, поскольку компьютер не думает, имя поля или переменной (например phonenumber) ничего не значит для компьютера. Для компьютера это поле / переменная называется просто «blah123». Подумайте, какой была бы ваша программа, если бы все переменные были "blahxxx". Хлоп. Ну, вот что видит компьютер. Предоставление типа дает компьютеру представление о значении переменной, которую он просто не может определить по своему имени.

Кроме того, как говорит @Robert, во многих современных языках нам не нужно указывать типы так же часто, как в старые времена, поскольку языки, такие как C #, выполняют «вывод типов», который представляет собой набор правил для определения правильного типа. для переменной в контексте. C # обеспечивает вывод типа только для локальных переменных, но не для формальных параметров или полей класса или экземпляра.

Эрик Эйдт
источник
4
RE печальная часть: невозможно определить тип общедоступного члена (публичное поле, подпись публичного метода), потому что вы не можете предсказать, когда и как он будет использоваться. Также аннотации типов являются документацией.
Серхио Туленцев
Я думаю, что вы должны выделить / выделить эту строку жирным шрифтом: Types are part of a system of checks that ...поскольку она непосредственно отвечает на OP на Why do we have to specify data type at all?..
txtechhelp
Примечание: вы отвечаете, что язык, используемый для определения типов, лучше избегает ошибок, чем ваш обычный язык программирования. Очевидно, что это не так, например, рассмотрим язык шаблонов C ++, который является полным по Тьюрингу (и, следовательно, позволяет выразить много проверок на ошибки), но он почти нечитаем по сравнению со многими другими полными по Тьюрингу языками, такими как Haskell, Python и даже другие части Сам C ++. Спросите себя, почему вы не будете использовать тот же язык программирования, чтобы выразить проверки ошибок, как и остальная часть вашей программы (есть хорошие ответы в некоторых, но не во всех случаях).
Jfs
@SergioTulentsev Это не так - в F # вы можете использовать открытые методы без явного указания их типов. Компилятор выведет типы из использования внутри метода. Например, следующие допустимые определения открытых методов: static member add x y = x + y, member x.Append s = x.Text + s. В первом случае xи yбудет выведено ints из-за сложения. Во втором случае они будут такими, какими они являются действительными, в зависимости от типа x.Text- если это так string, то sбудет stringтакже и. Я согласен, что аннотации типов - это документация.
Ружо
«Неявные локальные типы, явные типы интерфейса» - так программируют многие люди, даже на таких языках, как Haskell, которые позволяют вам опускать (почти) все типы, при этом компилятор выводит строгие типы. Есть много людей, которые не считают грустным, когда язык применяет эту практику (как в C #).
Бен
29

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

26 3A 00 FF

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

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

Telastyn
источник
10
Верно, но, чтобы по-настоящему ошеломить ваш разум, осознайте, что компьютер никогда не сможет понять, что означают эти биты, даже если вы скажете ему больше аннотаций типов. Ваши объяснения просто превращаются в еще больше шестнадцатеричных чисел, чтобы «уточнить» первые шестнадцатеричные числа. Все значение создается людьми для того, чтобы поместить намерение в электронику и заставить их делать то, что мы намереваемся. Теперь иди скажи «спасибо» инженеру. :)
Wildcard
1
Я провел много лет, программируя на мэйнфреймах. С PL / 1 этот ответ имеет много смысла. Довольно регулярно мы будем использовать хранилище на основе указателя, который был установлен на адрес другой переменной другого типа данных, чтобы получить доступ к байтам другим способом. Например, PL / 1 не поддерживает 1-байтовое двоичное числовое поле, но мы будем основывать 1-символьную переменную по адресу, чтобы позволить нам хранить 6-байтовый массив, хранящий 6 однобайтовых двоичных полей (в этом случае мы можем сохранить 6 байтов на адрес - что было важно, когда хранилище было дорогим).
Кикстарт
1
Компьютер способен понять множество возможностей, но даже умным компиляторам для понимания необходим контекст. Это не то же самое, что число 0 или «0». Или строка «31 декабря» будет заказана до того, как «1 мая» будет считаться строкой, но не считается датой. Или возьми 5/2. Это 2 как вход, но 2.5 как двойной. Кроме того, тип является мерой защиты от нежелательных преобразований. Ноль, NaN, округление или переполнение также могут стать проблемой. Сильные и статически типизированные языки имеют некоторые преимущества. Например, компилятор помогает обнаруживать проблемы при рефакторинге.
Борхаб
1
@ Borjab Вы имели в виду "Это 2 как целое число "?
Ричард Эверетт
1
@RichardEverett Конечно, это был ляпсус. Спасибо, но поздно, чтобы отредактировать его.
Борхаб
23

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

Название «тип данных» является ссылкой на правила, которые помогают компьютеру сохранять и извлекать информацию из его необработанных состояний 0 и 1 в памяти компьютера.

Например, ваш обычный 8-разрядный символ ASCII будет сохранен в памяти компьютера (либо в ОЗУ, либо на диске) как 01000001(символ «A» в верхнем регистре, код ASCII 65) или 00001000(знак процента), либо как любая комбинация из 0 и 1 в этих 8 битах.

Для другого примера некоторое 8-разрядное целое число без знака может быть сохранено как 00000101(число 5) или 00001000(число 8)

Обратите внимание, что двоичное представление числа 8 и символа% может быть одинаковым, но они означают разные вещи, потому что их типы различны.

Даже в языках, которые определяют тип данных, у них может не быть правила о том, что «все типы переменных должны быть объявлены программистом», у них есть правила типа «если ваша серия символов заключена в кавычки, это строка» и еще много правил для каждого типа данных.

Таким образом, даже им нужны типы данных, чтобы понять, что означают 0 и 1, поэтому они могут, например, выполнять функцию конкатенации строк, если вы пытаетесь «добавить» два символа, или делать целочисленное добавление, если вы пытаетесь добавить два целых числа. ,

В вашей истории , скажем, вы не спрашивали Сэма о номере телефона, но Сэм дает вам листок бумаги с надписью «1123581321». Вы не могли быть уверены, что Сэм просто фанат первых восьми чисел Фибоначчи или это номер телефона. Чтобы сделать предположение, вы должны будете принять во внимание контекст и подсказки, которые у вас есть, например, вы, возможно, попросили Сэма назвать номер телефона день назад, или в записке написано «Позвони мне», или если вы посчитаете цифры и найдете это соответствует шаблонам большинства телефонных номеров. Только тогда вы узнаете, что вы можете позвонить по номеру телефона, а не по цифрам, которые вы можете ввести в калькулятор.

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

Peeyush Kushwaha
источник
3
Это самый близкий ответ. Все это связано с памятью. Вы объявляете тип, чтобы компилятор знал, сколько памяти приложению следует запрашивать во время выполнения. Знание того, как следует интерпретировать биты, является вторичным.
Грег Бургхардт
@GregBurghardt правда. Для понимания уже существующих битов, а также для размещения битов на первом месте после преобразования данных в двоичные данные в соответствии с типом данных.
Peeyush Kushwaha
10

В некоторых языках вам не нужно указывать тип данных.

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

var name = "Ali"

внутренне типизируется как строка, потому что значение заключено в кавычки.

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

Роберт Харви
источник
5
var name = "Ali"Стиль на самом деле общий для современных статический типизированных языков. В статически типизированных языках тип фиксируется при создании, но он все еще может быть определен инициализатором. Определение языка с динамической типизацией заключается в том, что типы привязываются к значениям, а не к переменным. Присвоение значения переменной, следовательно, также устанавливает тип переменных.
MSalters
@MSalters: я немного изменил формулировку.
Роберт Харви
5
Ирония здесь в том, что это включает в себя C # с этим точным синтаксисом.
Дерек Элкинс
1
@MSalters Присвоение значения переменной, следовательно, также устанавливает тип переменных. Или, что переменная не имеет собственного типа, и интерпретатор попытается применить любую операцию к значению переменной. Существуют ли языки с динамической типизацией, в которых код, подобный следующему (Javascript), не был бы разрешен, var x = 5; x = "";потому что первый оператор приводит xк тому, что тип «Number» связан с x? Вроде конфликты с динамической типизацией . И если нет, то какой эффект имеет тип, связанный с переменной, помимо связи типа со значением?
Зев Шпиц
1
@ZevSpitz: первый тип системы не типизирован динамически, но не типизирован вообще. Ваш пример Javascript не типизирован динамически, потому что тип Number не может быть изменен. В динамически типизированном языке x = "";изменяет тип x на строковый, даже если это было число ранее.
MSalters
9

Потому что именно это определяет языковой дизайн. Поэтому, чтобы ответить на ваш вопрос, нам нужно взглянуть на цель явной типизации в таких языках, как C # и C ++. (Ну, C # делает это, потому что C ++ делает это, потому что C делает это, поэтому нам нужно взглянуть на намерение еще тогда).

Во-первых, явная и статическая типизация обеспечивает строгость кодирования - указание переменной как целого означает, что компилятор и программное обеспечение должны быть удивлены и выдавать ошибку, когда вы присваиваете переменную символ или строку. Динамическая типизация может вызвать головную боль у неосторожных (просто взгляните на PHP или подход JavaScript к правдивости таких вещей, как массивы и пустые строки).

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

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

PhoneNumber phoneNumber = "(61) 8 8000 8123";

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

PhoneNumber phoneNumber;
...
phoneNumber = "some value from somewhere";

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

Это не значит, что явное лучше, чем неявное, но дизайн языка опирается на такие варианты, и C # будет работать по-другому с неявной типизацией. PHP и JavaScript будут работать по-разному с явной типизацией.

HorusKol
источник
5

Потому что Сэм умнее компиляторов. Например, когда вы говорите, дайте мне номер телефона, вы не указываете, хотите ли вы, чтобы префикс страны или код города был ли это рабочий номер, для которого требуются только последние 4 цифры. Кроме того, если вы спросите номер местной пиццерии, вы сможете ответить на вопрос «pizza4u».

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

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

У каждого подхода есть свои преимущества и недостатки. В общем, авторы компиляторов стараются минимизировать недостатки и максимизировать преимущества. Вот почему C #, например, позволяет var phoneNumber = GetPhoneNumber();и будет выводить тип phoneNumber из подписи GetPhoneNumber. Это означает, что вы должны объявить тип для метода, но не переменную, которая получает результат. С другой стороны, для javascript существуют различные проекты хинтинга и принудительного исполнения. Все это компромисс.

jmoreno
источник
3

Это вопрос способа хранения данных. Ваше взаимодействие с Сэмом могло бы быть лучше, если бы вы спросили, чтобы вы могли записать его, но у вас было всего восемь знаков бумаги.

"Сэм, дай мне номер телефона."

"5555555555"

«О нет, у меня нет бумаги. Если бы я знал заранее, сколько данных я запрашивал, я мог бы подготовиться лучше!»

Таким образом, вместо большинства языков вы объявляете тип, поэтому он будет знать и готовиться заранее:

"Сэм, как долго номер телефона?"

«Десять символов».

«Хорошо, тогда позвольте мне взять лист бумаги побольше. Теперь дайте мне номер телефона».

"5555555555"

"Понял! Спасибо Сэм!"

Это становится еще более опасным, когда вы смотрите на фактические основные способы хранения данных. Если вы похожи на меня, у вас есть записная книжка с различными заметками, просто набросанными цифрами, без контекста или ярлыков для чего-либо, и вы не имеете ни малейшего понятия, что это означает через три дня. Это проблема для компьютеров также много раз. Многие языки имеют типы «int» (int, long, short, byte) и «float» (float, double). Почему это необходимо?

Ну, во-первых, давайте посмотрим, как целое число хранится и в целом представлено в компьютере. Вы, вероятно, знаете, что на базовом уровне это все двоичные (1 и 0). Двоичная система - это система счисления, которая работает точно так же, как наша десятичная система счисления. В десятичном исчислении вы считаете от 0 до 9 (с бесконечными подразумеваемыми ведущими нулями, которые вы не пишете), затем вы возвращаетесь к 0 и увеличиваете следующую цифру, чтобы получить 10. Вы повторяете, пока не перевернете с 19 на 20, повторяйте пока не перевернете с 99 на 100 и так далее.

Двоичные значения ничем не отличаются, за исключением того, что вместо 0 до 9 вы считаете от 0 до 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Поэтому, когда вы вводите 9, в памяти, записанной в двоичном виде как 1001. Это фактическое число. Он может быть добавлен, вычтен, умножен и т. Д., Именно в этой форме. 10 + 1 = 11. 10 + 10 = 100 (переверните 1 к 0 и держите 1). 11 х 10 = 110 (и, что эквивалентно, 11 + 11 = 110).

Теперь в фактической памяти (включая регистры) есть список, массив, как бы вы ни хотели его назвать, битов (потенциальных 1 или 0 ') рядом друг с другом, что позволяет логически организовывать эти биты для создания число больше 1. Проблема в том, что вы делаете с десятичными числами? Вы не можете просто вставить аппаратную часть между двумя битами в регистре, и будет слишком дорого добавлять «десятичные биты» между каждой парой битов. Так что делать?

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

Ввод позволяет компилятору знать, на что он смотрит. Представьте, что вы сохранили значение 1,3 в регистре 1. Мы просто придумаем здесь нашу собственную причудливую схему кодирования: 1 бит для знака, 4 для мантиссы, 3 для показателя степени (1 бит для знака, 2 для величины). Это положительное число, поэтому знак положительный (0). Наша мантисса будет 13 (1101), а наш показатель будет -1 (101 (1 для отрицательного, 01 = 1)). Таким образом, мы храним 01101101 в регистре 1. Теперь мы не вводили эту переменную, поэтому, когда среда выполнения начинает использовать ее, она говорит «конечно, это целое число, почему нет», поэтому, когда она печатает значение, мы видим 109 (64 + 32 + 8 + 4 + 1), что явно не правильно.

Однако не каждый язык требует от вас явного ввода. В C # есть ключевое слово «var», которое заставляет интерпретировать тип переменной во время компиляции, а другие языки, такие как Javascript, полностью динамически типизированы, так что вы можете сохранить целое число в переменной, затем присвоить его логическому значению, а затем назначьте это снова строке, и язык отслеживает все это.

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

Devsman
источник
2

Есть языки программирования, где вам не нужно объявлять типы данных для ваших переменных. Есть даже языки программирования, где вам не нужно объявлять переменные заранее; Вы можете просто использовать их, немедленно.

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

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

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

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

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

MathematicalOrchid
источник
1
В C ++ вы можете поставить «auto x = 1», и он знает, что это int. авто у = 1,2; auto z = 'Z'; и т.д.
QuentinUK
@QuentinUK В C # вы можете поставить var x=1с похожими результатами. Но это ничего; в Haskell вы можете написать всю свою программу без каких-либо сигнатур типов, но все это статически типизировано, и вы все равно будете получать ошибки, если сделаете ошибку ... (Не совсем мейнстрим, хотя.)
MatumaticOrchid
@QuentinUK Но если вы пишете for (auto i=0; i<SomeStdVector.size(); ++i)ваш ЛИНТЕР будет жаловаться , потому что он вывел подписанный тип и вы приступите сравнить его без знака типа. Вы должны написать auto i=0ul(поместив информацию о типе в явном виде снова, поэтому следует просто написать size_t i=0в первую очередь).
dmckee
1

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

"Сэм, дай мне номер телефона"

Я бы не сказал>

"Char (20) Сэм, дай мне номер телефона"

Почему мы вообще должны указывать тип данных?

Перейдите в MathOverflow или Теоретическую информатику и некоторое время читайте, чтобы получить представление о том, как люди общались друг с другом, когда хотят убедиться, что нет недопонимания. Или прочитайте стандарт для некоторого зрелого языка программирования.

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

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

Но вы когда-нибудь пытались снять номер телефона для кого-то в другой стране? Они говорили вам явно, сколько раз нажать ноль, чтобы добраться до международной адресации? Они сказали вам свой код страны? Вы узнали это как таковое? Сколько цифр вы ожидали? Сколько ты получил? Знаете ли вы, как сгруппировать цифры? Или даже если группировка имеет значение?

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

dmckee
источник
0

Другая причина объявления типов - эффективность. Хотя целое число может храниться в 1 байте, или 2 байтах, или 4, программа, использующая очень большое количество переменных, может использовать в 4 раза больше необходимой памяти, в зависимости от того, что делается. Только программист знает, жизнеспособен ли меньший объем памяти, поэтому он может сказать это, объявив тип.

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

donjuedo
источник
0

На многих ранних языках программирования (особенно на Fortran) не требовалось объявлять переменные перед использованием.

Это привело к ряду проблем. Одним из действительно очевидных является то, что компилятор больше не может отлавливать простые опечатки почти так же надежно. Если у вас есть код, который должен изменить существующую переменную, но содержит опечатку, у вас все еще есть совершенно законный код, который только что создал (и присвоил значение) новую переменную:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

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

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

Джерри Гроб
источник
0

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

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

Atul170294
источник
это, кажется, не предлагает ничего существенного по сравнению с замечаниями, сделанными и объясненными в предыдущих 11 ответах
комнат
1
Надо еще раз внимательно прочитать все ответы и убедиться, что я попытался ответить на этот вопрос гораздо более простым способом, который легко понять.
Atul170294
Я только что проверил три последних ответа, которые были опубликованы примерно за час до этого, и все три, кажется, подчеркивают одно и то же, и в моем чтении объясняю это проще, чем здесь
комнат
Хотя я не отвечал за вознаграждение за ваш голос, но я думаю, что вы должны узнать одну вещь, вы должны понизить ответ, потому что он может дать бесполезную или неправильную информацию, и если он содержит что-то оскорбительное. Все ответы, которые содержат наиболее полезную и полезную информацию, получат большее количество голосов, достаточных для того, чтобы различить ответ, хороший ответ и лучший ответ. Ваша ребяческая активность, направленная на отрицание ответа без веских причин, только отговорит других людей, которые также хотят поделиться своим мнением, которое, по их мнению, может быть полезным для других
Atul170294
1
Ваш ответ, скорее всего, был отклонен, потому что он не является правильным. Статическая типизация не требуется, чтобы помочь с управлением памятью. Существует много языков, которые допускают динамическую типизацию, и эти языки / среды способны решать упомянутые вами проблемы управления памятью.
Джей Элстон