Warum müssen Sie beim Deklarieren von Variablen den Datentyp angeben?

41

In den meisten Programmiersprachen (wenn nicht allen) müssen Sie Variablen deklarieren. Zum Beispiel in C #, wenn es ein Zahlenfeld ist

int PhoneNumber

Wenn ich normale englische Sprache bin mit brauche ich nicht zu erklären , PhoneNumberwie intes zu benutzen. Wenn ich zum Beispiel meinen Freund Sam nach seiner Telefonnummer frage, sage ich:

"Sam gib mir die Telefonnummer"

Würde ich nicht sagen

"Char (20) Sam gib mir die int phoneNumber"

Warum müssen wir überhaupt den Datentyp angeben?

Dick Smith
quelle
83
Das liegt daran, dass Englisch implizit tippt - Ihre Telefonnummer wird also implizit als Telefonnummer getippt - Menschen haben auch eine dynamische Speicherzuweisung ...;)
HorusKol
28
Sie und Sam wissen, dass eine Telefonnummer aus Ziffern besteht und Sie wären überrascht, einen Buchstaben darin zu finden. Computer müssen und müssen nicht erzählt werden.
Thorbjørn Ravn Andersen
16
Und wenn ich in Filmen Zahlen wie 1-800-JIMBO höre, ist mein Gedanke: Wie ist das eine Zahl ? Oo
muru
103
Sie sollten phoneNumber nicht als int deklarieren. In den meisten Programmiersprachen werden führende Nullen gelöscht.
Aron_dc
25
@ HorusKol: Menschen haben nicht nur dynamische Speicherzuweisung, sondern auch einen hochgradig nicht-
konservativen

Antworten:

79

In den meisten Programmiersprachen (wenn nicht allen) müssen Sie Variablen deklarieren.

[…]

Warum müssen wir überhaupt den Datentyp angeben?

Das sind zwei unabhängige Fragen:

  • Warum müssen wir Variablen deklarieren?
  • Warum müssen wir Typen deklarieren?

Die Antwort auf beide lautet übrigens: Wir nicht.

Es gibt viele statisch typisierte Programmiersprachen, in denen Sie keine Typen deklarieren müssen. Der Compiler kann die Typen aus dem Umgebungskontext und der Verwendung ableiten.

In Scala kann man zum Beispiel sagen

val age: Int = 23

oder du könntest einfach sagen

val age = 23

Die beiden sind genau gleichwertig: Der Compiler leitet den Typ Intaus dem Initialisierungsausdruck ab 23.

Ebenso können Sie in C♯ beides sagen, und beide bedeuten genau dasselbe:

int age = 23;
var age = 23;

Diese Funktion wird als Typinferenz bezeichnet , und viele Sprachen außer Scala und C♯ haben sie: Haskell, Kotlin, Ceylon, ML, F♯, C ++, Sie nennen sie. Sogar Java hat begrenzte Formen der Typinferenz.

In dynamisch getippten Programmiersprachen haben Variablen nicht einmal Typen. Typen existieren nur dynamisch zur Laufzeit, nicht statisch. Nur Werte und Ausdrücke haben Typen, und Variablen haben nur zur Laufzeit keine Typen.

ZB in ECMAScript:

const age = 23;
let age = 23;

Und schließlich müssen Sie in vielen Sprachen überhaupt keine Variablen deklarieren. zB in Ruby:

age = 23

Tatsächlich ist das letzte Beispiel in einer Reihe von Programmiersprachen gültig. Die exakt gleiche Codezeile würde beispielsweise auch in Python funktionieren.

Damit,

  • Selbst in statisch typisierten Sprachen, in denen Variablen Typen haben, müssen Sie diese nicht unbedingt deklarieren.
  • In dynamisch getippten Sprachen haben Variablen keine Typen. Sie können sie also offensichtlich nicht einmal deklarieren.
  • In vielen Sprachen müssen Sie nicht einmal Variablen deklarieren
Jörg W. Mittag
quelle
2
Plus eins zur Erklärung von Typinferenz und dynamischer Typisierung (späte Bindung)
Entkorken am
36
Dies ist eine großartige Information über Missverständnisse, die hinter der Frage stehen, aber die Frage bleibt unbeantwortet. Die Frage ist, warum wir den Datentyp angeben müssen, wenn wir Variablen in Sprachen deklarieren , die dies erfordern. Warum wurden sie so entworfen? Es gibt gute Antworten auf diese Frage, und obwohl die Ausarbeitung von Alternativen den Horizont des OP erweitert und sehr gut ist, scheint mir das nicht vollständig zu sein.
KRyan
7
@KRyan: Wenn Sie wissen möchten, warum ein bestimmter Sprachdesigner eine bestimmte Sprachdesign-Wahl getroffen hat, müssen Sie diesen Sprachdesigner leider fragen. Ich kann Ihnen nicht sagen, warum sich die Designer von C♯ gegen Typinferenz entschieden haben, und ich kann Ihnen auch nicht sagen, warum sie später ihre Meinung geändert haben. Sprachdesign ist stark aufgeschlossen und oft auf den Geschmack zurückzuführen. Wenn Sie, OTOH, über die spezifischen Kompromisse informiert werden möchten, ist die Antwort im Grunde genommen eine Neuauflage von Prof. Pierces Typen und Programmiersprachen, die für Stack Exchange viel zu umfangreich ist.
Jörg W Mittag
2
JörgWMittag: Wie @KRyan bereits sagte, ist die Antwort "Sie müssen nicht" nicht sehr interessant (es ist trivial offensichtlich - in vielen Sprachen können die Typdeklarationen in einigen Fällen weggelassen werden). Die Frage "Warum möchten Sie Typen deklarieren ?" Ist viel interessanter und spiegelt den Geist der ursprünglichen Frage besser wider (Ihre Antwort erinnert mich an den Witz: "Wo sind wir?" - "Sie sitzen in einem Heißluftballon ! " ). Sie müssen nicht wissen, was ein Designer einer bestimmten Sprache zu der Zeit dachte, um einige gute Gründe für die Typdeklaration anzugeben.
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>::iteratorund so weiter. Wenn Sie wissen möchten, wie genau das funktioniert, können Sie es in der Spezifikation nachschlagen.
Jörg W Mittag
53

