Globalna edycja: przepraszam chłopaki, wyrzuciłem wszystkich z pracy i napisałem wiele bzdur. Tylko stary geezer narzekający.
Chciałem wierzyć, że C zostało oszczędzone, ale niestety od C11 zostało wyrównane z C ++. Najwyraźniej wiedza o tym, co kompilator zrobi z efektami ubocznymi wyrażeń, wymaga teraz rozwiązania małej zagadki matematycznej polegającej na częściowym uporządkowaniu sekwencji kodu na podstawie „znajduje się przed punktem synchronizacji”.
Zdarzyło mi się zaprojektować i wdrożyć kilka krytycznych systemów osadzonych w czasie rzeczywistym w czasach K&R (w tym kontroler samochodu elektrycznego, który mógłby wysłać ludzi uderzających w najbliższą ścianę, gdyby silnik nie był kontrolowany, 10 ton przemysłowych robot, który mógłby zmiażdżyć ludzi na miazgę, jeśli nie byłby właściwie dowodzony, oraz warstwa systemowa, która, choć nieszkodliwa, miałaby kilkadziesiąt procesorów wysysających szynę danych z mniej niż 1% obciążenia systemowego).
Mogę być zbyt ostrożny lub głupi, aby dostrzec różnicę między niezdefiniowanym a nieokreślonym, ale myślę, że nadal mam całkiem niezłe pojęcie o tym, co oznacza równoczesne wykonywanie i dostęp do danych. W mojej, prawdopodobnie uzasadnionej opinii, ta obsesja na punkcie C ++, a teraz C facetów z ich językami domowymi przejmującymi problemy z synchronizacją, jest kosztownym marzeniem. Albo wiesz, co to jest równoczesne wykonywanie, i nie potrzebujesz żadnego z tych gadżetów, albo nie, i zrobiłbyś światu przysługę, nie próbując go zepsuć.
Cała ta ogromna ilość abstrakcyjnych barier pamięci jest po prostu spowodowana tymczasowym zestawem ograniczeń wieloprocesorowych systemów pamięci podręcznej, z których wszystkie można bezpiecznie zamknąć we wspólnych obiektach synchronizacji systemu operacyjnego, takich jak na przykład muteksy i zmienne warunkowe C ++ oferuje.
Koszt takiej enkapsulacji to zaledwie drobny spadek wydajności w porównaniu z tym, co może osiągnąć zastosowanie drobnoziarnistych instrukcji dla konkretnego procesora w niektórych przypadkach.
Thevolatile
kluczowe (lub a#pragma dont-mess-with-that-variable
dla mnie, jako programisty systemu, opieka) byłaby wystarczająca, aby powiedzieć kompilatorowi, aby przestał zmieniać kolejność dostępu do pamięci. Optymalny kod może być łatwo wytworzony za pomocą bezpośrednich dyrektyw asm, aby posypać kod sterownika niskiego poziomu i kod systemu operacyjnego instrukcjami ad hoc CPU. Bez dogłębnej wiedzy o tym, jak działa podstawowy sprzęt (system pamięci podręcznej lub interfejs magistrali), i tak będziesz musiał pisać bezużyteczny, nieefektywny lub wadliwy kod.
Drobna korekta volatile
słowa kluczowego i Boba byłaby wszystkim, ale najbardziej wujek programistów niskiego poziomu. Zamiast tego zwykły gang maniaków matematyki w C ++ miał dzień w terenie, projektując jeszcze jedną niezrozumiałą abstrakcję, ulegając ich typowej tendencji do projektowania rozwiązań szukających nieistniejących problemów i mylących definicję języka programowania ze specyfikacjami kompilatora.
Tylko tym razem zmiana wymagała zniszczenia podstawowego aspektu języka C, ponieważ te „bariery” musiały zostać wygenerowane nawet w kodzie niskiego poziomu, aby działały poprawnie. To między innymi spowodowało spustoszenie w definicji wyrażeń, bez żadnego wyjaśnienia ani uzasadnienia.
Podsumowując, fakt, że kompilator może wytworzyć spójny kod maszynowy z tego absurdalnego fragmentu C, jest tylko daleką konsekwencją sposobu, w jaki ludzie C ++ radzili sobie z potencjalnymi niespójnościami systemów pamięci podręcznej pod koniec 2000 roku.
To spowodowało straszny bałagan jednego podstawowego aspektu C (definicja wyrażenia), tak że ogromna większość programistów C - którzy nie dbają o systemy pamięci podręcznej i słusznie - jest teraz zmuszona polegać na guru, aby wyjaśnić różnica między a = b() + c()
i a = b + c
.
Zgadywanie, co stanie się z tym niefortunnym zestawem, jest i tak stratą czasu i wysiłku. Niezależnie od tego, co zrobi z niego kompilator, ten kod jest patologicznie niepoprawny. Jedyną odpowiedzialną rzeczą, jaką można z tym zrobić, jest wysłanie go do kosza.
Koncepcyjnie, skutki uboczne można zawsze usunąć z wyrażeń, przy trywialnym wysiłku wyraźnego zezwolenia na modyfikację przed lub po ocenie, w osobnym oświadczeniu.
Ten gówniany kod mógł być usprawiedliwiony w latach 80-tych, kiedy nie można było oczekiwać, że kompilator coś zoptymalizuje. Ale teraz, gdy kompilatory od dawna stają się mądrzejsze niż większość programistów, pozostaje tylko kawałek gównianego kodu.
Nie rozumiem również znaczenia tej nieokreślonej / nieokreślonej debaty. Albo możesz polegać na kompilatorze do generowania kodu o spójnym działaniu, albo nie możesz. To, czy nazywasz to niezdefiniowanym, czy nieokreślonym, wydaje się kwestią sporną.
Według mojej prawdopodobnie poinformowanej opinii C jest już wystarczająco niebezpieczny w swoim stanie K&R. Przydatną ewolucją byłoby dodanie zdrowych środków bezpieczeństwa. Na przykład, korzystając z tego zaawansowanego narzędzia do analizy kodu, specyfikacje zmuszają kompilator do wdrożenia przynajmniej generowania ostrzeżeń o kodzie bonkers, zamiast cichego generowania kodu potencjalnie niewiarygodnego.
Zamiast tego faceci postanowili na przykład zdefiniować stały porządek oceny w C ++ 17. Teraz każde imbecylowe oprogramowanie jest aktywnie zachęcane do celowego umieszczania efektów ubocznych w swoim kodzie, pławiąc się w przekonaniu, że nowe kompilatory chętnie zajmą się zaciemnianiem w deterministyczny sposób.
K&R był jednym z prawdziwych cudów świata komputerowego. Za dwadzieścia dolców masz pełną specyfikację języka (widziałem, jak pojedyncze osoby piszą kompletne kompilatory za pomocą tej książki), doskonałą instrukcję obsługi (spis treści zwykle wskazywałby na kilka stron odpowiedzi na twoje pytanie) pytanie) oraz podręcznik, który nauczy Cię rozsądnego posługiwania się językiem. Uzupełnij go uzasadnieniem, przykładami i mądrymi słowami ostrzegającymi o licznych sposobach nadużywania języka do robienia bardzo, bardzo głupich rzeczy.
Zniszczenie tego dziedzictwa za tak mały zysk wydaje mi się okrutnym marnotrawstwem. Ale znowu mogę nie rozumieć tego całkowicie. Może jakaś miła dusza mogłaby wskazać mi przykład nowego kodu C, który w znacznym stopniu wykorzystuje te skutki uboczne?