W większości języków kodowania (jeśli nie wszystkie) należy zadeklarować zmienne. Na przykład w C #, jeśli to pole liczbowe, to
int PhoneNumber
Jeśli używam normalnego języka angielskiego, nie muszę deklarować, PhoneNumber
że int
go używam. Na przykład, jeśli poproszę mojego przyjaciela Sama o podanie mi jego numeru telefonu, mówię:
„Sam daj mi numer telefonu”
Nie powiedziałbym
„Char (20) Sam daj mi numer telefonu wewnętrznego”
Dlaczego w ogóle musimy określać typ danych?
programming-languages
Dick Smith
źródło
źródło
Odpowiedzi:
To są dwa niezależne pytania:
Nawiasem mówiąc, odpowiedź na oba pytania brzmi: my nie.
Istnieje wiele statycznie wpisywanych języków programowania, w których nie trzeba deklarować typów. Kompilator może wywnioskować typy z otaczającego kontekstu i użycia.
Na przykład w Scali można powiedzieć
lub możesz po prostu powiedzieć
Oba są dokładnie równoważne: kompilator wywnioskuje typ
Int
z wyrażenia inicjującego23
.Podobnie w języku C♯ możesz powiedzieć jedno z nich i oba oznaczają dokładnie to samo:
Ta funkcja nosi nazwę wnioskowania typu i ma ją wiele języków poza Scalą i C♯: Haskell, Kotlin, Ceylon, ML, F♯, C ++. Nawet Java ma ograniczone formy wnioskowania typu.
W dynamicznie wpisywanych językach programowania zmienne nawet nie mają typów. Typy istnieją tylko dynamicznie w czasie wykonywania, a nie statycznie. Tylko wartości i wyrażenia mają typy, a tylko w czasie wykonywania zmienne nie mają typów.
Np. W ECMAScript:
I wreszcie, w wielu językach, nie musisz nawet deklarować zmiennych. np. w Ruby:
W rzeczywistości ten ostatni przykład obowiązuje w wielu językach programowania. Dokładnie taki sam wiersz kodu działałby również na przykład w Pythonie.
Więc,
źródło
auto i = 1 // i is inferred to type int
,vector<int> vec; auto itr = vec.iterator(); // itr is inferred to type vector<int>::iterator
i tak dalej. Jeśli chcesz wiedzieć, jak to dokładnie działa, możesz to sprawdzić w specyfikacji.Kiedy używasz języka naturalnego do odnoszenia się do informacji, nie jest to bardzo precyzyjne, a w szczególności nie przekazuje innym informacji o twoich zamiarach. Podobne problemy występują podczas próby wykonywania matematyki w języku naturalnym: po prostu nie jest wystarczająco precyzyjna.
Programowanie jest złożone; błędy są zbyt łatwe do znalezienia. Typy są częścią systemu kontroli zaprojektowanego w celu zapobiegania nielegalnym stanom programu poprzez wykrywanie warunków błędów. Różne języki używają typów w różny sposób: niektóre języki intensywnie używają typów do wykrywania błędów w czasie kompilacji. Prawie wszystkie języki mają pewne pojęcie niekompatybilnych typów jako błąd środowiska wykonawczego. Zwykle błąd typu wskazuje na jakiś błąd w programie. Gdy zezwalamy na kontynuowanie programów pomimo błędów, prawdopodobnie otrzymujemy bardzo złe odpowiedzi. Wolimy zatrzymać program niż otrzymywać złe lub niepoprawne odpowiedzi.
Innymi słowy, typy wyrażają ograniczenia w zachowaniu programu. Ograniczenia, gdy są egzekwowane przez jakiś mechanizm, dają gwarancje. Takie gwarancje ograniczają zakres rozumowania niezbędny do myślenia o programie, tym samym upraszczając zadanie czytania i utrzymywania programu dla programistów. Bez typów i ich implikacji narzędzi (tj. Kompilatora), które wykrywają błędy typu, obciążenie programistyczne jest znacznie wyższe, a zatem bardziej kosztowne.
Prawdą jest, że (wielu) ludzi łatwo rozróżnia europejski, amerykański i międzynarodowy numer telefonu. Jednak komputer tak naprawdę nie „myśli” i wybrałby numer telefonu Stanów Zjednoczonych w Europie lub odwrotnie. Na przykład typy są dobrym sposobem na rozróżnienie tych przypadków bez konieczności uczenia komputera, jak „myśleć”. W niektórych językach możemy otrzymać błąd czasu kompilacji podczas próby zmiksowania europejskiego numeru telefonu w amerykańskim systemie telefonicznym. Ten błąd mówi nam, że musimy zmodyfikować nasz program (być może poprzez konwersję numeru telefonu na międzynarodową sekwencję wybierania numerów lub, zamiast tego, używając numeru telefonu w Europie), zanim jeszcze spróbujemy uruchomić program.
Ponadto, ponieważ komputer nie myśli, nazwa pola lub zmiennej (np.
phonenumber
) Nic dla komputera nie znaczy. Dla komputera ta nazwa pola / zmiennej to po prostu „blah123”. Pomyśl, jak wyglądałby twój program, gdyby wszystkie zmienne były „blahxxx”. Yikes. Tak właśnie widzi komputer. Podanie typu daje komputerowi pojęcie o znaczeniu zmiennej, którego po prostu nie może wywnioskować z samej nazwy.Ponadto, jak mówi @Robert, w wielu współczesnych językach nie musimy określać typów tak, jak robiliśmy to w dawnych czasach, ponieważ języki takie jak C # wykonują „wnioskowanie o typie”, czyli zbiór reguł określających właściwy typ dla zmiennej w kontekście. C # zapewnia wnioskowanie typu tylko na zmiennych lokalnych, ale nie na parametrach formalnych ani polach klasy lub instancji.
źródło
Types are part of a system of checks that ...
ponieważ odpowiada on bezpośrednio POWhy do we have to specify data type at all?
…static member add x y = x + y
,member x.Append s = x.Text + s
. W pierwszym przypadku,x
iy
będą wywodzić sięint
dlatego, dodawania. W drugim przypadku będą to, co jest poprawne, w zależności od typux.Text
- jeśli tostring
, to równieżs
będziestring
. Zgadzam się jednak, że adnotacje typu są dokumentacją.Oprócz innych odpowiedzi, należy uwzględnić jedną rzecz. Pamiętaj, że komputery to tylko bity. Powiedz, że podaję bajty:
Co oznacza, że średni ? Jest przechowywany w ten sposób przez komputer, ale bez żadnej interpretacji, to tylko fragmenty . Mogą to być 4 znaki ascii. Może to być liczba całkowita. Mogą to być niektóre bajty w tablicy. Może być częścią obiektu. Może to być wskaźnik do miejsca buforowania tego wideo kota. Prawie wszystkie języki programowania od asemblera do góry potrzebują czegoś, aby wiedzieć, jak interpretować bity, aby mogły wykonywać sensowne obliczenia.
A ponieważ komputer nie zna znaczenia tych bitów, musisz to powiedzieć - albo wprost za pomocą adnotacji typu, albo pośrednio poprzez mechanizmy wnioskowania typu wspomniane w innych odpowiedziach.
źródło
Odpowiedź na pytanie, dlaczego komputery potrzebują tych informacji, ma związek z reprezentacją danych .
Nazwa „typu danych” odnosi się do reguł, które pomagają komputerowi przechowywać i pobierać informacje z jego stanu surowego zer i jedynek w pamięci komputera.
Na przykład twój zwykły 8-bitowy znak ASCII byłby przechowywany w pamięci komputera (RAM lub Dysk) jako
01000001
(wielkie litery „A”, kod ASCII 65) lub00001000
(znak procentu) lub dowolne kombinacje zer i 1 w tych 8 bitach.W innym przykładzie niektóre 8-bitowe liczby całkowite bez znaku mogą być przechowywane jako
00000101
(liczba 5) lub00001000
(liczba 8)Zauważ, że binarna reprezentacja 8 i znaku% może być taka sama, ale oznaczają one różne rzeczy, ponieważ ich typy są różne.
Nawet języki, które wnioskują o typie danych, mogą nie mieć reguły, że „wszystkie typy zmiennych muszą być zadeklarowane przez programistę”, mają reguły takie jak „jeśli twoja seria znaków jest ujęta w cudzysłów, jest to ciąg znaków” i wiele innych reguł dla każdego typu danych.
Więc nawet te potrzebują typów danych, aby zrozumieć, co oznaczają cyfry 0 i 1, więc mogą na przykład wykonać funkcję konkatenacji ciągu, jeśli spróbujesz „dodać” dwa znaki lub dodać liczbę całkowitą, jeśli spróbujesz dodać dwie liczby całkowite .
W swojej historii też, powiedzmy, że nie prosiłem Sama o numer telefonu, ale Sam daje kawałek papieru, który ma „1123581321” na niej napisane. Nie możesz mieć pewności, czy Sam jest fanem pierwszych ośmiu liczb Fibonacciego, czy jest to numer telefonu. Aby zgadnąć, musisz wziąć pod uwagę kontekst i dostępne wskazówki, takie jak być może poprosiłeś Sama o numer telefonu dzień temu lub notatkę z napisem „Zadzwoń do mnie” lub jeśli policzysz cyfry i znajdziesz pasuje do wzorców większości numerów telefonów. Dopiero wtedy będziesz wiedział, że jest to numer telefonu, pod który możesz zadzwonić, a nie kilka cyfr, które wybiłbyś do kalkulatora.
Zwróć uwagę, że te wskazówki, które doprowadziły cię do przypuszczenia, że numer był numerem telefonu, są podobne do tego, w jaki sposób wskazówki prowadzą do języka komputera, który nie wymaga deklaracji w celu wywnioskowania typu wartości.
źródło
W niektórych językach nie trzeba określać typu danych.
Języki, w których obsługiwane jest wnioskowanie o typie, zazwyczaj mogą dowiedzieć się, jaki typ danych ma zastosowanie. Na przykład,
jest wewnętrznie wpisany jako ciąg, ponieważ wartość jest otoczona cudzysłowami.
Niektóre języki również nie wymagają deklarowania zmiennej; zmienna jest tworzona przy pierwszym użyciu. Uważa się jednak, że najlepszą praktyką jest szczegółowe deklarowanie zmiennych z wielu ważnych powodów; głównie dlatego, że robienie tego lepiej wyraża Twoją intencję.
źródło
var name = "Ali"
styl jest właściwie wspólny dla współczesnych języków o typie statycznym . W językach o typie statycznym typ jest ustalany podczas tworzenia, ale nadal można go określić za pomocą inicjatora. Definicja języka o typie dynamicznym polega na tym, że typy dołączają się do wartości, a nie do zmiennych. Przypisanie wartości do zmiennej ustawia zatem również typ zmiennych.var x = 5; x = "";
ponieważ pierwsza instrukcja powodujex
skojarzenie typu „Liczba”x
? Rodzaj konfliktów z dynamicznym pisaniem . A jeśli nie, jaki wpływ ma typ powiązany ze zmienną, poza powiązaniem typu z wartością?x = "";
zmienia typ x na ciąg znaków, nawet jeśli poprzednio była liczbą.Ponieważ tak określa projekt języka. Aby odpowiedzieć na twoje pytanie, musimy przyjrzeć się celom jawnego pisania w językach takich jak C # i C ++. (C # robi to, ponieważ robi to C ++, ponieważ robi to C, więc musimy spojrzeć na to, co było w tamtym czasie).
Po pierwsze, pisanie jawne i statyczne zapewnia rygorystyczne kodowanie - określenie zmiennej jako liczby całkowitej oznacza, że kompilator i oprogramowanie powinny być zaskoczone i zgłaszać błąd podczas przypisywania znaku lub łańcucha do zmiennej. Pisanie dynamiczne może powodować ból głowy dla nieostrożnych (wystarczy spojrzeć na PHP lub podejście javascripts do prawdziwości takich rzeczy jak tablice i puste ciągi znaków).
Możesz mieć statyczne z niejawnym pisaniem - inicjowanie zmiennej jako ciąg oznacza, że zmienna powinna być zawsze ciągiem, ale mam wrażenie, że może to powodować problemy dla ludzi czytających kod (zazwyczaj zakładam, że pisanie dynamiczne jest niejawne ).
Ponadto w niektórych językach można napisać coś takiego jak ten pseudokod, aby zainicjować klasę na podstawie ciągu znaków:
Po drugie, wyraźne pisanie idzie w parze z alokacją pamięci. Liczba całkowita to zawsze tyle bajtów. Numer telefonu to tyle bajtów. Kompilator może przypisać blok pamięci o odpowiednim rozmiarze, który może być później wykorzystany bez konieczności sprawdzania, ile miejsca będzie potrzebować po przypisaniu wartości.
Wreszcie usuwa zamieszanie ... czy 123 jest liczbą całkowitą czy liczbą całkowitą bez znaku? Potrzebują tej samej liczby bajtów, ale maksymalna wartość przechowywana w zmiennych dowolnego typu jest bardzo różna ...
Nie oznacza to, że jawne jest lepsze niż niejawne - ale projekt języka opiera się na tego rodzaju wyborach, a C # działałby inaczej z niejawnym pisaniem. PHP i javascript działałyby inaczej z jawnym pisaniem.
źródło
Ponieważ Sam jest mądrzejszy niż kompilatory. Na przykład, kiedy mówisz „daj mi numer telefonu”, nie określasz, czy chcesz prefiks kraju, czy numer kierunkowy, czy jest to numer służbowy, w którym wymagane są tylko 4 ostatnie cyfry. Ponadto, jeśli poprosisz o numer lokalnego pizzy, możesz poradzić sobie z odpowiedzią „pizza4u”.
Sam, wymyśla to z kontekstu. Chociaż kompilator może to również zrozumieć na podstawie kontekstu, Sam będzie w tym lepszy (i jest w stanie przerwać proces, prosząc o wyjaśnienia).
Istnieją dwa podstawowe podejścia do typów i zmiennych, albo zmienna ma typ, w którym to przypadku akcje, które nie są dozwolone przez typ, są zabronione i uniemożliwiają kompilację, lub wartość ma typ i akcje, które nie są dozwolone przez typ zostanie przechwycony w czasie wykonywania.
Każde podejście ma swoje zalety i wady. Ogólnie rzecz biorąc, autorzy kompilatorów starają się minimalizować wady i maksymalizować zalety. Dlatego na przykład C # pozwala
var phoneNumber = GetPhoneNumber();
i wydedukuje typ phoneNumber na podstawie podpisu GetPhoneNumber. Oznacza to, że musisz zadeklarować typ metody, ale nie zmienną, która otrzyma wynik. Z drugiej strony istnieją różne typy podpowiedzi / egzekwowania dla javascript. Wszystko jest kompromisem.źródło
To kwestia sposobu przechowywania danych. Twoja interakcja z Samem byłaby lepszym porównaniem, gdybyś poprosił, żebyś mógł to zapisać, ale miał tylko osiem znaków papieru.
Zamiast tego większość języków sprawia, że deklarujesz typ, więc będzie wiedział i przygotuje się z wyprzedzeniem:
Staje się jeszcze bardziej włochaty, kiedy spojrzysz na rzeczywiste podstawowe sposoby przechowywania danych. Jeśli jesteś podobny do mnie, masz zeszyt z różnymi notatkami, po prostu zapisanymi cyframi, bez kontekstu lub etykietowania czegokolwiek i nie masz pojęcia, co to znaczy trzy dni później. Jest to często problem również dla komputerów. Wiele języków ma typy „int” (int, długi, krótki, bajt) i „float” (float, double). Dlaczego to konieczne?
Cóż, najpierw spójrzmy, jak liczba całkowita jest przechowywana i ogólnie reprezentowana w komputerze. Prawdopodobnie zdajesz sobie sprawę, że na poziomie podstawowym wszystko jest binarne (1 i 0). Binarny to w rzeczywistości system liczbowy, który działa dokładnie tak jak nasz system liczb dziesiętnych. W systemie dziesiętnym liczy się od 0 do 9 (z nieskończonymi domniemanymi zerami na początku, których nie piszesz), a następnie przewijasz z powrotem do 0 i zwiększasz kolejną cyfrę, tak abyś miał 10. Powtarzaj, aż przejdziesz z 19 do 20, powtarzaj, aż przejdziesz od 99 do 100 itd.
Binarny nie jest inny, z wyjątkiem tego, że zamiast 0 do 9, liczysz od 0 do 1. 0, 1, 10, 11, 100, 101, 110, 111, 1000. Więc kiedy wpiszesz 9, w pamięci zapisanej w binarnym jako 1001. Jest to liczba rzeczywista. Można go dodawać, odejmować, mnożyć itp. W dokładnie takiej formie. 10 + 1 = 11. 10 + 10 = 100 (przewiń 1 na 0 i przenieś 1). 11 x 10 = 110 (i równoważnie, 11 + 11 = 110).
Teraz w rzeczywistej pamięci (łącznie z rejestrami) znajduje się lista, tablica, jakkolwiek chcesz to nazwać, bitów (potencjalne 1 lub 0 ') tuż obok siebie, w ten sposób logicznie zorganizowane te bity tworzą liczba większa niż 1. Problem polega na tym, co robisz z miejscami po przecinku? Nie można po prostu wstawić elementu sprzętowego między dwa bity w rejestrze, a dodanie „bitów dziesiętnych” pomiędzy każdą parą bitów byłoby zbyt drogie. Co więc zrobić?
Kodujesz to. Zasadniczo architektura procesora lub oprogramowania określa, jak to się robi, ale jednym z powszechnych sposobów jest przechowywanie znaku (+ lub -, ogólnie 1 jest ujemny) w pierwszym bicie rejestru, mantysa (przesunięty numer jednak wiele razy trzeba pozbyć się przecinka dziesiętnego) dla następnej liczby bitów X i wykładnika (liczba razy, kiedy trzeba go przesunąć) dla pozostałej części. Jest podobny do notacji naukowej.
Wpisanie pozwala kompilatorowi wiedzieć, na co patrzy. Wyobraź sobie, że zapisałeś wartość 1,3 w rejestrze 1. Po prostu wymyślimy tutaj nasz własny fantazyjny schemat kodowania, 1 bit na znak, 4 dla mantysy, 3 dla wykładnika (1 bit na znak, 2 dla wielkości). Jest to liczba dodatnia, więc znak jest dodatni (0). Nasza mantysa wyniesie 13 (1101), a nasz wykładnik wyniesie -1 (101 (1 dla ujemnego, 01 = 1)). Więc przechowujemy 01101101 w rejestrze 1. Teraz nie wpisaliśmy tej zmiennej, więc kiedy środowisko wykonawcze przejdzie do jej użycia, mówi „jasne, to jest liczba całkowita, dlaczego nie”, więc kiedy wypisuje wartość, widzimy 109 (64 + 32 + 8 + 4 + 1), co oczywiście nie jest właściwe.
Jednak nie każdy język wymaga wyraźnego wpisania. C # ma słowo kluczowe „var”, które powoduje, że typ zmiennej jest interpretowany w czasie kompilacji, a inne języki, takie jak JavaScript, są całkowicie dynamicznie wpisywane, do tego stopnia, że można zapisać liczbę całkowitą w zmiennej, a następnie przypisać ją do wartości logicznej, a następnie przypisz go ponownie do łańcucha, a język będzie go śledził.
Ale kompilator, interpreter lub środowisko wykonawcze jest o wiele łatwiejsze - i często skutkuje szybszym programem, ponieważ nie musi on tracić cennych zasobów na sortowanie wszystkiego - na pytanie programisty, jaki rodzaj dane, które podajesz.
źródło
Istnieją języki programowania, w których nie trzeba deklarować typów danych dla zmiennych. Istnieją nawet języki programowania, w których nie trzeba wcześniej deklarować zmiennych; możesz ich natychmiast użyć .
Problem z niezadeklarowaniem nazw zmiennych polega na tym, że jeśli przypadkowo błędnie przeliterujesz nazwę zmiennej, teraz przypadkowo utworzyłeś nową, całkowicie niepowiązaną zmienną. Więc kiedy uruchamiasz swój program, nie możesz zrozumieć, dlaczego, do cholery, ta zmienna, którą ustawiłeś, nagle nie ma w sobie nic ... Dopóki po wielu godzinach debugowania nie zdasz sobie sprawy, że źle wpisałeś cholerną nazwę! GRRR !!
Więc zrobili to, więc musisz zadeklarować nazwy zmiennych, których będziesz używać wcześniej. A teraz, gdy źle wpiszesz nazwę, pojawi się błąd czasu kompilacji, który natychmiast powie ci dokładnie, gdzie jest błąd, zanim nawet Twój program uruchomi się. Czy to nie jest o wiele łatwiejsze?
To samo dotyczy typów danych. Istnieją języki programowania, w których nie musisz deklarować, jaki typ rzeczy powinien być. Jeśli masz
customer
zmienną, która w rzeczywistości jest tylko nazwą klienta, a nie całym obiektem klienta, próba pobrania adresu klienta ze zwykłego zwykłego ciągu ... nie zadziała. Cały sens pisania statycznego polega na tym, że program się nie skompiluje; głośno narzeka, wskazując dokładne miejsce, w którym występuje problem. To o wiele szybsze niż uruchamianie kodu i próbowanie zrozumienia, dlaczego, do diabła, nie działa.Wszystkie te funkcje informują kompilator o tym, co zamierzasz zrobić, dzięki czemu może sprawdzić, co faktycznie zrobiłeś, i upewnić się, że ma to sens. Dzięki temu kompilator może automatycznie lokalizować błędy, co jest dużym problemem.
(W odległej przeszłości nie musieliśmy deklarować podprogramów . Po prostu
GOSUB
pod konkretny numer linii. Jeśli chcesz przekazywać informacje między podprogramami, ustawiasz określone zmienne globalne, wywołujesz podprogram, a następnie sprawdzasz inne zmienne po powrocie podprogramu. Ale przerażająco łatwo jest zapomnieć o zainicjowaniu jednego z parametrów. Tak więc teraz prawie wszystkie współczesne języki programowania wymagają zadeklarowania, jakie rzeczywiste parametry przyjmuje podprogram, abyśmy mogli sprawdzić, czy podałeś je wszystkie. )źródło
var x=1
z podobnymi wynikami. Ale to nic; w Haskell, można napisać cały program bez podpisów typu w ogóle, ale to wszystko jest wpisane statycznie i nadal pojawiają się błędy, jeśli się pomylisz ... (choć nie dokładnie nurtu.)for (auto i=0; i<SomeStdVector.size(); ++i)
twój linter będzie narzekał, ponieważ wydedukował typ podpisany i przystąpisz do porównania go z typem niepodpisanym. Musisz pisaćauto i=0ul
(ponownie wpisując informacje o typie, więc po prostu napiszsize_t i=0
najpierw).Wejdź do MathOverflow lub Theoretical Computer Science i poczytaj przez chwilę, aby dowiedzieć się, w jaki sposób ludzie komunikowali się między sobą alogrithms, gdy chcą się upewnić, że nie ma możliwości nieporozumień. Lub przeczytaj standard dla dojrzałego języka programowania.
Przekonasz się, że określenie, jakie wartości są dozwolone dla danego terminu, jest częścią naprawdę precyzyjnej praktyki komunikacyjnej, nawet między ludźmi.
Zauważyłeś, że codzienne interakcje są dość regularne, a ludzie są dość odporni na winy, więc dzięki wspólnej wiedzy uczestników nie unika się nieporozumień dotyczących numerów telefonów.
Ale czy kiedykolwiek próbowałeś usunąć numer telefonu dla kogoś z innego kraju? Czy powiedzieli ci wprost, ile razy naciskasz zero, aby dostać się do adresowania międzynarodowego? Czy powiedzieli ci swój kod kraju? Czy rozpoznałeś to jako takie? Ile cyfr się spodziewałeś? Ile dostałeś? Czy wiesz, jak grupować cyfry? A nawet jeśli grupa ma znaczenie?
Nagle problem jest o wiele trudniejszy i zapewne o wiele bardziej starałeś się, aby wyraźnie sprawdzić, czy otrzymany numer został zrozumiany w sposób, w jaki nadawca go rozumiał.
źródło
Innym powodem deklarowania typów jest wydajność. Podczas gdy liczba całkowita może być zapisana w 1 bajcie, 2 bajtach lub 4, program wykorzystujący bardzo dużą liczbę zmiennych może zużywać czterokrotnie potrzebną pamięć, w zależności od tego, co zostanie zrobione. Tylko programista wie, czy mniejsze miejsce do przechowywania jest opłacalne, więc może to powiedzieć, deklarując typ.
Ponadto dynamicznie wpisywane obiekty pozwalają na wiele możliwych typów w locie. Mogłoby to spowodować pewne obciążenie „pod maską”, spowalniając program w porównaniu do trzymania się jednego rodzaju przez cały czas.
źródło
Wiele wczesnych języków programowania (zwłaszcza Fortran) nie wymagało deklarowania zmiennych przed użyciem.
Doprowadziło to do wielu problemów. Jedną naprawdę oczywistą jest to, że kompilator nie jest już w stanie wychwycić prostych błędów typograficznych prawie tak samo niezawodnie. Jeśli masz kod, który ma modyfikować istniejącą zmienną, ale ma literówkę, nadal masz całkowicie uzasadniony kod, który właśnie utworzył (i przypisał wartość) nowej zmiennej:
Teraz, patrząc na to osobno, ponieważ już wspomniałem o literówce jako źródle problemu, prawdopodobnie dość łatwo jest znaleźć literówkę i problem tutaj. W długim programie, w którym jest on ukryty w środku wielu innych kodów, o wiele łatwiej jest go przeoczyć.
Nawet obecnie z wieloma dynamicznie wpisywanymi językami wciąż możesz łatwo uzyskać ten sam podstawowy problem. Niektóre mają pewne możliwości ostrzeżenia cię, jeśli przypiszesz zmienną, ale nigdy jej nie czytaj (co heurystycznie łapie sporo takich problemów), a inne nie mają takich rzeczy.
źródło
Kiedy deklarujesz dowolną zmienną, część pamięci jest przydzielana w pamięci ,, ale maszyna (w tym przypadku komputer) nie wie już, ile miejsca musi zostać przydzielone dla tej zmiennej.
Przykład: - tworzysz program, który prosi użytkownika o wprowadzenie dowolnej liczby, w tym przypadku musisz określić typ danych, aby zapisać ten numer, w przeciwnym razie maszyna nie będzie w stanie sama ocenić, czy przydzieli 2 bajty lub 2 gigabajty , jeśli spróbuje samodzielne dokonanie alokacji może spowodować nieefektywne wykorzystanie pamięci. Z drugiej strony, jeśli określisz typ danych w swoim programie, to po kompilacji maszyna przydzieli odpowiednią przestrzeń zgodnie z potrzebą.
źródło