Wenn Sie auf Informationen in natürlicher Sprache verweisen, ist dies nicht sehr präzise und kommuniziert insbesondere nicht viel über Ihre Absichten mit anderen. Ähnliche Probleme treten auf, wenn Sie versuchen, Mathematik in natürlicher Sprache zu üben: Es ist einfach nicht präzise genug.

Die Programmierung ist komplex; Fehler sind allzu leicht zu finden. Typen sind Teil eines Überprüfungssystems, mit dem unzulässige Programmzustände durch Erkennen von Fehlerzuständen verhindert werden sollen. Verschiedene Sprachen verwenden Typen unterschiedlich: Einige Sprachen verwenden Typen sehr häufig, um Fehler beim Kompilieren zu erkennen. Fast alle Sprachen kennen inkompatible Typen als Laufzeitfehler. Normalerweise weist ein Tippfehler auf einen Fehler im Programm hin. Wenn wir zulassen, dass Programme trotz Fehlern fortgesetzt werden, erhalten wir wahrscheinlich sehr schlechte Antworten. Wir halten das Programm lieber an, als falsche oder falsche Antworten zu erhalten.

Anders ausgedrückt, Typen drücken Einschränkungen für das Verhalten des Programms aus. Einschränkungen bieten, wenn sie durch einen Mechanismus erzwungen werden, Garantien. Diese Garantien begrenzen den Umfang der Überlegungen, die zum Nachdenken über das Programm erforderlich sind, und vereinfachen so das Lesen und Verwalten des Programms für Programmierer. Ohne Typen und deren Implikation durch Tools (dh den Compiler), die Typfehler erkennen, ist der Programmieraufwand erheblich höher und damit teurer.

Es ist wahr, dass (viele) Menschen leicht zwischen einer europäischen, einer amerikanischen und einer internationalen Telefonnummer unterscheiden können. Der Computer "denkt" jedoch nicht wirklich und wählt, wenn er dazu aufgefordert wird, eine Telefonnummer in Europa (USA) oder umgekehrt. Typen zum Beispiel sind eine gute Möglichkeit, zwischen diesen Fällen zu unterscheiden, ohne dem Computer beibringen zu müssen, wie man "denkt". In einigen Sprachen kann ein Kompilierungsfehler auftreten, wenn versucht wird, eine europäische Telefonnummer in einem amerikanischen Telefonsystem zu mischen. Dieser Fehler besagt, dass wir unser Programm ändern müssen (möglicherweise durch Konvertieren der Telefonnummer in eine internationale Wählfolge oder durch Verwenden der Telefonnummer in Europa), bevor wir überhaupt versuchen, das Programm auszuführen.

Da der Computer nicht denkt, bedeutet der Name des Feldes oder der Variablen (z. B. phonenumber) für den Computer nichts. Für den Computer ist dieser Feld- / Variablenname nur "blah123". Überlegen Sie, wie Ihr Programm aussehen würde, wenn alle Variablen "blahxxx" wären. Huch. Nun, das sieht der Computer. Das Bereitstellen eines Typs gibt dem Computer einen Hinweis auf die Bedeutung der Variablen, die er einfach nicht allein aus ihrem Namen ableiten kann.

Wie @Robert sagt, müssen wir in vielen modernen Sprachen nicht mehr so ​​viele Typen wie früher angeben, da Sprachen wie C # "Typinferenz" ausführen, dh eine Reihe von Regeln, um den richtigen Typ zu bestimmen für eine Variable im Kontext. C # ermöglicht nur eine Typinferenz für lokale Variablen, nicht jedoch für formale Parameter oder Klassen- oder Instanzfelder.

