Podobnie uczyniono z kilkoma innymi słowami kluczowymi, mającymi wcześniej formę, rozpoczynającą się od znaku podkreślenia i wielkiej litery13. XX wieku Bjarne Stroustrup stworzył język C++, który stanowił rozszerzenie C, dodające przede wszystkim wsparcie dla programowania obiektowego. Dodatków tych nie wcielono do C, a C++ został niezależnie ustandaryzowany przez ANSI i ISO12. W 1978 opublikowane zostało pierwsze wydanie książki The C Programming Language (wyd. polskie Język C, 19877), autorstwa Briana Kernighana i Dennisa Ritchiego. Stanowiła ona pierwszą, nieformalną, specyfikację języka C4.
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.
Jego specyfikacja pozwala na rzutowanie typów wskaźnikowych na dowolne inne typy wskaźnikowe. W konsekwencji dowolny region pamięci Jak ja uratowany ‘ 40k przy Crypto Hacker i wciąż zgubiony ‘ 10K może być traktowany tak, jakby zawierał dane dowolnego typu. Jednocześnie narzędzia wspomagające pisanie kodu nie są w stanie sprawdzić, czy konwersja typów jest sensowna166. W C jest ponadto dozwolone przypisanie wartości do zmiennej innego typu.
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.
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.
Ponadto przez cały ten czas dany obiekt będzie dostępny pod stałym adresem i będzie przechowywał ostatnio zapisaną wartość. Momenty utworzenia i zniszczenia obiektu są zależne od przypisanej mu klasy pamięci110. Dostęp do pamięci nie jest kontrolowany przez język111, ale próby odczytu lub zapisu pod nieprawidłowymi adresami mogą skończyć się naruszeniami ochrony pamięci112. Użycie kwalifikatora long jest dopuszczalne również w połączeniu z typem double, choć standard C nie gwarantuje, że uzyskany w ten sposób typ będzie miał większą pojemność niż wyjściowy. Podobnie jak w przypadku liczb całkowitych, dostępne typy zmiennoprzecinkowe również nie mają sztywno określonego zakresu wartości oraz minimalnej dokładności69.
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 standardach Unicode i UTF-822. W 1999 roku do języka C wprowadzono Wskaźnik Skalpowanie Ultimate PRO Scalper także obsługę tablic o długości ustalanej w czasie działania programu20.
Cechy standardów
Autorzy publikacji wspomnieli również o planowanym zniesieniu większości ograniczeń dotyczących struktur11. Do 1980 roku możliwe stało się przekazywanie ich jako parametry funkcji oraz bezpośrednie przypisywanie. Jedynie brak notacji dla literału powodował, że nie były typem pierwszoklasowym. Do tego czasu wprowadzono również do składni języka obsługę struktur. Mniej więcej w tym samym czasie powstała pierwsza wersja preprocesora.
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 zmiany w standardzie języka C były zainspirowane językiem C++ (np. słowo inline w C99).
XX wieku przez Dennisa Ritchiego, ówczesnego pracownika Bell Labs. W języku C powstały narzędzia systemowe dla Uniksa, a potem również kod systemu Unix. Od tego czasu jego rozwojem zajmuje się grupa robocza w ramach ISO. Badanie projektów open source na platformie GitHub z 2014 roku wskazało, że ok. 60% linii kodu źródłowego napisanych było w C, choć znajdowały się one jedynie w 10% przebadanych repozytoriów. Autorzy badania są zdania, że tak wysoka wartość pierwszego wskaźnika może wynikać w faktu, iż w C powstały znaczące części systemów operacyjnych, m.in. Jądro Linux i jego odmiany, które należą do projektów o największej bazie kodu3.
W głąb języka C
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.
Klasy pamięci
- Elementów macierzy wykorzystywano pomocniczą tablicę wskaźników do pierwszych elementów każdego wiersza170.
- 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.
- Kompilator C, wraz z kilkoma programami napisanymi w tym języku, został dołączony do drugiej wersji systemu Unix5.
- Wszystkie operacje, które są dopuszczalne dla struktur, można wykonywać również na uniach89.
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.
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.
Kwalifikatory typów
W przeciwieństwie do tablic, takie składowe mogą być różnych typów, a poszczególne pola rozróżnia się z użyciem ich identyfikatorów81. Każda struktura stanowi odrębną przestrzeń nazw, toteż pole o tej samej nazwie może występować w kilku strukturach8238. Zagnieżdżanie struktur jest dozwolone – składowe mogą również być strukturami. Standard ISO C zabrania natomiast rekursywnego zagnieżdżania struktury samej w sobie.
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 Aktualizacja rynku 5 maja Yellen poprawia komentarze (lub obiektów)47. Piątą wersję standardu języka C opublikowano w październiku 2024 roku1.
- Środowiska wykonawcze dla programów napisanych w innych językach również powstają z wykorzystaniem kodu w C.
- Kompilator języka jedynie rezerwuje dla zmiennej obszar w pamięci, a jej wartość jest taka jaka wynika ze stanu bitów, która się w tej pamięci aktualnie znajduje181.
- W rezultacie ten sam kod skompilowany na różnych kompilatorach lub z różnymi opcjami kompilacji może się inaczej zachowywać173.
- Miejscami pozostawiała miejsce do interpretacji szczegółów języka.
- Popularność i szerokie zastosowanie języka C ma bezpośredni wpływ na składnię lub semantykę innych języków programowania134.
- To od niej rozpoczyna się wykonanie programu napisanego w C.
Typy pochodne
Dostęp pośredni do zmiennych tego rodzaju należących do innych wątków wywołuje zachowanie zależne od implementacji110. Po upłynięciu czasu życia zmiennej, wszelkie odwołania do niej prowadzą do niezdefiniowanego zachowania. Podobnie wartość wskazywana przez wskaźnik staje się nieokreślona, kiedy wskazywany obiekt kończy życie110. W powyższej tabeli zebrano minimalne wymagania stawiane dostępnym w C typom całkowitoliczbowym. Dodatkowym ograniczeniem, stawianym przez standard jest to, aby kolejne typy miały zakres niemniejszy od poprzednich.
Obiekt (zwany też zmienną44), według standardu języka C, to region pamięci środowiska wykonawczego, mogący reprezentować wartości45. Wyrażenie, które może odwoływać się do obiektu jest l-wartością. Jej typ określa, w jaki sposób interpretować zawartość obiektu46. Pierwsze kompilatory języka C++, podobnie jak Cfront, były wyłącznie translatorami na język C. Jednym z nich jest Comeau C++ – jeden z niewielu kompilatorów oferujących pełne wsparcie dla standardu języka.