Co dokładnie oznacza „Cel-C jest nadzbiorem języka C ściślej niż C ++”?

87

Z tego, co tam przeczytałem: Dlaczego Objective-C nie jest zbyt popularny poza społecznością Apple?

Objective-C jest nadzbiorem języka C (w rzeczywistości znacznie ściślej niż C ++), więc kwestia kompatybilności wstecznej nie pojawia się. Wszystko, co możesz zrobić w C, możesz zrobić w Objective-C.

Bycie w superserii jest binarne, jak ciąża. Obj-C jest nadzbiorem języka C, a C ++ nie.

Co rozumieją przez superset? W jaki sposób cel-C byłby bardziej zbliżony / wstecznie zgodny z C? W jaki sposób obiektywne C jest bardziej zgodne z filozofią C niż C ++?

Czy jakikolwiek program w C może być skompilowany bez modyfikacji przez kompilator z celem C (100% zgodność)?

Jest to bardziej kwestia projektowania i kompatybilności języka programowania niż wojny o to, który z nich jest lepszy.

user1115057
źródło

Odpowiedzi:

134

Przygotowałem prosty schemat; nie jest zbyt ładna, ale miejmy nadzieję, że trafia w sedno:

  • Czerwony: zestaw wszystkich programów poprawnych w C, C ++ i Objective-C (stosunkowo mały)
  • Zielony: zestaw wszystkich programów ważnych w C i Objective-C, ale nieprawidłowych w C ++ (jeszcze mniejszy)
  • Szary: zestaw wszystkich programów ważnych w Objective C i C ++, ale nieprawidłowych w C (pusty, o ile wiem)
  • Niebieski: zestaw wszystkich programów ważnych tylko w celu C (stosunkowo duży)
  • Żółty: zestaw wszystkich programów ważnych tylko w C ++ (największy)

Zestaw ważnych programów w języku C (w kolorze czerwonym i zielonym) jest ścisłym podzbiorem zbioru ważnych programów w języku Cel C (na niebiesko)

wprowadź opis obrazu tutaj

Escualo
źródło
14
A co z obiektywnym C ++?
user1115057
14
Dziwne podobieństwo ...: justindomke.files.wordpress.com/2008/11/scalaimage11.png
user1115057
19
W jakim stopniu według Ciebie kolor żółty jest tutaj „większy” niż niebieski? Intuicja podpowiada mi, że oba zbiory byłyby policzalnie nieskończone.
wim
4
@wim: I oba są reprezentowane jako niepoliczalne podzbiory R ^ 2;) To ta sama sztuczka, ponieważ zobaczysz N wewnątrz Q, mimo że mają ten sam rozmiar (a N to ścisły podzbiór Q).
Maciej Piechotka
3
Myślałem o tym trochę więcej i zdałem sobie sprawę, że zestaw ObjC ++ tak naprawdę nie obejmie tego wszystkiego. Jest to nadzbiór C ++, ale nie ścisły nadzbiór ObjC. Te same programy, które są legalnym C, ale nielegalnym C ++ (zielony obszar), są nielegalnymi ObjC ++.
Rob Napier,
62
  1. Co rozumieją przez superset?

    Oznaczają ścisły nadzbiór. Każdy poprawny program w C skompiluje się za pomocą kompilatora Objective-C. Niektóre prawidłowe programy w C nie będą się kompilować za pomocą kompilatora C ++.

  2. W jaki sposób cel-C byłby bardziej zbliżony / wstecznie zgodny z C?

    Oto prosty przykład:

    int *foo = malloc(12);
    

    Kompiluje się w C i Objective-C, ale nie w C ++. Oczywiście są też inne przykłady.

  3. W jaki sposób obiektywne C jest bardziej zgodne z filozofią C niż C ++?

    Wszystko - Objective-C jest ścisłym nadzbiorem C.

  4. Czy jakikolwiek program w C może być skompilowany bez modyfikacji przez kompilator z celem C (100% zgodność)?

    Tak.