Erik Eidt
quelle
4
Was den traurigen Teil betrifft: Es ist unmöglich, auf einen öffentlich zugänglichen Elementtyp (öffentliches Feld, öffentliche Methodensignatur) zu schließen, da Sie nicht vorhersagen können, wann und wie er verwendet wird. Typanmerkungen sind auch Dokumentationen.
Sergio Tulentsev
Ich denke, Sie sollten diese Zeile hervorheben / fett Types are part of a system of checks that ...Why do we have to specify data type at all?
schreiben
Hinweis: Sie gehen davon aus, dass eine Sprache, in der Typen angegeben werden, Fehler irgendwie besser vermeidet als Ihre normale Programmiersprache. Es ist offensichtlich nicht so, dass zB C ++ - Vorlagensprache Turing-vollständig ist (und daher viele Fehlerprüfungen ermöglicht), aber es ist im Vergleich zu vielen anderen Turing-vollständigen Sprachen wie Haskell, Python und sogar anderen Teilen von fast unlesbar C ++ selbst. Fragen Sie sich, warum Sie nicht dieselbe Programmiersprache verwenden, um die Fehlerprüfungen wie im Rest Ihres Programms auszudrücken (in einigen, aber nicht in allen Fällen gibt es gute Antworten).
JFS
@SergioTulentsev Das stimmt nicht - in F # können Sie öffentliche Methoden verwenden, ohne deren Typ explizit anzugeben. Der Compiler leitet die Typen aus der Verwendung innerhalb der Methode ab. Zum Beispiel sind die folgenden gültige öffentliche Methode Definitionen: static member add x y = x + y, member x.Append s = x.Text + s. Im ersten Fall xund ywird intaufgrund des Zusatzes davon ausgegangen, dass es sich um s handelt. Im zweiten Fall sind sie gültig, abhängig von der Art von x.Text- wenn es eine ist string, dann sist es auch eine string. Ich stimme jedoch zu, dass Typanmerkungen Dokumentationen sind.
Roujo
"Implizite lokale Typen, explizite Schnittstellentypen" ist, wie viele Leute programmieren, selbst in Sprachen wie Haskell, mit denen Sie (fast) alle Typen auslassen können, während der Compiler noch strenge Typen ableiten muss. Es gibt viele Leute, die es nicht für traurig halten, wenn eine Sprache diese Praxis erzwingt (wie C #).
Ben
29

Neben den anderen Antworten sollte noch eines berücksichtigt werden. Denken Sie daran, dass Computer nur Bits sind. Sagen wir, ich gebe dir die Bytes:

26 3A 00 FF

Was bedeutet , dass Mittel ? Es wird auf diese Weise vom Computer gespeichert, aber ohne Interpretation sind es nur Bits . Es können 4 ASCII-Zeichen sein. Es könnte eine ganze Zahl sein. Es können einige Bytes in einem Array sein. Es könnte Teil eines Objekts sein. Dies könnte ein Hinweis darauf sein, wo das Katzenvideo zwischengespeichert wird. So gut wie alle Programmiersprachen von der Montage auf bis Notwendigkeit , etwas zu wissen , wie die Bits zu interpretieren , um sie zu tun sinnvolle Berechnung zu machen.

Und da der Computer die Bedeutung dieser Bits nicht kennen kann, müssen Sie sie mitteilen - entweder explizit über Typanmerkungen oder implizit über Typinferenzmechanismen, die in den anderen Antworten erwähnt werden.

Telastyn
quelle
10
Wohl wahr, aber um wirklich boggle, Geist erkennen , dass der Computer nie der Lage zu verstehen , was diese Bits bedeuten, selbst wenn Sie es Anmerkungen mehr Art erzählen. Ihre Erklärungen werden einfach in noch mehr Hexadezimalzahlen umgewandelt, um die ersten Hexadezimalzahlen zu "verdeutlichen". Die Bedeutung wird allesamt von Menschen geschaffen, um die Absicht in die Elektronik zu bringen und sie dazu zu bringen, das zu tun, was wir beabsichtigen. Sagen Sie jetzt einem Ingenieur "Danke". :)
Wildcard
1
Ich habe viele Jahre mit dem Programmieren auf Großrechnern verbracht. Mit PL / 1 ist diese Antwort sehr sinnvoll. Ziemlich regelmäßig würden wir Speicher basierend auf einem Zeiger verwenden, der auf die Adresse einer anderen Variablen eines anderen Datentyps gesetzt wurde, um auf andere Weise auf die Bytes zuzugreifen. Zum Beispiel unterstützt PL / 1 kein 1-Byte-Binärzahlenfeld, aber wir würden eine 1-Zeichen-Variable an der Adresse verwenden, um ein 6-Byte-Array zu speichern, das 6 Einzelbyte-Binärfelder speichert (in diesem Fall können wir speichern) 6 Bytes pro Adresse - das war wichtig, als Speicher teuer war).
Kickstart
1
Der Computer ist in der Lage, viele Möglichkeiten zu verstehen, aber auch der clevere Compiler benötigt Kontext, um zu verstehen. Es ist nicht dasselbe die Zahl 0 oder "0". Oder der String "Dec 31" wird vor dem "May 1" als String, aber nicht als Date bestellt. Oder nimm 5/2. Es ist 2 als Enter, aber 2,5 als Double. Der Typ ist auch eine Sicherheitsmaßnahme gegen unerwünschte Konvertierungen. Null, NaN und Rundungen oder Überläufe können ebenfalls zu einem Problem werden. Starke und statisch typisierte Sprachen haben einige Vorteile. Der Compiler hilft Ihnen beispielsweise beim Erkennen von Problemen beim Refactoring.
Borjab
1
@Borjab Meinten Sie "It is 2 as a integer "?
Richard Everett
1
@RichardEverett Sicher war das ein Lapsus. Danke aber zu spät um es zu bearbeiten.
Borjab
23

Die Antwort, warum die Computer diese Informationen benötigen, hat mit der Datendarstellung zu tun .

Der Name des "Datentyps" ist ein Verweis auf Regeln, die dem Computer helfen, Informationen aus dem Rohzustand der Nullen und Einsen im Computerspeicher zu speichern und abzurufen.

