Według Stack Overflow Developer Survey 2022, co szósty profesjonalny programista zna język C. Większość respondentów (60%) oceniła go jednak jako „przerażający” (w dwustopniowej skali, drugą opcją było „uwielbiany”). Natomiast 4,3% osób zadeklarowało, że chce rozpocząć pracę z tym językiem149.
ANSI C i ISO C
Nie zapewnia ono jednak przenośności między różnymi platformami174. Jest to jeden z głównych powodów nieprzenaszalności kodu, który ujawnia się podczas wymiany danych poprzez pamięć współdzieloną, masową lub ich transmisję175. Jedną z naczelnych zasad ducha programowania w C jest tworzenie wydajnego kodu nawet za cenę jego przenośności176. Deklarując obiekt, można wskazać jego klasę pamięci, która określa między innymi jego czas życia i zasięg widoczności. Zmienne lokalne, o ile nie użyto żadnego specyfikatora klasy pamięci, są deklarowane jako zmienne automatyczne44. Wartości niezainicjalizowanych zmiennych są niezdefiniowane i mogą mieć wartość zależną od kompilatora lub od tego, co akurat było w pamięci113.
W zamian stworzył własną, okrojoną wersję BCPL, którą nazwał B. W języku tym powstało niewiele narzędzi, ponieważ wynikowe programy były powolne oraz nie mogły korzystać z adresowania poszczególnych bajtów pamięci (funkcji dostępnej np. w PDP-11)4. Niektóre Trading: nauczyć się handlu zmiany w standardzie języka C były zainspirowane językiem C++ (np. słowo inline w C99).
Aliasy typów
Zadeklarowanie obiektu ze słowem register sugeruje kompilatorowi, by umieścił go w pamięci o szybkim dostępie (np. rejestrze procesora114). Ostateczny wybór rodzaju pamięci, w której znajdzie się zmienna, należy jednak do kompilatora. Niezależnie od tego, czy obiekt zlokalizowany będzie w pamięci adresowalnej, zabronione jest pobieranie adresu zmiennej rejestrowej115. Typ danych określa zbiór wartości, które może przyjąć dany obiekt, jak również dozwolone operacje na nim60.
Składnia
Język udostępnia zestaw typów podstawowych oraz mechanizmów konstruowania typów pochodnych61. Deklaracja obiektu polega na podaniu typu danych oraz opcjonalnie klasy pamięci i sposobu linkowania, po których występuje przynajmniej jeden identyfikator tworzonego obiektu (lub obiektów)47. Piątą wersję standardu języka C opublikowano w październiku 2024 roku1.
Obiekty
Pamięć dla nich inicjalizowana jest w momencie uruchomienia programu i od tego momentu wszystkie odwołania dotyczą tego samego regionu pamięci110. W przypadku, gdy zmienną lokalną zadeklarowano jako statyczną, będzie ona przechowywała tę samą wartość pomiędzy różnymi wywołaniami funkcji. Z kolei statyczne zmienne zewnętrzne charakteryzują się linkowaniem wewnętrznym, co oznacza, że nie są widoczne na zewnątrz jednostki tłumaczenia, w której je zadeklarowano114. W języku C dostępny jest mechanizm pozwalający na zdefiniowanie synonimów dla istniejących typów danych. Aliasowanie nie tworzy nowego typu, zatem obiekty utworzone z użyciem zarówno pierwotnej, jak i nowej nazwy mają identyczne właściwości93.
W odróżnieniu od poprzedniego wydania standardu, w tym wprowadzono normatywne zmiany27. W 2011 roku do języka C wprowadzono także mechanizm definiowania makr generycznych ze względu na typ parametrów oraz wsparcie dla literałów napisowych w Aktualizacja rynku 3 maja standardach Unicode i UTF-822. W 1999 roku do języka C wprowadzono także obsługę tablic o długości ustalanej w czasie działania programu20.
W głąb języka C
Podczas prac nad nią, komitety odpowiedzialne za języki C i C++ współpracowały ze sobą, by zachować wzajemną zgodność obu na tyle, na ile to możliwe. W tej wersji standardu zadecydowano, że tablice o Krzyż śmierci w handlu zmiennej długości oraz typy zespolone staną się funkcjonalnością opcjonalną (C99 wymagał, by kompilatory je wspierały). Rozbudowano również bibliotekę standardową o procedury sprawdzające zakres i granice obszaru pamięci podczas operowania na napisach. Z powodu licznych podatności usunięto funkcję gets(), zastępując ją bezpieczniejszą gets_s()22.
Umożliwiała ona dołączanie plików zewnętrznych (dyrektywa #include) oraz wykonywanie prostych podstawień (definiując makra bez parametrów z użyciem #define). Funkcjonalności takie jak kompilacja warunkowa czy parametryzowane makra zostały wprowadzone niedługo później – przez Mike’a Leska(inne języki) oraz Johna Reisera. Na tym etapie rozwoju języka preprocesor stanowił opcjonalny dodatek, który nie musiał być uruchamiany w trakcie kompilacji4.
C (język programowania)
- Okresy najszybszego rozwoju języka C to lata 1972–1973 oraz 1977–1979.
- Standard języka C gwarantuje, że zdarzą się one przed następnym punktem sekwencyjnym(inne języki)41.
- Zarówno przypisywanie do zmiennej typu strukturalnego nowej wartości, jak i przekazywanie jej jako argument oraz zwracanie z funkcji są dopuszczalnymi operacjami84.
- Podczas prac nad językiem Kernighan i Ritchie nie skupiali się na ustandaryzowaniu biblioteki standardowej.
Pierwsza linijka tego kodu informuje preprocesor, aby dołączył w to miejsce zawartość pliku stdio.h, który wchodzi w skład biblioteki standardowej języka C125. Zadeklarowane w nim są procedury odpowiadające za obsługę wejścia i wyjścia, w tym printf126. To od niej rozpoczyna się wykonanie programu napisanego w C. Funkcja ta nie przyjmuje żadnych argumentów i zwraca wartość całkowitą. Wewnątrz nawiasów klamrowych znajduje się lista instrukcji, które zostaną wywołane po uruchomieniu programu127.
Wspiera mechanizmy kompilacji warunkowej (dyrektywa #if i jej warianty) oraz dołączania innych plików źródłowych (#include). Odpowiada również za rozwijanie makr (zdefiniowanych przy użyciu #define)5657. Wprowadzony w C99 typ logiczny, który do tej pory nazywał się _Bool, zmienił nazwę na bool. Podobnie, true i false, będące wcześniej makrami, promowano na słowa kluczowe.
Mechanizm ten wykorzystuje się między innymi w celu zapewnienia przenośności oprogramowania podczas wykorzystania typów zależnych od docelowej architektury. Przykładem takiego zastosowania są size_t i ptrdiff_t, pochodzące z biblioteki standardowej języka C94. Przechowują one liczby całkowite, lecz ich dokładny typ zależy od implementacji95. Podczas prac nad językiem Kernighan i Ritchie nie skupiali się na ustandaryzowaniu biblioteki standardowej. Odpowiednie funkcje dostarczał system Unix, niezależnie od stosowanego kompilatora.
- Podczas prac nad nią, komitety odpowiedzialne za języki C i C++ współpracowały ze sobą, by zachować wzajemną zgodność obu na tyle, na ile to możliwe.
- Preprocesor w języku C pozwala na manipulację kodem źródłowym przed właściwą kompilacją.
- W języku C powstały narzędzia systemowe dla Uniksa, a potem również kod systemu Unix.
- Przykładem takiego zastosowania są size_t i ptrdiff_t, pochodzące z biblioteki standardowej języka C94.
Wersja ta bywa nazywana C78, gdzie nazwa pochodzi od roku wydania. Inne skrócone określenie, K&R C, pochodzi od nazwisk autorów książki8. Kompilator C, wraz z kilkoma programami napisanymi w tym języku, został dołączony do drugiej wersji systemu Unix5. Latem 1973 jądro tego systemu zostało przepisane w języku C4.
Podwaliny pod nią położył w 1972 roku Mike Lesk, pisząc „przenośną bibliotekę wejścia/wyjścia”. W następnych latach, wraz z pracami nad przenośnością systemu Unix, została ona rozwinięta i usprawniona. Funkcje biblioteczne nie zostały przez autorów książki uznane za część języka, lecz dodatek do niego410. Thompson czuł potrzebę wykorzystania języka wyższego poziomu do napisania narzędzi systemowych dla Uniksa. Początkowo próbował przygotować kompilator Fortranu, lecz dość szybko porzucił ten pomysł.