Carl Norum
źródło
2
Tak, to było by w porządku. Prawdopodobnie nie potrzebujesz też Objective-C dla GUI, jeśli chcesz dowiedzieć się, jakich funkcji uruchomieniowych niskiego poziomu użyć.
Carl Norum,
3
W większości filozoficzne.
Carl Norum
2
+1 Świetne wyjaśnienie. Sugerowałbym, że kwestia „filozofii C” jest nieco niejasna, ale większość obserwatorów prawdopodobnie zgodziłaby się, że „cele” C i „cele” ObjC różnią się. Intencją C jest być bardzo blisko sprzętu, jednocześnie zapewniając kilka użytecznych abstrakcji przenośności, podczas gdy celem ObjC jest wprowadzenie podejścia SmallTalk do C. Ponieważ Cocoa stała się integralną częścią ObjC w ostatnich latach, ta rozbieżność jest jeszcze silniejsza. „Filozofia” (podejście projektowe) tablicy C i NSArray są z pewnością bardzo różne.
Rob Napier,
2
To zależy całkowicie od programu. Prawdopodobnie nie zrobiłbyś zbyt wielu rzeczy w stylu C w programie Objective-C. Dlaczego więc miałbyś używać Objective-C?
Carl Norum,
1
@ user1115057: nie powinieneś się zbytnio przejmować tym, jak rzeczy są brane pod uwagę. Istnieją dwa problemy z pisaniem kodu w C ++, który kompiluje się jako (lub przynajmniej tak wygląda) C. Po pierwsze, nie uzyskujesz żadnych korzyści z C ++, ale to jest twoje wezwanie. Najważniejsze jest to, że piszesz w zepsutym dialekcie C, który tak naprawdę nie jest C. Zamiast tego powinieneś skompilować swój kod C za pomocą kompilatora C i połączyć go z kodem C ++. Ta ostatnia obawa nie dotyczy Objective-C, ponieważ podzbiór Objective-C, który kompiluje się jako C, to C.
Steve Jessop
31

Od samego początku C ++ został zaprojektowany jako „lepsze C”, naprawiając zaniedbania projektowe, zarówno rzeczywiste, jak i postrzegane, gdy autorzy C ++ przeszli przez język. Rezultatem tej decyzji projektowej było to X, że bycie poprawnym programem w C nie gwarantuje, że Xbędzie się kompilował, nie mówiąc już o uruchomieniu, podczas przetwarzania przez kompilator C ++. Zmiany dotyczyły takich podstawowych konstrukcji, jak literały łańcuchowe (stały się const char*), przypisywanie voidwskaźników, konwersje między enums i typami całkowitymi, semantyka operatorów przypisania złożonych i tak dalej.

Co więcej, gdy pojawił się C99, funkcje, które przeszły do ​​zaktualizowanego standardu C, zostały pominięte w zaktualizowanym standardzie C ++. Ponownie, bardzo ważne funkcje języka zostały pominięte - w szczególności wyznaczone inicjatory i tablice o zmiennej wielkości.

W przeciwieństwie do tego, Objective C został umieszczony jako nadzbiór języka C, wymagając, aby wszystkie prawidłowe programy w C były kompatybilne z kompilatorem Objective C.