Beispiel: Ihr reguläres 8-Bit-ASCII-Zeichen wird im Computerspeicher (RAM oder Disk) als 01000001(Großbuchstabe "A", ASCII-Code 65) oder 00001000(Prozentzeichen) oder beliebige Kombinationen von Nullen und gespeichert Einsen in diesen 8 Bits.

In einem anderen Beispiel kann eine 8-Bit-Ganzzahl ohne Vorzeichen als 00000101(die Nummer 5) oder 00001000(die Nummer 8) gespeichert werden.

Beachten Sie, dass die binäre Darstellung von 8 und dem% -Zeichen zwar identisch ist, jedoch unterschiedliche Bedeutungen hat, da ihre Typen unterschiedlich sind.

Selbst die Sprachen, die auf den Datentyp schließen, haben möglicherweise nicht die Regel, dass "alle Variablentypen vom Programmierer deklariert werden müssen". Sie haben Regeln wie "Wenn Ihre Zeichenfolge in Anführungszeichen eingeschlossen ist, handelt es sich um eine Zeichenfolge" viele weitere Regeln für jeden Datentyp.

Selbst diese benötigen Datentypen, um zu verstehen, was die Nullen und Einsen bedeuten. Sie können also beispielsweise die Funktion zur Verkettung von Zeichenfolgen ausführen, wenn Sie versuchen, zwei Zeichen "hinzuzufügen", oder die Ganzzahladdition, wenn Sie versuchen, zwei Ganzzahlen hinzuzufügen .

In Ihrer Geschichte zu, sagen wir , Sie nicht Sam fragen Sie nach der Telefonnummer , aber Sam gibt Ihnen ein Stück Papier , das „1123581321“ auf sie hat. Sie konnten nicht sicher sein, ob Sam nur ein Fan der ersten acht Fibonacci-Nummern ist oder ob das eine Telefonnummer ist. Um eine Vermutung anzustellen, müssen Sie den verfügbaren Kontext und die verfügbaren Hinweise berücksichtigen, z. B. haben Sie Sam vor einem Tag nach einer Telefonnummer gefragt oder in der Notiz steht "Ruf mich an", oder wenn Sie die Ziffern zählen und suchen Es entspricht den Mustern der meisten Telefonnummern. Nur dann würden Sie wissen, dass es sich um eine Telefonnummer handelt, die Sie anrufen können, und nicht um einige Ziffern, die Sie in einen Taschenrechner eingeben würden.

Beachten Sie, wie diese Hinweise, die Sie zu der Annahme geführt haben, dass es sich bei der Nummer um eine Telefonnummer handelt, denen ähneln, wie Hinweise zu einer Computersprache führen, für die keine Deklaration erforderlich ist, um den Typ eines Werts abzuleiten.

Peeyush Kushwaha
quelle
3
Dies ist die naheliegendste Antwort. Alles hat mit Erinnerung zu tun. Sie deklarieren den Typ, damit der Compiler weiß, wie viel Speicher die Anwendung zur Laufzeit anfordern soll. Zu wissen, wie die Bits interpretiert werden sollen, ist zweitrangig.
Greg Burghardt
@ GregBurghardt wahr. Zum Verstehen bereits vorhandener Bits und zum Platzieren der Bits an erster Stelle nach dem Umwandeln gegebener Daten in Binärdaten entsprechend dem Datentyp.
Peeyush Kushwaha
10

In einigen Sprachen müssen Sie den Datentyp nicht angeben.

Sprachen, die Typinferenz unterstützen, können normalerweise den Datentyp aus Ihrer Verwendung ermitteln. Zum Beispiel,

var name = "Ali"

wird intern als Zeichenfolge eingegeben, da der Wert von Anführungszeichen umgeben ist.

In einigen Sprachen müssen Sie die Variable auch nicht deklarieren. Die Variable wird bei der ersten Verwendung erstellt. Es wird jedoch aus mehreren wichtigen Gründen als bewährte Methode angesehen, Ihre Variablen speziell zu deklarieren. Meistens, weil dies Ihre Absicht besser zum Ausdruck bringt.

Robert Harvey
quelle
5
Der var name = "Ali"Stil ist eigentlich für moderne statisch typisierte Sprachen üblich. In statisch typisierten Sprachen ist der Typ bei der Erstellung festgelegt, kann jedoch weiterhin vom Initialisierer bestimmt werden. Die Definition einer dynamisch typisierten Sprache ist, dass Typen an Werte und nicht an Variablen angehängt werden. Wenn Sie einer Variablen einen Wert zuweisen, wird auch der Variablentyp festgelegt.
MSalters
@MSalters: Ich habe den Wortlaut leicht angepasst.
Robert Harvey
5
Die Ironie hier ist, dass dies C # mit genau dieser Syntax beinhaltet.
Derek Elkins
1
@MSalters Wenn Sie einer Variablen einen Wert zuweisen, wird auch der Variablentyp festgelegt. Oder dass die Variable keinen inhärenten Typ hat und der Interpreter versucht, eine beliebige Operation auf den Wert der Variablen anzuwenden. Gibt es dynamisch typisierte Sprachen, in denen Code wie der folgende (Javascript) nicht zulässig ist, var x = 5; x = "";weil die erste Anweisung bewirkt x, dass der Typ "Number" zugeordnet wird x? Art von Konflikten mit der dynamischen Eingabe . Und wenn nicht, welchen Effekt hat der mit der Variablen verknüpfte Typ über die Typzuordnung zum Wert hinaus?
Zev Spitz
1
@ZevSpitz: Die erste Art von System ist nicht dynamisch, aber überhaupt nicht typisiert. Ihr Javascript-Beispiel wird nicht dynamisch eingegeben, da sich der Zahlentyp nicht ändern kann. Ändert in einer dynamisch getippten Sprache x = "";den Typ von x in string, auch wenn es sich zuvor um eine Zahl handelte.
MSalters
9

