Jakich zasad można się nauczyć z języka C, których nie można się nauczyć w językach wyższego poziomu? [Zamknięte]
11
Wierzę, że C jest dobrym językiem do nauki zasad programowania. Czego możesz się nauczyć w językach niższego poziomu, które są „magiczne” od języków wysokiego poziomu, takich jak Ruby?
W każdym razie uczysz się magii lub jej części. Ponieważ C jest „bliżej metalu”, uczysz się więcej o metalu.
Robert Harvey,
1
Nigdy w pełni nie rozumiałem pojęcia odniesienia, dopóki nie spotkałem się z C ++.
user6245072,
6
C nauczy Cię, czym tak naprawdę jest przepełnienie stosu. Trudna droga.
david25272,
1
Chciałbym, aby nowi programiści zaczęli od nauki starego, dobrego Pascala i programowania strukturalnego. Nauczysz się wyrażać siebie logicznie i uporządkowany.
Wygięty
2
Czego uczą cię tylko C i C ++, to że kompilator jest twoim największym wrogiem.
CodesInChaos
Odpowiedzi:
9
Nie ma zasad, w ogólnym abstrakcyjnym znaczeniu informatyki, które są obecne w C, które nie są również obecne w językach wyższego poziomu. Cała informatyka sprowadza się do algorytmów, a wszystkie algorytmy można zaimplementować w dowolnym języku, który jest Turing-zupełny jak C.
Różnica, którą C przenosi poza języki wyższego poziomu, jest podobna do różnicy, którą kod maszynowy niesie poza C: Relacja maszyny do kodu.
Pisząc kod w językach wysokiego poziomu, nie musisz (ogólnie) martwić się interakcją kodu z maszyną. Maszyna wirtualna zdefiniowana przez język ukrywa wiele z tych aspektów wykonywania kodu.
W C interakcja twojego programu z pamięcią jest na pierwszym planie. To więcej niż tylko to, że musisz zarządzać wykorzystaniem sterty, obejmuje ona interakcję kodu ze stosem oraz sposób, w jaki sam dostęp pamięci do kodu wpływa na zachowanie i wydajność kodu - nawet na kolejność dostępu do pamięci można uniknąć uwagi, ponieważ czytanie niewłaściwej pamięci w niewłaściwym czasie może skutecznie osłabić wydajność.
W językach wyższego poziomu te rzeczy nie są tak oczywiste. Pamięć jest przydzielana i zwalniana bez Twojej wiedzy, a czasem bez Twojej prośby. Najczęściej jest to po prostu poza twoją kontrolą. Kiedy, gdzie, jak i dlaczego większość przydziałów pamięci jest po prostu ukryta przed tobą.
Podobnie, w innym kierunku, pisanie kodu maszynowego lub kodu asemblera przynosi jeszcze więcej szczegółów na pierwszy plan: prawie nic nie pozostaje poza twoim zakresem, a twój kod musi być napisany z uwzględnieniem każdej alokacji, każdego zasobu, każdej przekazywanej części danych poprzez rejestry procesora - wiedza tak daleko od języków wysokiego poziomu, że jest tajemna.
Nigdy do końca nie rozumiałem, dlaczego ludzie zawsze wspominają o kompletności Turinga w tego rodzaju dyskusjach. W tym kontekście kompletność Turinga nie ma znaczenia; C nie różni się pod tym względem od innych języków programowania, więc nie można się niczego nauczyć o kompletności Turinga, przechodząc na C. Jedynym momentem, w którym kompletność Turinga staje się istotna, jest omawianie czegoś, co nie jest kompletne Turinga, np. CSS lub HTML . Do diabła, jeśli zmrużysz wystarczająco mocno, nawet te są pełne Turinga . Bardziej sensowne pytania dotyczą użyteczności.
Robert Harvey
3
@RobertHarvey Chodzi mi o to, że dopóki język ma rozsądne minimum możliwości obliczeniowych, jego „poziom” staje się nieistotny z punktu widzenia algorytmów, które są jedynymi istotnymi w tym kontekście.
greyfade
3
Ponieważ robisz punkt, który jest całkowicie nieistotny dla pytania PO. Programiści robią to cały czas; rzucają się wokół frazy „Turing-complete”, tak jakby faktycznie miała sensowne zastosowanie w praktyce. Nie ma, poza zaznaczeniem, że to nie ma znaczenia.
Robert Harvey
2
<irony> Biologia to tylko szczególny przypadek chemii, który jest szczególnym przypadkiem fizyki cząstek. Nic nie możesz nauczyć się z biologii, jeśli znasz fizykę cząstek. Prawda? </irony>
Florian F
3
Warto zauważyć, że C wymaga po prostu wyraźnego przydzielenia przydziałów i zwolnień, ale wciąż dotyczą one abstrakcyjnej maszyny, podobnie jak w językach „wyższego poziomu” - fizyczna (np.) Maszyna x86 jest nadal poza zakresem C. może tworzyć idealnie piaskowatą maszynę wirtualną, która interpretuje kod C, ale nie ma kontroli nad alokacjami pamięci fizycznej maszyny i nadal może być implementacją w 100% zgodną.
Theodoros Chatzigiannakis,
13
Wiem, że C jest dobrym językiem do nauki zasad programowania.
Nie zgadzam się. C nie ma zbyt wielu funkcji, aby nauczyć się zasad programowania. Funkcje C do tworzenia abstrakcji są okropne, a abstrakcja jest jedną z kluczowych zasad programowania.
Jeśli chcesz się dowiedzieć, jak działa sprzęt, a co za tym idzie mechanicznej sympatii do maszyny, powinieneś nauczyć się kodu maszynowego, czyli architektury zestawu instrukcji, a także przestudiować budowę pamięci podręcznej nowoczesnych procesorów. Zauważ, że nie polecam języka asemblera, po prostu zapoznaj się z instrukcjami sprzętowymi, aby zrozumieć, co generuje kompilator.
Jeśli chcesz nauczyć się zasad programowania, użyj nowoczesnego języka, takiego jak Java, C # lub Swift, lub jednego z wielu innych, takich jak Rust. Studiuj także różne rodzaje paradygmatów programowania, w tym funkcjonalne.
C jest w porządku w tworzeniu abstrakcji. Możesz pisać metody w C i możesz spakować dane jako struktury w C. Całe systemy operacyjne zostały zbudowane przy użyciu C. To, w czym C nie jest dobry, to zaspokajanie „nowoczesnego” wyobrażenia o tym, jak powinna wyglądać orientacja obiektowa lubić.
Robert Harvey,
4
Nie do końca. C jest nieco wyższy niż ASM. Nie spodziewaj się, że użyjesz w nim klas, choć są na to sposoby , jeśli masz na to ochotę.
Robert Harvey,
4
Zamień „Brainfuck” na „asembler” w swoim komentarzu i nadal powinno to być prawdą. Ale to nie znaczy, że niedługo będę używać Brainfuck.
Robert Harvey,
6
Twój argument o funkcjach C naprawdę ma sens tylko wtedy, gdy uważasz, że klasy (i wyrzucanie elementów bezużytecznych itp.) Są niezbędnym elementem nauczania nowego programisty (czego ja nie). Nikt tutaj nie opowiada się za wykorzystaniem klas w języku bezklasowym.
Robert Harvey,
5
@Robert, moim argumentem jest to, że C jest językiem niższego poziomu i jako taki nie jest najlepszym językiem do zrozumienia zasad programowania, co możemy również powiedzieć o asemblerze, a to, że są to języki niższego poziomu, nie oznacza są one w jakiś sposób bliższe „prawdziwym” zasadom programowania. Języki te lepiej rozumieją, jak działa sprzęt i systemy operacyjne, a jeśli o to chodzi, zalecam przejście do najniższego poziomu w nauce architektury zestawu instrukcji i języka maszynowego. W przeciwnym razie istnieje wiele języków do wyboru.
C nie jest wyjątkiem od powyższej reguły. Jest to opisane jako abstrakcyjna maszyna, która nie ma pojęcia o twoim rzeczywistym sprzęcie.
Jako takie, gdy ludzie mówią, że C uczy cię, jak naprawdę działa komputer, zwykle oznaczają, że C uczy, jak działa C. Ale C, ponieważ jest tak wszechobecny w programowaniu systemów, jest zrozumiałe, że wiele osób zaczyna mylić go z samym komputerem. I osobiście posunąłbym się nawet do stwierdzenia, że wiedza o tym, jak działa C, jest często ważniejsza niż wiedza o tym, jak działa sam komputer.
Ale C i komputer to różne rzeczy. Rzeczywisty sprzęt jest w rzeczywistości skomplikowany - w taki sposób, że specyfikacja C jest czytana jak książka dla dzieci. Jeśli jesteś zainteresowany działaniem twojego sprzętu, zawsze możesz poszukać instrukcji i zacząć pisać kod w asemblerze. Lub zawsze możesz zacząć uczyć się o obwodach cyfrowych, aby móc samodzielnie zaprojektować sprzęt. (Przynajmniej docenisz, jak wysoki jest poziom C.)
Jak mają się uczyć? A jak się uczysz?
Okay, właściwie nauka o sprzęcie obejmuje rzeczy inne niż C. Ale czy C może dzisiaj uczyć programistów czegoś innego?
Myślę, że to zależy.
Niektórzy twierdzą, że możesz lepiej nauczyć się koncepcji , pracując w środowisku, które ją oferuje i zachęca, często na wiele sposobów.
Są tacy, którzy powiedzieliby, że możesz lepiej nauczyć się koncepcji , pracując w środowisku, które jej nie oferuje i gdzie zamiast tego musisz ją zbudować samodzielnie.
Nie bądź zbyt szybki, aby wybrać jedną z tych możliwości. Piszę kod od wielu lat i nadal nie mam pojęcia, która z nich jest poprawna, ani czy poprawna odpowiedź jest tylko jedną z dwóch, czy też istnieje coś takiego jak poprawna odpowiedź w tej sprawie.
Nie jestem skłonny wierzyć, że prawdopodobnie powinieneś ostatecznie zastosować obie opcje, w luźnej kolejności, w której je opisałem. Ale nie sądzę, że to naprawdę kwestia techniczna, myślę, że ma ona głównie charakter edukacyjny. Wydaje się, że każda osoba uczy się na różne sposoby.
Wyłącznie w C.
Jeśli odpowiedziałeś na powyższe pytanie przynajmniej przez włączenie drugiej opcji, którą zaproponowałem, masz już kilka odpowiedzi: wszystko, czego można się nauczyć w językach wyższego poziomu, można lepiej nauczyć poprzez ponowne wynalezienie go w C lub w najmniej rozwinięty przez dodanie C do miksu.
Ale bez względu na odpowiedź z pewnością jest kilka rzeczy, których możesz nauczyć się prawie wyłącznie z języka C (i być może kilku innych języków).
C jest historycznie ważne. Jest to kamień milowy, na który możesz spojrzeć i docenić, skąd pochodzimy, i może uzyskać nieco więcej kontekstu na temat tego, dokąd zmierzamy. Możesz docenić, dlaczego istnieją pewne ograniczenia i możesz zrozumieć, że pewne ograniczenia zostały zniesione.
C może nauczyć cię pracy w niebezpiecznych warunkach. Innymi słowy, może wyszkolić cię do pilnowania, gdy język (dowolny język) nie może lub nie zrobi tego za ciebie, z jakiegokolwiek powodu. Może to sprawić, że będziesz lepszym programistą nawet w bezpiecznych środowiskach, ponieważ sam wygenerujesz mniej błędów i ponieważ będziesz mógł tymczasowo wyłączyć bezpieczeństwo, aby wycisnąć dodatkową prędkość z twojego bezpiecznego programu (np. Użycie wskaźników w języku C #), w przypadkach, w których bezpieczeństwo wiąże się z kosztami środowiska wykonawczego.
C może nauczyć cię, że każdy obiekt ma wymagania dotyczące pamięci, układ pamięci, fakt, że do pamięci można uzyskać dostęp za pośrednictwem skończonej przestrzeni adresowej i tak dalej. Podczas gdy inne języki nie wymagają Twojej uwagi w tych sprawach, istnieje kilka przypadków, w których nabyta intuicja może pomóc w podejmowaniu bardziej świadomych decyzji.
C może uczyć cię o szczegółach plików łączących i obiektowych oraz innych zawiłościach poprzez swój system kompilacji. Może to pomóc w praktycznym zrozumieniu, w jaki sposób natywnie skompilowany program często przechodzi od kodu źródłowego do wykonania.
C może skłonić twój umysł do myślenia w nowatorski sposób poprzez koncepcję niezdefiniowanego zachowania. Nieokreślone zachowanie jest jednym z moich ulubionych pojęć w tworzeniu oprogramowania, ponieważ badanie jego wpływu na nieklasyczne kompilatory jest unikalnym ćwiczeniem umysłowym, którego nie można całkiem zrozumieć z innych języków. Musisz jednak odrzucić próbę i błąd i zacząć uczyć się języka w ostrożny i celowy sposób, zanim w pełni docenisz ten aspekt.
Ale być może najważniejszą realizacją, jaką C może ci dać, będąc małym językiem, jest idea, że całe programowanie sprowadza się do danych i operacji . Możesz spojrzeć na rzeczy jako na klasy modułowe z hierarchiami i interfejsami z wirtualną wysyłką lub na eleganckie niezmienne wartości, które są obsługiwane przy użyciu czysto matematycznych funkcji. I to wszystko w porządku - ale C przypomni Ci, że to wszystko tylko operacje na danych . Jest to przydatny sposób myślenia, ponieważ pozwala znieść wiele barier mentalnych.
Powodem, dla którego C jest dobry do nauki, nie jest to, że uczy on jakichkolwiek zasad . Uczy cię, jak to działa .
C można porównać z jednym z tych dobrych, dobrych samochodów z lat 70. lub 80., które właśnie zbudowano do jazdy. Możesz je rozerwać, przykręcić śrubą i zrozumieć, jak działa każda część, i jak to działa razem z innymi częściami, które możesz wziąć w swoje ręce, aby na nie spojrzeć. Po zrozumieniu wszystkich części masz bardzo jasny obraz tego, jak działa całość.
Współczesne języki są bardziej jak nowoczesny samochód, w którym silnik jest w zasadzie czarną skrzynką, co jest zbyt skomplikowane, aby zrozumieć go przeciętny właściciel samochodu. Te samochody mogą wiele zdziałać, do diabła, w tych dniach aktywnie uczą się jeździć samodzielnie. A przy tej złożoności i komforcie interfejs użytkownika został znacznie przesunięty w stosunku do tego, co faktycznie dzieje się w silniku.
Kiedy uczysz się programowania w C, masz do czynienia z wieloma śrubami i nakrętkami, z których składa się komputer. To pozwala rozwinąć zrozumienie samej maszyny. Na przykład pozwala zrozumieć, dlaczego nie jest dobrym pomysłem budowanie długiego łańcucha:
java.lang.String result ="";for(int i =0; i < components.size; i++){
result = result + components[i];};
(Mam nadzieję, że to jest poprawna Java, nie używałem jej od dłuższego czasu ...) Z tego przykładu kodu nie jest oczywiste, dlaczego pętla ma kwadratową złożoność. Ale tak właśnie jest i jest to powód, dla którego ten kod przestanie działać, gdy masz kilka milionów małych komponentów do połączenia. Doświadczony programista C natychmiast wie, gdzie jest problem i prawdopodobnie uniknie pisania takiego kodu w pierwszej kolejności.
Zgadzam się całkowicie. C nauczy Cię wiele o tym, jak działają rzeczy, co znacznie ułatwia zrozumienie a) dlaczego napisane zostały języki wyższego poziomu (np. Co oznaczały, aby je wyodrębnić), oraz b) jak te języki wyższego poziomu działają za kulisami, co na pewno dobrą wiedzę. Nie będzie uczył zasad i może nie będzie tak łatwy, ale da ci to szacunek, komputery i głębsze zrozumienie języków wyższego poziomu. Przeczytaj także Powrót do podstawowego autorstwa Joela Spolsky'ego
jleach
1
Twoja odpowiedź jest z pewnością w porządku, ale jeśli napiszesz for(int i = 0; i < strlen(s); i++)w C, pętla będzie miała kwadratową złożoność i jest tak samo nieoczywista jak w twoim przykładzie Java ;-)
Doc Brown
Nie jestem pewien, ale zaufałbym kompilatorowi Java, który zoptymalizuje to :-)
Bruno Schäpper
Doświadczony programista Java natychmiast wie, gdzie jest problem, i prawdopodobnie przede wszystkim uniknie pisania takiego kodu. Ten konkretny problem omówiono w podstawowych samouczkach dotyczących języka Java. Z pewnością nie jest to coś, czego można się nauczyć z języka C, ale nie z języka Java.
Peter Taylor
@PeterTaylor Jeśli masz instruktora Java, który zna ich C, tak. Wątpię jednak, aby ten rodzaj wiedzy pozostał, gdy ludzie znający C umrą. Dla programisty C jest to definicja tego, czym jest łańcuch C, co mówi im, że mój przykład kodu nie może być wydajny. Dla programisty Java jest to pewna głęboka, tajemna i mało używana wiedza na temat abstrakcji, których używają, co każe im unikać tego rodzaju kodu. Ok, przesadzam trochę tutaj, ale masz pomysł: programista C musi to wiedzieć, programista Java może uciec od niewiedzy.
cmaster
2
Są lepsze języki niż C do nauki „zasad programowania”, zwłaszcza zasad teoretycznych, ale C może być dobrym rozwiązaniem, aby nauczyć się kilku praktycznych, ważnych rzeczy na temat rzemiosła. Odpowiedź greyfade jest z pewnością poprawna, ale IMHO może nauczyć się więcej od C niż samodzielne zarządzanie pamięcią. Na przykład,
jak tworzyć programy z pełną obsługą błędów przy braku wyjątków
jak stworzyć strukturę w programie bez obsługi języka dla orientacji obiektowej
jak radzić sobie z danymi przy braku struktur danych, takich jak dynamiczne, spore listy, słowniki lub przydatna abstrakcja ciągów
jak uniknąć typowych błędów, takich jak przepełnienie tablicy, nawet jeśli kompilator lub środowisko wykonawcze nie ostrzega automatycznie
jak tworzyć ogólne rozwiązania bez obsługi języka dla szablonów lub ogólnych
i czy wspominałem, że możesz nauczyć się samodzielnie zarządzać pamięcią? ;-)
Ponadto, ucząc się języka C, dowiesz się, skąd biorą się podobieństwa składniowe C ++, Java, C #, Cel C.
W 2005 roku Joel Spolsky napisał zalecenie dotyczące nauki języka C przed jakimkolwiek innym językiem wyższego poziomu. Jego argumenty są
„nigdy nie będziesz w stanie stworzyć wydajnego kodu w językach wyższego poziomu”.
„Nigdy nie będziesz w stanie pracować na kompilatorach i systemach operacyjnych, które są jednymi z najlepszych zadań programistycznych.”
„Nigdy nie będziesz mieć zaufania do tworzenia architektur dla dużych projektów”
„jeśli nie potrafisz wyjaśnić, dlaczego while(*s++ = *t++);kopiujesz ciąg znaków lub jeśli nie jest to dla ciebie najbardziej naturalne na świecie, programujesz na podstawie przesądów
Oczywiście to, co napisał, jest z pewnością dyskusyjne, ale wiele jego argumentów IMHO jest nadal aktualnych.
C to bardzo dobry język do nauki, zanim nauczysz się tych „rzeczy na wyższym poziomie, które Twoim zdaniem C nie obsługują”, ponieważ pomagają zrozumieć, jak te rzeczy faktycznie działają (i jak są one drogie).
Brendan,
@Brendan: Nie jestem pewien, czy celem twojego komentarza jest wyrażenie zgody, nieporozumienia, czy tylko pomijanie mojej odpowiedzi.
Doc Brown,
Programy C napisane przez profesjonalistów są wydawane z przepełnieniem bufora i poważnymi awariami. Tak więc, podczas gdy zdyscyplinowany programista może się uczyć tych rzeczy , język C z natury nie naucza jedynie przez zubożenie. Istnieje wiele złych sposobów (i, co gorsza, mieszania wielu niekonsekwentnych sposobów) wykonywania błędów bez wyjątków i tworzenia struktury bez obiektów, na przykład.
Erik Eidt,
@ErikEidt: rzeczywiście, ale szczególnie w ekosferze C istnieje wiele książek, samouczków i innych materiałów dotyczących tych tematów. Na przykład „Writing Solid Code” Steve'a Maguire'a. Oczywiście, jeśli ktoś po prostu wybierze pierwsze wydanie K&R do nauki składni języka, prawdopodobnie nie stanie się lepszym programistą.
Doc Brown
1
Dwie podstawowe abstrakcje obliczeń to maszyny Turinga i rachunek Lambda, a C to sposób na eksperymentowanie z widokiem maszyny obliczeń Turinga: głównie seria działań na niskim poziomie, z których wynika pożądany rezultat. Trzeba jednak pamiętać, że C ma własny model obliczeń. Zatem nauka języka C nauczy Cię szczegółów niskiego poziomu maszyny abstrakcyjnej C, która różni się od rzeczywistych architektur. Jedną z pierwszych rzeczy, których nauczyłem się w C, było nigdy nie przechytrzenie kompilatora przez zastosowanie „sprytnych” sztuczek i wydaje się, że trendem jest coraz większa optymalizacja kompilatorów. Podobnie jak w innych językach wysokiego poziomu, podczas pisania w języku C kompilatory rozumieją, czego oczekujesz na abstrakcyjnej maszynie C i sprawiają, że dzieje się to na rzeczywistym sprzęcie,
Mam na myśli to, że nauka języka C niekoniecznie da ci dobry obraz tego, co faktycznie dzieje się w sprzęcie. „C jest blisko maszyny” należy rozumieć jako „bliżej niż większość języków wyższego poziomu”. Bezpośrednie uczenie się architektury oprogramowania będzie bardziej opłacalne, jeśli chcesz uzyskać dokładniejszy obraz „tego, jak to działa”.
Z drugiej strony nauka języka C może zaznajomić się z programowaniem systemu, typami niskiego poziomu, wskaźnikami, a zwłaszcza alokacją pamięci. Jeśli chodzi o algorytmy uczenia się i strukturę danych, nie ma przewagi, aby nauczyć się ich w języku C niż w innych językach.
Więc czego C może nauczyć cię, że języki wyższego poziomu nie mogą?
Philip Kendall,
2
Myślę, że domyślna odpowiedź brzmi: „ Nic , a przynajmniej nie to, co zwykle twierdzą zwolennicy”. Tak i tak rozumiem odpowiedź.
Jörg W Mittag,
-3
To bardzo otwarte pytanie, może nie dać rozstrzygającej odpowiedzi. Możesz nauczyć się prawie wszystkiego w każdym języku, pod warunkiem, że znasz wewnętrzne ramy językowe. C zmusza Cię do zrozumienia niższych szczegółów, ponieważ został zaprojektowany przede wszystkim do napisania systemu operacyjnego. Nawet po tylu latach wciąż jest jednym z najczęściej używanych języków, przede wszystkim dzięki systemom wbudowanym i projektom open source. Pytanie brzmi: czego chcesz się nauczyć? A w jakiej domenie?
Odpowiedzi:
Nie ma zasad, w ogólnym abstrakcyjnym znaczeniu informatyki, które są obecne w C, które nie są również obecne w językach wyższego poziomu. Cała informatyka sprowadza się do algorytmów, a wszystkie algorytmy można zaimplementować w dowolnym języku, który jest Turing-zupełny jak C.
Różnica, którą C przenosi poza języki wyższego poziomu, jest podobna do różnicy, którą kod maszynowy niesie poza C: Relacja maszyny do kodu.
Pisząc kod w językach wysokiego poziomu, nie musisz (ogólnie) martwić się interakcją kodu z maszyną. Maszyna wirtualna zdefiniowana przez język ukrywa wiele z tych aspektów wykonywania kodu.
W C interakcja twojego programu z pamięcią jest na pierwszym planie. To więcej niż tylko to, że musisz zarządzać wykorzystaniem sterty, obejmuje ona interakcję kodu ze stosem oraz sposób, w jaki sam dostęp pamięci do kodu wpływa na zachowanie i wydajność kodu - nawet na kolejność dostępu do pamięci można uniknąć uwagi, ponieważ czytanie niewłaściwej pamięci w niewłaściwym czasie może skutecznie osłabić wydajność.
W językach wyższego poziomu te rzeczy nie są tak oczywiste. Pamięć jest przydzielana i zwalniana bez Twojej wiedzy, a czasem bez Twojej prośby. Najczęściej jest to po prostu poza twoją kontrolą. Kiedy, gdzie, jak i dlaczego większość przydziałów pamięci jest po prostu ukryta przed tobą.
Podobnie, w innym kierunku, pisanie kodu maszynowego lub kodu asemblera przynosi jeszcze więcej szczegółów na pierwszy plan: prawie nic nie pozostaje poza twoim zakresem, a twój kod musi być napisany z uwzględnieniem każdej alokacji, każdego zasobu, każdej przekazywanej części danych poprzez rejestry procesora - wiedza tak daleko od języków wysokiego poziomu, że jest tajemna.
źródło
Nie zgadzam się. C nie ma zbyt wielu funkcji, aby nauczyć się zasad programowania. Funkcje C do tworzenia abstrakcji są okropne, a abstrakcja jest jedną z kluczowych zasad programowania.
Jeśli chcesz się dowiedzieć, jak działa sprzęt, a co za tym idzie mechanicznej sympatii do maszyny, powinieneś nauczyć się kodu maszynowego, czyli architektury zestawu instrukcji, a także przestudiować budowę pamięci podręcznej nowoczesnych procesorów. Zauważ, że nie polecam języka asemblera, po prostu zapoznaj się z instrukcjami sprzętowymi, aby zrozumieć, co generuje kompilator.
Jeśli chcesz nauczyć się zasad programowania, użyj nowoczesnego języka, takiego jak Java, C # lub Swift, lub jednego z wielu innych, takich jak Rust. Studiuj także różne rodzaje paradygmatów programowania, w tym funkcjonalne.
źródło
C i (abstrakcyjna) maszyna
Większość języków programowania jest opisywana w kategoriach abstrakcyjnych maszyn. Następnie są one wdrażane przy użyciu zestawów narzędzi, takich jak kompilatory, konsolidatory, asemblery, interpretery, analizatory statyczne, języki pośrednie i sprzęt , które wspólnie wygenerują wynik, który honoruje co najmniej wszystkie oczekiwane zachowanie maszyny abstrakcyjnej, zaobserwowane przez program .
C nie jest wyjątkiem od powyższej reguły. Jest to opisane jako abstrakcyjna maszyna, która nie ma pojęcia o twoim rzeczywistym sprzęcie.
Jako takie, gdy ludzie mówią, że C uczy cię, jak naprawdę działa komputer, zwykle oznaczają, że C uczy, jak działa C. Ale C, ponieważ jest tak wszechobecny w programowaniu systemów, jest zrozumiałe, że wiele osób zaczyna mylić go z samym komputerem. I osobiście posunąłbym się nawet do stwierdzenia, że wiedza o tym, jak działa C, jest często ważniejsza niż wiedza o tym, jak działa sam komputer.
Ale C i komputer to różne rzeczy. Rzeczywisty sprzęt jest w rzeczywistości skomplikowany - w taki sposób, że specyfikacja C jest czytana jak książka dla dzieci. Jeśli jesteś zainteresowany działaniem twojego sprzętu, zawsze możesz poszukać instrukcji i zacząć pisać kod w asemblerze. Lub zawsze możesz zacząć uczyć się o obwodach cyfrowych, aby móc samodzielnie zaprojektować sprzęt. (Przynajmniej docenisz, jak wysoki jest poziom C.)
Jak mają się uczyć? A jak się uczysz?
Okay, właściwie nauka o sprzęcie obejmuje rzeczy inne niż C. Ale czy C może dzisiaj uczyć programistów czegoś innego?
Myślę, że to zależy.
Nie bądź zbyt szybki, aby wybrać jedną z tych możliwości. Piszę kod od wielu lat i nadal nie mam pojęcia, która z nich jest poprawna, ani czy poprawna odpowiedź jest tylko jedną z dwóch, czy też istnieje coś takiego jak poprawna odpowiedź w tej sprawie.
Nie jestem skłonny wierzyć, że prawdopodobnie powinieneś ostatecznie zastosować obie opcje, w luźnej kolejności, w której je opisałem. Ale nie sądzę, że to naprawdę kwestia techniczna, myślę, że ma ona głównie charakter edukacyjny. Wydaje się, że każda osoba uczy się na różne sposoby.
Wyłącznie w C.
Jeśli odpowiedziałeś na powyższe pytanie przynajmniej przez włączenie drugiej opcji, którą zaproponowałem, masz już kilka odpowiedzi: wszystko, czego można się nauczyć w językach wyższego poziomu, można lepiej nauczyć poprzez ponowne wynalezienie go w C lub w najmniej rozwinięty przez dodanie C do miksu.
Ale bez względu na odpowiedź z pewnością jest kilka rzeczy, których możesz nauczyć się prawie wyłącznie z języka C (i być może kilku innych języków).
C jest historycznie ważne. Jest to kamień milowy, na który możesz spojrzeć i docenić, skąd pochodzimy, i może uzyskać nieco więcej kontekstu na temat tego, dokąd zmierzamy. Możesz docenić, dlaczego istnieją pewne ograniczenia i możesz zrozumieć, że pewne ograniczenia zostały zniesione.
C może nauczyć cię pracy w niebezpiecznych warunkach. Innymi słowy, może wyszkolić cię do pilnowania, gdy język (dowolny język) nie może lub nie zrobi tego za ciebie, z jakiegokolwiek powodu. Może to sprawić, że będziesz lepszym programistą nawet w bezpiecznych środowiskach, ponieważ sam wygenerujesz mniej błędów i ponieważ będziesz mógł tymczasowo wyłączyć bezpieczeństwo, aby wycisnąć dodatkową prędkość z twojego bezpiecznego programu (np. Użycie wskaźników w języku C #), w przypadkach, w których bezpieczeństwo wiąże się z kosztami środowiska wykonawczego.
C może nauczyć cię, że każdy obiekt ma wymagania dotyczące pamięci, układ pamięci, fakt, że do pamięci można uzyskać dostęp za pośrednictwem skończonej przestrzeni adresowej i tak dalej. Podczas gdy inne języki nie wymagają Twojej uwagi w tych sprawach, istnieje kilka przypadków, w których nabyta intuicja może pomóc w podejmowaniu bardziej świadomych decyzji.
C może uczyć cię o szczegółach plików łączących i obiektowych oraz innych zawiłościach poprzez swój system kompilacji. Może to pomóc w praktycznym zrozumieniu, w jaki sposób natywnie skompilowany program często przechodzi od kodu źródłowego do wykonania.
C może skłonić twój umysł do myślenia w nowatorski sposób poprzez koncepcję niezdefiniowanego zachowania. Nieokreślone zachowanie jest jednym z moich ulubionych pojęć w tworzeniu oprogramowania, ponieważ badanie jego wpływu na nieklasyczne kompilatory jest unikalnym ćwiczeniem umysłowym, którego nie można całkiem zrozumieć z innych języków. Musisz jednak odrzucić próbę i błąd i zacząć uczyć się języka w ostrożny i celowy sposób, zanim w pełni docenisz ten aspekt.
Ale być może najważniejszą realizacją, jaką C może ci dać, będąc małym językiem, jest idea, że całe programowanie sprowadza się do danych i operacji . Możesz spojrzeć na rzeczy jako na klasy modułowe z hierarchiami i interfejsami z wirtualną wysyłką lub na eleganckie niezmienne wartości, które są obsługiwane przy użyciu czysto matematycznych funkcji. I to wszystko w porządku - ale C przypomni Ci, że to wszystko tylko operacje na danych . Jest to przydatny sposób myślenia, ponieważ pozwala znieść wiele barier mentalnych.
źródło
Powodem, dla którego C jest dobry do nauki, nie jest to, że uczy on jakichkolwiek zasad . Uczy cię, jak to działa .
C można porównać z jednym z tych dobrych, dobrych samochodów z lat 70. lub 80., które właśnie zbudowano do jazdy. Możesz je rozerwać, przykręcić śrubą i zrozumieć, jak działa każda część, i jak to działa razem z innymi częściami, które możesz wziąć w swoje ręce, aby na nie spojrzeć. Po zrozumieniu wszystkich części masz bardzo jasny obraz tego, jak działa całość.
Współczesne języki są bardziej jak nowoczesny samochód, w którym silnik jest w zasadzie czarną skrzynką, co jest zbyt skomplikowane, aby zrozumieć go przeciętny właściciel samochodu. Te samochody mogą wiele zdziałać, do diabła, w tych dniach aktywnie uczą się jeździć samodzielnie. A przy tej złożoności i komforcie interfejs użytkownika został znacznie przesunięty w stosunku do tego, co faktycznie dzieje się w silniku.
Kiedy uczysz się programowania w C, masz do czynienia z wieloma śrubami i nakrętkami, z których składa się komputer. To pozwala rozwinąć zrozumienie samej maszyny. Na przykład pozwala zrozumieć, dlaczego nie jest dobrym pomysłem budowanie długiego łańcucha:
(Mam nadzieję, że to jest poprawna Java, nie używałem jej od dłuższego czasu ...) Z tego przykładu kodu nie jest oczywiste, dlaczego pętla ma kwadratową złożoność. Ale tak właśnie jest i jest to powód, dla którego ten kod przestanie działać, gdy masz kilka milionów małych komponentów do połączenia. Doświadczony programista C natychmiast wie, gdzie jest problem i prawdopodobnie uniknie pisania takiego kodu w pierwszej kolejności.
źródło
for(int i = 0; i < strlen(s); i++)
w C, pętla będzie miała kwadratową złożoność i jest tak samo nieoczywista jak w twoim przykładzie Java ;-)Są lepsze języki niż C do nauki „zasad programowania”, zwłaszcza zasad teoretycznych, ale C może być dobrym rozwiązaniem, aby nauczyć się kilku praktycznych, ważnych rzeczy na temat rzemiosła. Odpowiedź greyfade jest z pewnością poprawna, ale IMHO może nauczyć się więcej od C niż samodzielne zarządzanie pamięcią. Na przykład,
jak tworzyć programy z pełną obsługą błędów przy braku wyjątków
jak stworzyć strukturę w programie bez obsługi języka dla orientacji obiektowej
jak radzić sobie z danymi przy braku struktur danych, takich jak dynamiczne, spore listy, słowniki lub przydatna abstrakcja ciągów
jak uniknąć typowych błędów, takich jak przepełnienie tablicy, nawet jeśli kompilator lub środowisko wykonawcze nie ostrzega automatycznie
jak tworzyć ogólne rozwiązania bez obsługi języka dla szablonów lub ogólnych
i czy wspominałem, że możesz nauczyć się samodzielnie zarządzać pamięcią? ;-)
Ponadto, ucząc się języka C, dowiesz się, skąd biorą się podobieństwa składniowe C ++, Java, C #, Cel C.
W 2005 roku Joel Spolsky napisał zalecenie dotyczące nauki języka C przed jakimkolwiek innym językiem wyższego poziomu. Jego argumenty są
„nigdy nie będziesz w stanie stworzyć wydajnego kodu w językach wyższego poziomu”.
„Nigdy nie będziesz w stanie pracować na kompilatorach i systemach operacyjnych, które są jednymi z najlepszych zadań programistycznych.”
„Nigdy nie będziesz mieć zaufania do tworzenia architektur dla dużych projektów”
„jeśli nie potrafisz wyjaśnić, dlaczego
while(*s++ = *t++);
kopiujesz ciąg znaków lub jeśli nie jest to dla ciebie najbardziej naturalne na świecie, programujesz na podstawie przesądówOczywiście to, co napisał, jest z pewnością dyskusyjne, ale wiele jego argumentów IMHO jest nadal aktualnych.
źródło
Dwie podstawowe abstrakcje obliczeń to maszyny Turinga i rachunek Lambda, a C to sposób na eksperymentowanie z widokiem maszyny obliczeń Turinga: głównie seria działań na niskim poziomie, z których wynika pożądany rezultat. Trzeba jednak pamiętać, że C ma własny model obliczeń. Zatem nauka języka C nauczy Cię szczegółów niskiego poziomu maszyny abstrakcyjnej C, która różni się od rzeczywistych architektur. Jedną z pierwszych rzeczy, których nauczyłem się w C, było nigdy nie przechytrzenie kompilatora przez zastosowanie „sprytnych” sztuczek i wydaje się, że trendem jest coraz większa optymalizacja kompilatorów. Podobnie jak w innych językach wysokiego poziomu, podczas pisania w języku C kompilatory rozumieją, czego oczekujesz na abstrakcyjnej maszynie C i sprawiają, że dzieje się to na rzeczywistym sprzęcie,
Mam na myśli to, że nauka języka C niekoniecznie da ci dobry obraz tego, co faktycznie dzieje się w sprzęcie. „C jest blisko maszyny” należy rozumieć jako „bliżej niż większość języków wyższego poziomu”. Bezpośrednie uczenie się architektury oprogramowania będzie bardziej opłacalne, jeśli chcesz uzyskać dokładniejszy obraz „tego, jak to działa”.
Z drugiej strony nauka języka C może zaznajomić się z programowaniem systemu, typami niskiego poziomu, wskaźnikami, a zwłaszcza alokacją pamięci. Jeśli chodzi o algorytmy uczenia się i strukturę danych, nie ma przewagi, aby nauczyć się ich w języku C niż w innych językach.
źródło
To bardzo otwarte pytanie, może nie dać rozstrzygającej odpowiedzi. Możesz nauczyć się prawie wszystkiego w każdym języku, pod warunkiem, że znasz wewnętrzne ramy językowe. C zmusza Cię do zrozumienia niższych szczegółów, ponieważ został zaprojektowany przede wszystkim do napisania systemu operacyjnego. Nawet po tylu latach wciąż jest jednym z najczęściej używanych języków, przede wszystkim dzięki systemom wbudowanym i projektom open source. Pytanie brzmi: czego chcesz się nauczyć? A w jakiej domenie?
źródło