Sergey Kalinichenko
źródło
4
Odpowiedziałem na to pytanie, ponieważ wiem, co to jest „nadzbiór”, ale nie wiem nic o Objective-C. W innym pytaniu SO widziałem twierdzenie, że prawidłowy fragment kodu C int nil = 0; nil++;nie kompiluje się jako Objective-C. Jaki jest problem, czy jest oczywistą rzeczą, że Objective-C udostępnia dostępne nagłówki, które po dołączeniu mogą złamać twój kod dokładnie tak, jak mogą to zrobić nagłówki C. Dlatego autor tego fragmentu nie powinien ich uwzględniać.
Steve Jessop,
2
„nil” to właściwie #define, a nie słowo kluczowe. Widzisz problemy, ponieważ uwzględniono objc / objc.h. Jest to podobne do problemów, które napotkałbyś, gdybyś próbował utworzyć zmienną o nazwie TAK. (Xcode podkreśla je tak, jakby były naprawdę słowami kluczowymi, ponieważ o wiele łatwiej jest o tym myśleć w ten sposób; ale są zaimplementowane jako prosty kod w C.)
Rob Napier,
4
Przy okazji, warto trochę pogrzebać w objc.ha, jeśli interesuje cię, jak ObjC żyje nad C. Rzeczy, które myślisz, że byłyby słowami kluczowymi (id, BOOL, Class, nil itp.) To tylko proste typy, struktury i definiuje. Możesz nawet zaimplementować ręczne przekazywanie wiadomości w czystym C. Nigdy, przenigdy tego nie rób. : D Ale możesz. github.com/iosptl/ios6ptl/blob/master/ch28/Runtime/MyMsgSend.c
Rob Napier,
2
@DanNeely: Rob Napier powiedział „nigdy, przenigdy tego nie rób” jako komentarz dotyczący połączonego pliku. Połączony plik nie jest środowiskiem wykonawczym Objective-C, to tylko szybki hack, który pokazuje, jak naprawdę działa obsługa wiadomości.
Dietrich Epp
1
Połączony plik nie pokazywał, jak skomplikowane jest przekazywanie wiadomości ObjC. Pokazuje, że środowisko uruchomieniowe jest dostępne z C i że w zasadzie można konwertować kod ObjC do czystego C. ALE… to jest tak powolne, jak można to zbudować. Opierał się na mojej znajomości zwracanego typu metod (a dla niektórych typów zwracanych prawdopodobnie musiałbym znać typ procesora) i starannie wybrałem metody, które nie przyjmują parametrów. Pełne rozwiązanie ma wiele subtelnych sztuczek (części muszą być w asemblerze, ponieważ oszukują ramkami stosu). Nigdy nie powinieneś próbować go odbudowywać.
Rob Napier,
12

„Cel-C jest nadzbiorem C” oznacza, że ​​każdy poprawny program w C jest poprawnym programem Celu C (o tym samym znaczeniu).

To jest czasami powiedział, choć nie przez ekspertów C ++, C ++, który jest rozszerzeniem C. To nie jest dokładna, dlatego Twój cytat jest dokonanie wielkiego porównywania dwóch.

Steve Jessop
źródło
9

Cel C to zestaw wstecznie kompatybilnych rozszerzeń C. Jest to możliwe, ponieważ cechy celu C są rozgraniczone na dwa bardzo proste sposoby:

  • użycie znaku @. Ten znak nie jest obecnie używany w języku C.
  • prosty składniowym rozszerzeniem dla wywoływania metod [obj method:argument]. W języku C nawiasy kwadratowe są używane w bardzo specyficzny sposób do indeksowania tablic, więc jest to niepoprawna składnia C. Rozszerzenia oparte na nieprawidłowej składni nie zmieniają znaczenia niczego, co jest poprawne w języku hosta.

Tak łatwo zauważyć, że żaden program, który używa rozszerzeń Objective C, nie może być programem ściśle zgodnym z ISO C, bez względu na to, jak prosty. Ponadto każdy program ISO C można z definicji zadeklarować jako ważny program Celu C. Cel C może z łatwością podążać za zmianami, takimi jak C99 i C11.

Z drugiej strony, C ++ to nie tylko rozszerzenie C; jest to inny język, który zmienia znaczenie niektórych składni C. C ++ i C są utrzymywane osobno, więc ich związek zmienia się w czasie. Na przykład C uzyskał nowe funkcje, które są całkowicie nieobecne w C ++ i prawdopodobnie nie przejdą do C ++, takie jak tablice C99 o zmiennej długości. C ++ nie może łatwo znaleźć nowych funkcji C.

Jeśli piszesz przenośny program w C, powinien on być jednocześnie programem Objective C. Potrzebna będzie jednak dodatkowa uwaga, aby był to również program w C ++ o tym samym znaczeniu. (Ta praktyka nie jest niczym niezwykłym, a dialekt, którego wymaga, jest nieformalnie nazywany „czystym C”).

Prostym przykładem programu w C, który ulega awarii, gdy jest traktowany jako C ++, jest dowolny program w C, który używa słowa kluczowego C ++ jako identyfikatora, takiego jak classlub virtual. Cel C nie wprowadza żadnych zastrzeżonych słów kluczowych. Ma nowe słowa kluczowe, które są wprowadzane przez @postać, na przykład @interface.

Kaz
źródło