Denn genau das gibt das Sprachdesign vor. Um Ihre Frage zu beantworten, müssen wir uns die Absicht hinter expliziter Eingabe in Sprachen wie C # und C ++ ansehen. (Nun, C # macht es, weil C ++ es tut, weil C es tut, also müssen wir uns die Absichten von damals ansehen.)

Erstens bietet die explizite und statische Typisierung eine strenge Codierung. Wenn Sie eine Variable als Ganzzahl angeben, sollten der Compiler und die Software überrascht sein und einen Fehler auslösen, wenn Sie der Variablen ein Zeichen oder eine Zeichenfolge zuweisen. Dynamische Eingabe kann Kopfschmerzen für die Unachtsamen verursachen (schauen Sie sich einfach PHP an oder Javascripts nähern sich der Wahrheit von Dingen wie Arrays und leeren Strings).

Sie können statisch mit impliziter Typisierung arbeiten. Wenn Sie eine Variable als Zeichenfolge initialisieren, bedeutet dies, dass die Variable immer nur eine Zeichenfolge sein sollte. Ich bin jedoch der Meinung, dass dies beim Lesen des Codes zu Problemen führen kann ).

In einigen Sprachen ist es auch möglich, so etwas wie diesen Pseudocode zu schreiben, um eine Klasse aus einer Zeichenfolgeneingabe zu initialisieren:

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

Zweitens geht die explizite Eingabe auch mit der Speicherzuweisung einher. Ein int ist immer so viele Bytes. Eine PhoneNumber besteht aus so vielen Bytes. Der Compiler kann einen Speicherblock mit der entsprechenden Größe zuweisen, der später verwendet werden kann, ohne dass Sie sehen müssen, wie viel Speicherplatz für die Zuweisung eines Werts erforderlich ist.

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

Schließlich beseitigt es Verwirrung ... ist 123 eine ganze Zahl oder eine vorzeichenlose ganze Zahl? Sie benötigen die gleiche Anzahl von Bytes, aber der in Variablen beider Typen gespeicherte Maximalwert ist sehr unterschiedlich ...

Dies bedeutet nicht, dass explizit besser ist als implizit - aber das Sprachdesign basiert auf diesen Auswahlmöglichkeiten, und C # würde bei impliziter Typisierung anders funktionieren. PHP und Javascript würden bei expliziter Eingabe anders funktionieren.

HorusKol
quelle
5

Weil Sam schlauer ist als Compiler. Wenn Sie beispielsweise sagen, dass Sie mir die Telefonnummer geben, geben Sie nicht an, ob Sie die Ländervorwahl oder die Vorwahl haben möchten, ob es sich um eine Geschäftsnummer handelt, für die nur die letzten 4 Ziffern erforderlich sind. Auch wenn Sie nach der Nummer des örtlichen Pizzakneipens fragen, können Sie sich mit der Antwort "pizza4u" auseinandersetzen.

Sam, findet es aus dem Kontext heraus. Während der Compiler es auch aus dem Kontext herausfinden kann, wird Sam es besser können (und in der Lage sein, den Prozess zu unterbrechen, um nach einer Klärung zu fragen).

Es gibt zwei grundlegende Ansätze für Typen und Variablen: Entweder hat die Variable einen Typ. In diesem Fall sind Aktionen, die vom Typ nicht zugelassen sind, verboten und verhindern die Kompilierung, oder der Wert hat einen Typ und Aktionen, die vom Typ nicht zugelassen sind Typ werden zur Laufzeit abgefangen.

Jeder Ansatz hat seine Vor- und Nachteile. Im Allgemeinen versuchen Compiler-Autoren, die Nachteile zu minimieren und die Vorteile zu maximieren. Aus diesem Grund ermöglicht var phoneNumber = GetPhoneNumber();und leitet C # den Typ der phoneNumber aus der Signatur von GetPhoneNumber ab. Das heißt, Sie müssen den Typ für die Methode deklarieren, aber nicht die Variable, die das Ergebnis empfängt. Auf der anderen Seite gibt es verschiedene Arten von Hinweisen / Durchsetzungsprojekten für Javascript. Alles ist ein Kompromiss.

jmoreno
quelle
3

Es ist eine Frage der Art und Weise, wie die Daten gespeichert werden. Ihre Interaktion mit Sam würde einen besseren Vergleich ergeben, wenn Sie darum bitten, dass Sie es aufschreiben könnten, aber nur Papier im Wert von acht Zeichen haben.

"Sam, gib mir die Telefonnummer."

"5555555555"

"Oh nein, ich habe kein Papier mehr. Wenn ich nur vorher gewusst hätte, wie viele Daten ich angefordert habe, hätte ich sie besser aufbereiten können!"

In den meisten Sprachen müssen Sie stattdessen einen Typ deklarieren, damit dieser im Voraus weiß und sich vorbereitet:

"Sam, wie lange ist eine Telefonnummer?"

"Zehn Zeichen."

"Okay, dann lass mich ein größeres Stück Papier holen. Jetzt gib mir die Telefonnummer."

"5555555555"

"Verstanden! Danke Sam!"

Noch haariger wird es, wenn man sich die grundlegenden Arten der Datenspeicherung ansieht. Wenn Sie wie ich sind, haben Sie ein Notizbuch mit verschiedenen Notizen, nur notierten Zahlen, keinem Kontext oder Beschriftungen für irgendetwas, und drei Tage später haben Sie keine Ahnung, was dies bedeutet. Dies ist auch für Computer häufig ein Problem. Viele Sprachen haben "int" -Typen (int, long, short, byte) und "float" -Typen (float, double). Warum ist das notwendig?

Schauen wir uns zunächst an, wie eine Ganzzahl gespeichert und im Allgemeinen im Computer dargestellt wird. Sie wissen wahrscheinlich, dass auf der Basisebene alles binär ist (Einsen und Nullen). Binär ist eigentlich ein Zahlensystem, das genau wie unser Dezimalzahlensystem funktioniert. In der Dezimalzahl zählen Sie 0 bis 9 (mit unendlichen implizierten führenden Nullen, die Sie nicht schreiben), dann rollen Sie zurück auf 0 und erhöhen die nächste Ziffer, so dass Sie 10 haben. Sie wiederholen, bis Sie von 19 auf 20 rollen, Wiederholen Sie diesen Vorgang, bis Sie von 99 auf 100 gewechselt haben.

Binär ist nicht anders, außer dass Sie anstelle von 0 bis 9 0 bis 1 zählen. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Wenn Sie also 9 eingeben, wird der Speicher binär aufgezeichnet als 1001. Dies ist eine tatsächliche Zahl. Es kann in genau dieser Form addiert, subtrahiert, multipliziert usw. werden. 10 + 1 = 11. 10 + 10 = 100 (1 auf 0 rollen und 1 tragen). 11 × 10 = 110 (und äquivalent 11 + 11 = 110).

Jetzt gibt es im eigentlichen Speicher (einschließlich der Register) eine Liste, ein Array, wie auch immer Sie es nennen möchten, von Bits (potenzielle Einsen oder Nullen) direkt nebeneinander. Auf diese Weise werden diese Bits logisch organisiert, um eine zu erstellen Zahl größer als 1. Problem ist, was machst du mit Dezimalstellen? Sie können nicht einfach ein Stück Hardware zwischen die beiden Bits im Register einfügen, und es würde viel zu viel kosten, zwischen jedem Bitpaar "Dezimalbits" einzufügen. Also, was ist zu tun?

Sie kodieren es. Im Allgemeinen bestimmt die Architektur der CPU oder der Software, wie dies durchgeführt wird. Eine übliche Methode besteht jedoch darin, ein Vorzeichen (+ oder -, im Allgemeinen 1 ist negativ) im ersten Bit des Registers, einer Mantisse, zu speichern (Ihre Nummer ist verschoben Es muss jedoch häufig erforderlich sein, die Dezimalzahl für die folgende X-Anzahl von Bits und einen Exponenten (die Anzahl der Verschiebungen) für den Rest zu entfernen. Es ähnelt der wissenschaftlichen Notation.

Durch die Eingabe kann der Compiler erkennen, worauf es ankommt. Stellen Sie sich vor, Sie haben den Wert 1,3 in Register 1 gespeichert. Wir werden hier nur unser eigenes ausgefallenes Codierungsschema entwickeln, 1 Bit für das Vorzeichen, 4 für die Mantisse, 3 für den Exponenten (1 Bit für das Vorzeichen, 2 für die Größe). Dies ist eine positive Zahl, daher ist das Vorzeichen positiv (0). Unsere Mantisse wäre 13 (1101) und unser Exponent wäre -1 (101 (1 für negativ, 01 = 1)). Also speichern wir 01101101 in Register 1. Jetzt haben wir diese Variable nicht mehr eingegeben. Wenn die Laufzeitumgebung sie verwendet, heißt es "sicher, das ist eine ganze Zahl, warum nicht". Wenn also der Wert ausgegeben wird, wird 109 (64 +) angezeigt 32 + 8 + 4 + 1), was offensichtlich nicht richtig ist.

Es ist jedoch nicht für jede Sprache erforderlich, dass Sie explizit eingeben. C # hat ein Schlüsselwort "var", das bewirkt, dass der Variablentyp beim Kompilieren interpretiert wird, und andere Sprachen wie Javascript werden vollständig dynamisch typisiert, bis Sie eine Ganzzahl in einer Variablen speichern und sie dann einem Booleschen Wert zuweisen können Weisen Sie es erneut einer Zeichenfolge zu, und die Sprache behält alles im Auge.

Der Compiler, der Interpreter oder die Laufzeit sind jedoch viel einfacher - und dies führt häufig zu einem schnelleren Programm, da keine wertvollen Ressourcen für die Eingabe von Daten aufgewendet werden müssen Daten, die Sie geben.

Devsman
quelle
2

Es gibt Programmiersprachen, in denen Sie keine Datentypen für Ihre Variablen deklarieren müssen. Es gibt sogar Programmiersprachen, in denen Sie Variablen nicht vorher deklarieren müssen. Sie können einfach verwenden sie, sofort.

Das Problem, dass Variablennamen nicht deklariert werden, besteht darin, dass Sie versehentlich eine neue, völlig unabhängige Variable erstellt haben, wenn Sie den Namen einer Variablen versehentlich falsch geschrieben haben. Also , wenn Sie Ihr Programm ausführen, können Sie nicht herausfinden , warum die Hölle , dass Variable , die Sie plötzlich nichts in ihm aufgebaut ... Bis nach vielen Stunden Debuggen, merkt man den verdammten Namen falsch eingegeben! GRRR !!

Sie haben es also so gemacht, dass Sie die Variablennamen, die Sie verwenden möchten, vorher deklarieren müssen . Und jetzt, wenn Sie einen falschen Namen eingeben, erhalten Sie einen Fehler beim Kompilieren, der Ihnen sofort genau sagt , wo der Fehler ist, bevor Ihr Programm überhaupt ausgeführt wird. Ist das nicht so viel einfacher?

Gleiches gilt für Datentypen. Es gibt Programmiersprachen, in denen Sie nicht deklarieren müssen, welcher Typ die Dinge sein sollen. Wenn Sie eine customerVariable haben, die eigentlich nur der Name eines Kunden ist, nicht das gesamte Kundenobjekt, funktioniert der Versuch, die Kundenadresse aus einer einfachen gewöhnlichen Zeichenfolge abzurufen, nicht. Der gesamte Punkt der statischen Typisierung ist, dass das Programm nicht kompiliert werden kann. es wird sich lautstark beschweren und auf den genauen Ort hinweisen, an dem das Problem liegt. Das ist viel schneller, als den Code auszuführen und herauszufinden, warum zum Teufel das nicht funktioniert.

All dies sind Funktionen, die dem Compiler mitteilen, was Sie beabsichtigt haben, damit er überprüfen kann, was Sie tatsächlich getan haben, und sicherstellen kann, dass es sinnvoll ist. Dies ermöglicht es dem Compiler, automatisch Fehler für Sie zu lokalisieren, was eine große Sache ist.

(Früher mussten Sie keine Unterroutinen deklarieren . Sie mussten nur GOSUBeine bestimmte Zeilennummer angeben. Wenn Sie Informationen zwischen Unterroutinen weitergeben möchten, würden Sie bestimmte globale Variablen festlegen, Ihre Unterroutine aufrufen und dann andere untersuchen Variablen, wenn das Unterprogramm zurückkehrt, aber das macht es erschreckend einfach, zu vergessen, einen der Parameter zu initialisieren. Daher verlangen heutzutage fast alle modernen Programmiersprachen, dass Sie deklarieren, welche tatsächlichen Parameter ein Unterprogramm annimmt, damit wir überprüfen können, ob Sie sie alle angegeben haben. )

MathematicalOrchid
quelle
1
In C ++ können Sie "auto x = 1" setzen und es weiß, dass es ein int ist. auto y = 1,2; auto z = 'Z'; etc
QuentinUK
@QuentinUK In C # können Sie var x=1mit ähnlichen Ergebnissen setzen. Aber das ist nichts; In Haskell können Sie Ihr gesamtes Programm ohne Typensignaturen schreiben, es ist jedoch statisch geschrieben. Wenn Sie einen Fehler machen, erhalten Sie trotzdem Fehler ... (Nicht unbedingt Mainstream.)
MathematicalOrchid
@QuentinUK Aber wenn Sie for (auto i=0; i<SomeStdVector.size(); ++i)Ihren Linter schreiben, wird er sich beschweren, weil er einen signierten Typ abgeleitet hat, und Sie fahren fort, ihn mit einem nicht signierten Typ zu vergleichen. Sie müssen schreiben auto i=0ul(geben Sie die Typinformationen explizit erneut ein, schreiben Sie also einfach size_t i=0an erster Stelle).
Dmckee
1

Wenn ich normale englische Sprache verwende, muss ich PhoneNumber nicht als int deklarieren, um es zu verwenden. Wenn ich zum Beispiel meinen Freund Sam nach seiner Telefonnummer frage, sage ich:

"Sam gib mir die Telefonnummer"

Ich würde nicht sagen>

"Char (20) Sam gib mir die int phoneNumber"

Warum müssen wir überhaupt den Datentyp angeben?

Kommen Sie zu MathOverflow oder Theoretical Computer Science und lesen Sie eine Weile, um eine Vorstellung davon zu bekommen, wie Menschen Alogrithmen miteinander kommunizierten, um sicherzustellen, dass es keine Möglichkeit für Missverständnisse gibt. Oder lesen Sie den Standard für eine ausgereifte Programmiersprache.

Sie werden feststellen , dass die Definition , welche Arten von Werten zu einem Begriff erlaubt ist Teil wirklich präzise Kommunikation auch von Mensch zu Mensch üben.

Was Sie bemerkt haben, ist, dass die alltäglichen Interaktionen ziemlich regelmäßig sind und dass Menschen ziemlich fehlertolerant sind, so dass ein Missverständnis über Telefonnummern im Allgemeinen durch das gemeinsame Wissen der Teilnehmer vermieden wird.

Aber haben Sie jemals versucht, eine Telefonnummer für jemanden in einem anderen Land zu notieren? Haben sie Ihnen ausdrücklich gesagt, wie oft Sie auf Null drücken müssen, um zur internationalen Adressierung zu gelangen? Haben sie Ihnen ihre Landesvorwahl mitgeteilt? Hast du es als solches erkannt? Wie viele Stellen haben Sie erwartet? Wie viele hast du bekommen? Wussten Sie, wie man die Ziffern gruppiert? Oder auch wenn die Gruppierung Bedeutung hat?

Plötzlich ist das Problem viel schwerer und Sie haben wahrscheinlich viel mehr Sorgfalt darauf verwendet, explizit zu überprüfen, ob die empfangene Nummer so verstanden wurde, wie es der Absender meinte.

dmckee
quelle
0

Ein weiterer Grund für die Angabe von Typen ist die Effizienz. Während eine Ganzzahl in 1 Byte oder 2 Byte oder 4 Byte gespeichert werden kann, kann ein Programm, das eine sehr große Anzahl von Variablen verwendet, den vierfachen Speicherbedarf haben, je nachdem, was gerade ausgeführt wird. Nur der Programmierer weiß, ob ein kleinerer Speicherplatz sinnvoll ist, und kann dies durch Angabe des Typs sagen.

Dynamisch getippte Objekte ermöglichen auch viele mögliche Typen im laufenden Betrieb. Dies könnte etwas Aufwand "unter der Haube" verursachen und das Programm verlangsamen, verglichen mit dem Festhalten an einem Typ.

donjuedo
quelle
0

In einigen frühen Programmiersprachen (insbesondere in Fortran) mussten Sie vor der Verwendung keine Variablen deklarieren.

Dies führte zu einer Reihe von Problemen. Eine wirklich offensichtliche ist, dass der Compiler einfache typografische Fehler nicht mehr annähernd so zuverlässig abfangen kann. Wenn Sie Code haben, der eine vorhandene Variable ändern soll, aber einen Tippfehler aufweist, haben Sie immer noch absolut legitimen Code, der gerade eine neue Variable erstellt (und einen Wert zugewiesen) hat:

longVariableName = 1

// ...

longVaraibleName = longvariableName + anotherLongVariableName

Wenn ich dies isoliert betrachte, da ich bereits einen Tippfehler als Quelle des Problems erwähnt habe, ist es wahrscheinlich ziemlich einfach, den Tippfehler und das Problem hier zu finden. In einem langen Programm, in dem dies inmitten vieler anderer Codes vergraben ist, ist es viel einfacher, es zu übersehen.

Sogar gegenwärtig mit vielen dynamisch getippten Sprachen können Sie immer noch ziemlich leicht das gleiche Grundproblem bekommen. Einige haben die Möglichkeit, Sie zu warnen, wenn Sie eine Variable zuweisen, aber lesen Sie sie nie (was heuristisch einige Probleme wie dieses aufwirft), beide andere haben solche Dinge nicht.

Jerry Sarg
quelle
0

Wenn Sie eine Variable deklarieren, wird Speicherplatz im Speicher zugewiesen, aber der Computer (in diesem Fall der Computer) weiß noch nicht, wie viel Speicherplatz für diese Variable zugewiesen werden muss.

Beispiel: - Sie erstellen ein Programm, das den Benutzer auffordert, eine beliebige Nummer einzugeben. In diesem Fall müssen Sie einen Datentyp angeben, um diese Nummer zu speichern. Andernfalls kann der Computer nicht selbst beurteilen , ob er 2 Bytes oder 2 Gigabytes zuweisen soll , wenn er dies versucht Wenn Sie die Zuordnung selbst vornehmen, kann dies zu einer ineffizienten Speichernutzung führen. Wenn Sie dagegen den Datentyp in Ihrem Programm angeben, weist die Maschine nach der Kompilierung den erforderlichen Speicherplatz zu.

Atul170294
quelle
dies scheint nicht zu bieten alles wesentliche über gemacht Punkte und erläuterte vor 11 Antworten
gnat
1
Mücke, du solltest noch einmal alle Antworten gründlich durchlesen und sehen, dass ich versucht habe, diese Frage auf eine viel einfachere Art und Weise zu beantworten, die man leicht verstehen kann.
Atul170294
Ich habe gerade wieder geprüft letzten drei Antworten , die etwa eine Stunde gebucht wurden vor dieser und alle drei scheinen den gleichen Punkt zu machen und per meiner Lektüre erklären es auf einfachere Weise als hier
gnat
Obwohl ich nicht für die Belohnung Ihrer Stimme geantwortet habe , denke ich, dass Sie eine Sache kennenlernen sollten, sollten Sie eine Antwort ablehnen, weil sie unbrauchbare oder falsche Informationen geben kann und wenn sie etwas Anstößiges enthält. Alle Antworten mit den nützlichsten und relevantesten Informationen erhalten eine höhere Anzahl von Upvotes, die ausreichen, um zwischen einer Antwort, einer guten Antwort und der besten Antwort zu unterscheiden. Ihre kindische Aktivität, eine Antwort ohne triftigen Grund abzustimmen, wird andere Leute nur entmutigen, die auch ihre Meinung teilen möchten, von der sie denken, dass sie für andere nützlich sein könnte
Atul170294
1
Ihre Antwort wurde höchstwahrscheinlich abgelehnt, weil sie nicht korrekt ist. Zur Unterstützung der Speicherverwaltung ist keine statische Typisierung erforderlich. Es gibt viele Sprachen, die dynamisches Schreiben ermöglichen, und diese Sprachen / Umgebungen sind in der Lage, die von Ihnen erwähnten Speicherverwaltungsprobleme zu lösen.
Jay Elston