Kiedy używać C w C ++, a C ++ w C?

164

Od nieco ponad roku zapoznałem się z informatyką i z mojego doświadczenia wynika, że ​​zarówno C, jak i C ++ są uważane za języki „ultraszybkie”, podczas gdy inne, takie jak Python i takie języki skryptowe są zwykle uważane za nieco wolniejsze .

Ale widziałem również wiele przypadków, w których projekt oprogramowania lub nawet mały przeplatałby pliki, w których pewna liczba n tych plików byłaby zapisana w C, a pewna liczba m tych plików byłaby napisana w C ++.

(Zauważyłem również, że pliki C ++ prawie zawsze mają odpowiednie nagłówki, podczas gdy pliki C nie tak bardzo). Ale moim głównym pytaniem jest uzyskanie ogólnego wyczucia intuicji, kiedy należy używać C nad C ++, a kiedy lepiej jest używać C ++ nad C. Poza faktami, że (1) C ++ jest zorientowany obiektowo, podczas gdy C nie jest, a (2) składnie są bardzo podobne, a C ++ został celowo stworzony, aby pod wieloma względami przypominać C, nie jestem pewien, jakie są ich różnice. Wydaje mi się, że są (prawie) doskonale wymienne w wielu dziedzinach.

Byłoby więc mile widziane, gdyby ktoś mógł wyjaśnić sytuację! Dzięki

Mroczny Templariusz
źródło
4
Użycie C inline w kodzie C ++ jest zwykle w przypadku niektórych modułów, które muszą być wysoce zoptymalizowane, wykonują prace na bardzo niskim poziomie bliżej sprzętu lub są krytyczne dla integralności danych, a nawet bezpieczeństwa ludzi i muszą być możliwe do skontrolowania i udowodnienia poprawności. Zamiast robić to wszystko w C, większość projektu może skorzystać z funkcji C ++ dla elastycznych projektów, jednocześnie uzyskując korzyści z ciasności C w tych miejscach, w których jest to potrzebne.
kylben
30
@kylben: Wielu facetów C ++ powie Ci: (1) Wydajność nie jest powodem do spadku do C (być może do uniknięcia virtuali kilku innych funkcji, które uniemożliwiają optymalizację, ale np. nieklasy virtualnie są z natury nieefektywne, a szablony są potężne narzędzie abstrakcyjne, które może faktycznie prowadzić do większej wydajności - np. qsortvs std::sort). (2) Duże znaczenie prawidłowości jest to powód, aby korzystać z C ++ (typesafety, constNess private, RAII aby zarządzanie zasobami opanowania, etc.) na C lub o to chodzi, użyj Ada albo coś w pierwszej kolejności.
11
@ Pubby8 Nie zgadzam się z tym. Jeśli pracuję nad plikiem .c i widzę, że ludzie to robią, zwykle mentalnie oflaguję ich jako nie wiedzących, co robią. Na przykład nie ma potrzeby przesyłania z void*innego typu wskaźnika w kodzie C, jest to bardzo rozpraszające i typowe dla osób, które nie znają C.
asveikau 10.10.11
4
@kylben: (Możesz nauczyć się poprawnie zwracać się do innych w odpowiedziach na komentarze, aby mieli szansę ich zobaczyć .) To, że „programista dobrze obeznany z tym, jak kompilator zamienia C w asm”, działałoby w C ++ tak samo jak dobrze. Ale to po prostu nieistotne: jeśli chcesz zagłębiać się w asm, po prostu napisz asm zamiast tworzyć kompilator z innego języka. W końcu sposób, w jaki to robi, może się zmieniać przy każdej aktualizacji kompilatora.
sbi,
9
Moim skromnym zdaniem ... używasz C, kiedy chcesz, dla mnie: C jest znacznie prostszy i łatwiejszy w użyciu niż C ++ ... C ++ może wyglądać jak „C z klasami”, ale już nie jest, teraz jest bardzo złożony język z wirtualnymi konstruktorami i szablonami.
dysoco

Odpowiedzi:

184

Kiedy wybierasz C

  • potrzebujesz przenośnego asemblera (którym naprawdę jest C) z jakiegokolwiek powodu,
  • Twoja platforma nie zapewnia C ++ (kompilator C jest znacznie łatwiejszy do wdrożenia),
  • musisz wchodzić w interakcje z innymi językami, które mogą wchodzić w interakcje tylko z C (zwykle najniższym wspólnym mianownikiem na dowolnej platformie), a twój kod składa się z niewiele więcej niż interfejsu, nie czyniąc z tego powodu wartego umieszczenia interfejsu C na kodzie C ++,
  • włamujesz się do projektu Open Source (wiele z różnych powodów trzyma się C),
  • nie znasz C ++.

We wszystkich innych przypadkach powinieneś wybrać C ++.

rev sbi
źródło
15
Dodałbym również, że C ++ z modelem wyjątków czasami sprawia więcej problemów, niż jest to warte, powiedzmy, jądra systemu operacyjnego. Przynajmniej takie ogólne odczucie mam podczas czytania o różnych rzeczach.
Koder
12
@SF: C jest lingua franca? To coś nowego. A raczej bardzo stary. Może jeśli rozmawiasz tylko z ludźmi, którzy nie uczyli się nowych języków przez ostatnie 20 lat, ale powiedziałbym, że znajomość języka C nie jest już tak powszechna.
DeadMG,
13
@SF .: Jak pisałem gdzie indziej, brałem udział w projektach, które wyniosły miliony LoC, i widziałem bardzo niewiele meta-rzeczy w porównaniu do projektów C z ich nieuniknionym i wszechobecnym hakowaniem makr. (OTOH, możliwość tworzenia EDSL w razie potrzeby może być niewiarygodnie potężnym narzędziem w twoim pudełku.) Jeśli chodzi o C jako lingua franca: Wolę trzymać się terminu, że jest to najniższy wspólny mianownik. I nie chciałbym, aby osoby z umiarkowanymi umiejętnościami programistycznymi hakowały jądro systemu operacyjnego.
sbi,
18
@ Max: Całkowicie się nie zgadzam. C jest językiem bezużytecznym, chyba że jakaś nie do pokonania praktyczna bariera uniemożliwia użycie C ++.
DeadMG,
17
@ Przyciski: To ty zgłosiłeś roszczenie („C ++ potrzebuje więcej pamięci”), więc to ty popieraj to. I nie, nie twierdzę, że C ++ potrzebuje mniej pamięci. To, co mówię, to koszt funkcji , bez względu na to, czy kompilator implementuje je dla ciebie (funkcje wirtualne), czy robisz to sam (tablica wskaźników funkcji).
sbi
88

Jest kilka powodów, dla których wolę C. Najważniejsze jest to, że trudniej jest stworzyć naprawdę małe pliki wykonywalne w C ++. W naprawdę małych systemach i tak rzadko piszesz dużo kodu, a dodatkowe miejsce w pamięci ROM, które byłoby potrzebne dla C ++ zamiast C, może być znaczące.

Powinienem jednak dodać, że w naprawdę małych systemach C ma problemy z dokładnie tego samego powodu, a język asemblera jest prawie jedynym rozsądnym wyborem. Zakres rozmiarów systemu, w którym C naprawdę ma sens, jest dość mały i stale się kurczy (choć przyznaję, dość powoli).

Innym powodem / powodem użycia C jest zapewnienie zestawu funkcji, z którymi można się połączyć w zasadzie z dowolnego innego języka. Państwo może pisać te funkcje w C ++, definiując je jako extern "C"funkcje, ale robi tak ogranicza te funkcje do przedstawienia się „twarzą” zasadniczo C-life na świat - zajęcia, przeciążone funkcje, szablony i funkcje składowe, etc., nie trzeba zastosować. Nie musi to jednak ograniczać rozwoju do C - całkowicie uzasadnione jest korzystanie z wewnętrznych funkcji C ++ , o ile interfejs zewnętrzny wygląda jak C.

Jednocześnie muszę powiedzieć, że odpowiedzi @ Toll (dla jednego oczywistego przykładu) mają pod pewnymi względami pewne cechy wstecz. Rozsądnie napisane C ++ będzie na ogół co najmniej tak szybkie jak C, a często co najmniej trochę szybsze. Czytelność jest na ogół znacznie lepsza, choćby dlatego, że nie zakopano się w lawinie całego kodu nawet dla najbardziej trywialnych algorytmów i struktur danych, obsługi błędów itp.

Szablony nie „rozwiązują problemu z systemem typów języka”, po prostu dodają szereg podstawowych możliwości prawie całkowicie nieobecnych w C i / lub C ++ bez szablonów. Jednym z pierwotnych założeń było zapewnienie pojemników bezpiecznych dla typu, ale w rzeczywistości wykraczają one daleko poza to - zasadniczo żaden z nich nie zapewnia C.

Zautomatyzowane narzędzia to w większości również czerwony śledź - choć prawdą jest, że pisanie parsera C jest mniej pracy niż pisanie parsera C ++, w rzeczywistości nie robi on praktycznie żadnej różnicy. Bardzo niewiele osób chce lub jest w stanie napisać użyteczny parser dla jednego z nich. Jako taki, rozsądnym punktem wyjścia jest Clang w obu kierunkach.

Tak się składa, że ​​C i C ++ są dość często używane razem w tych samych projektach, prowadzonych przez te same osoby. Pozwala to na coś, co poza tym jest dość rzadkie: badanie, które bezpośrednio, obiektywnie porównuje łatwość utrzymania kodu napisanego w dwóch językach przez osoby, które są jednakowo kompetentne (tj. Dokładnie te same osoby). Przynajmniej w powiązanym badaniu jeden wniosek był jasny i jednoznaczny: „Odkryliśmy, że użycie C ++ zamiast C skutkuje lepszą jakością oprogramowania i mniejszym nakładem prac konserwacyjnych ...”

Jerry Coffin
źródło
12
Wsparcie narzędzi nie jest czerwonym śledziem. To prawda, że ​​obecnie mamy brzęk. Ale narzędzie wsparcia dla C ++ nie pozostają w tyle znacznie oder językach, nawet w IDE big-shot. Dlaczego? Proste, ponieważ do niedawna nie było żadnego brzęku (a GCC nigdy nie była alternatywą). Jeszcze może pół roku temu, jeśli potrzebowałeś kodu C ++ w wersji AST, zasadniczo nie miałeś szczęścia lub tysiące dolarów (jeśli kupiłeś nakładkę EDG).
Konrad Rudolph,
5
+1, a dla przypomnienia, regularnie piszę kod C ++ dla 8-bitowych procesorów z ROMami 4KiB.
avakar
2
+1 za ogólną świetną odpowiedź. Czego nie rozumiem (nie mam doświadczenia). Dlaczego (chyba mówimy, że jest osadzony?) Kompilator C powinien wytwarzać mniejszy kod wykonywalny niż kompilator C ++, biorąc pod uwagę ten sam zestaw funkcji ? Może mógłbyś podać jakieś referencje?
Martin Ba,
2
@ Martin: najważniejsze jest to, że C ++ obejmuje obsługę wyjątków, co (przynajmniej zwykle) dodaje pewne minimum do rozmiaru pliku wykonywalnego. Większość kompilatorów pozwoli ci wyłączyć obsługę wyjątków, ale kiedy to zrobisz, wynik nie jest już całkiem C ++. Podejrzewam, że jest też trochę z prostego faktu, że wielu dostawców kompilatorów C ++ po prostu nie pracuje tak ciężko przy tworzeniu najmniejszego możliwego kodu wyjściowego.
Jerry Coffin
3
„Odkryliśmy, że użycie C ++ zamiast C poprawia jakość oprogramowania i zmniejsza nakłady konserwacyjne ...”, to jest wniosek, o którym należy pamiętać.
Stephane Rolland
24

Różnice między C i C ++ zostały już tutaj szczegółowo wyliczone . Chociaż czasami ludzie mogą mieć uzasadnione powody, aby wybrać jedno lub drugie (C ++ dla OOP lub C, gdy czują, że dodatkowe funkcje C ++ wprowadzają na przykład niepożądany narzut), z mojego doświadczenia wynika, że ​​zwykle sprowadza się to do preferencji. Co ludzie pracujący nad tym plikiem wiedzą lepiej i lubią lepiej? Uważam, że jest to najczęściej przyczyną, ponieważ prawdą jest, że oba te języki radzą sobie z aplikacjami krytycznymi pod względem wydajności.

(Uwaga dodatkowa: Sprawdź zdanie Linusa Torvadsa dotyczące tego, dlaczego woli C od C ++. Niekoniecznie zgadzam się z jego punktami, ale daje to wgląd w to, dlaczego ludzie mogą wybrać C zamiast C ++. Raczej ludzie, którzy się z nim zgadzają może wybrać C z tych powodów.)

Casey Patton
źródło
51
-1na rant Linusa. : - {
sbi 10.10.11
12
Nie pomniejsz za to mnie! Ha ha. Nie zgadzam się z Linusem, ale jest to całkiem dobry przykład DLACZEGO ludzie mogą wybrać C zamiast C ++ (jeśli wierzą w to, w co wierzy Linus). Nie komentuję zasadności tych powodów.
Casey Patton
10
@CaseyPatton: Zasadniczo głosuję za każdą odpowiedzią, która przedstawia tę retorykę bez komentarza, jak gdyby był to prawdziwy argument.
sbi,
11
@ Koder: W ogóle nie musisz znać implementacji STL. Istotą STL jest to, że nie musisz znać implementacji, chyba że polegasz na zachowaniu nie zdefiniowanym przez Standard - w takim przypadku, po co zawracać sobie głowę używaniem biblioteki Standard? Co więcej, nie jest to trochę szalone, że nie lubię języka z powodu tego, jak zachowują się jego programiści. Programiści C zachowują się tak, jak C jest darem Bożym dla Człowieka i są zbyt ślepi, aby dostrzec oczywistą prawdę, że C ++ oferuje funkcje, które są zasadniczo i wewnętrznie bezpośrednio lepsze od C, takie jak RAII.
DeadMG,
8
@ Koder: Jeśli skończysz z tak wieloma współużytkowanymi parametrami pojedynczego obiektu, że przepełnisz licznik wewnętrzny, robisz to źle. Standard określi minimalny rozmiar licznika - prawdopodobnie 32-bitowy - i jest to dość nierealne, aby mieć więcej niż 2 miliardy share_ptrs na jednym obiekcie. Nawet jeśli sam obiekt miał rozmiar 0 i miałeś zerowy narzutnik pamięci, to nadal zużywasz 16 GB pamięci, tylko na share_ptrs.
DeadMG
13

Głównym problemem, którego brakuje w istniejących odpowiedziach (w chwili opublikowania tego posta), jest wybór.

To proste. Jeśli z jakiegoś zupełnie irracjonalnego powodu uważasz, że wyjątki nie są warte kosztów ogólnych, nie musisz ich używać . Nadal możesz mieć szablony i RAII oraz bibliotekę Standard i nigdy nie pisać ani jednego „rzutu”. To samo dotyczy szablonów. Jeśli z jakiegoś powodu uważasz, że powodują nieodwracalne (i faktycznie ważne, co dzieje się tylko na wbudowanym) wzdęciu wykonywalnym, to niespodzianka - możesz także używać void * i sizeof (T) przez cały dzień. Nic nie zmusza Cię do korzystania z funkcji C ++ w porównaniu do C.

Właśnie dlatego C ++ jest z natury lepszym językiem - możesz bez problemu wybierać pożądane funkcje i wracać do programowania w stylu C, jeśli nie lubisz danej funkcji. Dlatego, biorąc pod uwagę, że C ++ jest wszystkim, czym jest C i więcej, oczywistym faktem jest, że C ++ jest lepszym językiem. Sugerowanie inaczej jest jak próba zasugerowania, że ​​4 jest większe niż 5.

DeadMG
źródło
1
Zgodnie z twoim rozumowaniem pierwotne pytanie nie ma sensu i dlatego powinno zostać zamknięte. Sądzę, że pytanie powinno brzmieć mniej więcej tak: kiedy powinniśmy ograniczyć się do podzbioru C C ++ (użyj zwykłego C), a kiedy ma sens użycie pełnego C ++.
Giorgio
To prawda, ale tylko w przypadku jednej osoby pracującej nad własnym małym projektem. W prawdziwym życiu prawie wszyscy spędzają może połowę swojego czasu pracując nad kodem innych ludzi. Niestety większość innych ludzi „źle myśli” w odniesieniu do tych całkowicie irracjonalnych powodów.
DarenW,
1
@DeadMG: W jaki sposób alokatorzy mają zgłaszać błędy bez zgłaszania wyjątków? Ponadto dodanie większej liczby funkcji niekoniecznie jest lepsze, gdy wszystko, co robi, to zwiększenie złożoności lub nadmiarowości.
Mankarse,
@Mankarse: Jeśli kompilujesz z opcjami wyłączenia wyjątków, alokatorzy albo przerywają program, albo wesoło przystępują do używania wskaźnika zerowego, w zależności od implementacji biblioteki.
Zan Lynx,
4
@Mankarse: Od czasu mojego doświadczenia w 2007 roku, kiedy próbowałem uruchomić system Linux z 1 GB pamięci RAM i bez wymiany, prawie wszystkie programy komputerowe zawodzą w straszny, okropny sposób, gdy i tak kończy się przydział pamięci.
Zan Lynx
9

Rzeczy na temat C ++, które denerwują programistów C.

Pod maską dzieje się dużo magii; konstruktory, destruktory, wirtualne metody, szablony itp. mogą znacznie ułatwić i przyspieszyć pisanie kodu C ++ niż równoważny kod C, ale trudniej go zrozumieć i zrozumieć (w zależności od tego, jak dobrze znasz C ++ i związane z nim konwencje). Coś tak prostego, co Foo newFoo;może wywoływać dużo kodu, w zależności od tego, jak Foozdefiniowano konstruktor klasy (i dowolne klasy, od których zależy). Dlatego konwencja polega na pisaniu ++itzamiast na it++iteracji przez kontener, ponieważ postfiks ++często wymaga kosztownej operacji kopiowania.

W zależności od tego, co robisz, mogą występować pewne trywialne koszty ogólne, szczególnie w przypadku prostych zadań. Weź następujące dwa programy, pierwszy w C, drugi w C ++:

/* C version */
#include <stdio.h>
int main(void)
{
  char greeting[] = "Hello, world";
  printf("%s\n", greeting);
  return 0;
}
/* end C version */

/* C++ version */
#include <iostream>
#include <string>
int main(void)
{
  std::string greeting("Hello, world");
  std::cout << greeting << std::endl;
  return 0;
}
/* end C++ version */

Identyczne zachowanie, niezbyt duża różnica w zakresie źródła, ale na pudełku SLES 10, nad którym pracuję z gcc 4.1.2, pierwszy generuje plik wykonywalny o wielkości ~ 9 kb, podczas gdy drugi zajmuje 12,5 kb (bez optymalizacji ), prawie 28% większy. Typ C ++ stringjest o wiele łatwiejszy do pracy z IMO niż biblioteka ciągów C, a strumienie C ++ są o wiele bardziej elastyczne i konfigurowalne niż strumienie C, ale w przypadku tak naprawdę martwego kodu, takie mogą nie być warte narzutu.

C ++ to ogromny język w porównaniu do C, z pewną niezwykle złożoną semantyką. Osiągnięcie biegłości w posługiwaniu się C ++ zajmuje dużo więcej czasu, co oznacza, że ​​wiele osób, które twierdzą, że znają C ++, nie zna go tak dobrze, jak im się wydaje.

Rzeczy na temat C, które denerwują programistów C ++

C nie jest bezpiecznym językiem programowania w żadnym stopniu wyobraźni; brak ograniczeń sprawdzania tablic prowadzi do wielu możliwych do wykorzystania zachowań (czy to poprzez martwą getsfunkcję, czy poprzez scanfspecyfikatory %si %[). C ++ daje przynajmniej kontenery, które zgłaszają wyjątki, jeśli próbujesz uzyskać dostęp poza ich obecnie zdefiniowanym zakresem; wszystko, co daje Ci, to (jeśli masz szczęście) naruszenie segmentacji.

Zarządzanie pamięcią w C jest bardzo pracochłonne i podatne na błędy, w porównaniu do narzędzi, które udostępnia C ++. Jeśli budujesz swój własny kontener, jesteś odpowiedzialny za dopasowanie wszystkich połączeń malloci free, upewnienie się, że alokacje są udane, wycofanie częściowych alokacji w przypadku błędu itp. W C ++ dodajesz elementy do lub wyjmij przedmioty z pojemnika. Jeśli wystąpi problem, zostanie zgłoszony wyjątek.

Podobnie, obsługa błędów w C jest uciążliwa w porównaniu do narzędzi udostępnianych przez C ++ (mianowicie wyjątków). Naprawdę fajne jest to, że przydzieliłeś sporo pamięci, a potem uderzyłeś w ścianę podczas przetwarzania; gdy musisz się wycofać, musisz zwolnić tę pamięć we właściwej kolejności. W przypadku zasad C ++ i RAII jest to (stosunkowo) łatwe.

Więc kiedy używam jednego nad drugim?

Jeśli to, co piszesz, jest bajecznie proste, przeczytaj je / zrób z nim / pozbądź się aplikacji, której zachowanie można opisać w kategoriach danych wejściowych i wyjściowych oraz wydajności, a następnie preferuj C niż C ++. W przeciwnym razie preferuj C ++

John Bode
źródło
2
Zarządzanie pamięcią jest skomplikowane i podatne na błędy w niektórych przypadkach, ale szczególnie w świecie osadzonym często praktyczne jest pisanie programów w języku C przy użyciu całkowicie statycznej alokacji pamięci. Jeśli program łączy się, nie może zabraknąć pamięci w czasie wykonywania. Czy takie gwarancje można łatwo osiągnąć w C ++?
supercat
9

Bjarne Stroustrup prowadzi listę aplikacji i firm korzystających z C ++; możesz kłócić się o programowanie vs programowanie OOP, ile chcesz, ale nie możesz kłócić się z wynikami branży w ciągu ostatnich 20 lat.

C ++ jest powszechnie stosowany w dużych projektach złożonych dla wielu osób, w których oddzielne osoby muszą pracować na modułowych komponentach. Oczywiście możesz budować i utrzymywać zmodularyzowany kod w C, ale wrodzona natura C ++ w OOP prowadzi do doskonałej modularyzacji, testowalności i ponownego wykorzystania kodu.

Standardowa biblioteka C ++ (STL), sama w sobie z jedynie wektorami i mapami, jest wystarczającym powodem do używania C ++.

C jest powszechnie używany w systemach wbudowanych.

Osobiście użyłbym C tylko, jeśli istnieje biblioteka, która ma tylko C API.

stackoverflowuser2010
źródło
19
Ostatnie zdanie nie jest powodem do użycia C. Możesz wywoływać biblioteki C z C ++.
user207421,
2
Użyłem c ++ do projektu DSP - nie c
BЈовић
9

Powiedziałbym, że głównym powodem, dla którego wybrałem C zamiast C ++, jest tylko wtedy, gdy musiałbym uciekać się do tego typu „NASZ MUSI BYĆ 1000% stabilny”.

C ++ wynosi ~ 99% C, gdy patrzymy na wydajność, i jest o wiele bardziej produktywny. Więc nawet będąc w C możesz pisać kod, który będzie szybszy niż C ++ (możesz użyć podzbioru C ++ bez wyjątków, wirtualnych, streamingów, abstrakcji itp., Ale to w zasadzie C), czas na optymalizację każdej cholernej rzeczy podczas gdy STL jest testowany i już to robi, kosztowałoby Cię więcej niż niewielki wzrost wydajności, który możesz osiągnąć lub poświęcić, ponieważ algorytmy STL zostały napisane przez grupy ekspertów i prawdopodobnie nie jesteś ekspertem we wszystkim.

Z drugiej strony C ++ ma mnóstwo abstrakcji. Gdy w pewnych okolicznościach wyciekają, wpadasz w kłopoty. I jest niewiele osób, które znają 100% gotcha C ++, podczas gdy, myślę, że jest więcej, którzy znają wszystkie gotcha C, więc napisanie rozwiązania, w którym każdy krok jest w pełni zrozumiały dla wszystkich członków zespołu, jest znacznie łatwiejsze w C.

Przykład: Czy wiesz, kiedy shared_ptr<smthn>przepełni liczbę referencyjną, czy zgłosi wyjątek? Takie rzeczy nie są fajne, kiedy Shuttle musi ponownie wprowadzić atmosferę, przynajmniej tak sądzę.

Ponadto obsługa wyjątków jest bardzo, bardzo trudna w porównaniu z kodami błędów. Trudno sprawdzić, czy klasa jest w 100% bezpieczna pod względem wyjątków i czy łatwo się w nią dostać. Wiele osób o wysokiej reputacji wyraziło tę opinię.

Koder
źródło
12
I w jaki sposób dokładnie ręczne zarządzanie pamięcią jest „bardziej stabilne” niż abstrakcje w C ++, takie jak std::stringi tym podobne? Czy próbowałeś kiedyś podać platformę, na której shared_ptrprzepełniłby się licznik? To byłaby jedna zabawna platforma. A jeśli uważasz, że obsługa wyjątków jest trudna, powinieneś rzucić okiem na kawałek kodu C, który sprawdza każdy możliwy błąd przy każdym wywołaniu funkcji. (Przyznaję, że taki kod jest trudny do zdobycia, ale to tylko mocniejszy argument przeciwko twojemu stwierdzeniu.) Przepraszam, ale to są naprawdę bydlęce odchody.
sbi 10.10.11
12
@Lundin: „Implementacje„ musi być stabilne w 1000% ”, nie pozwalają przede wszystkim na dynamiczny przydział pamięci”. A co powstrzymuje cię przed zrobieniem dokładnie tego w C ++ ?? (A udzielanie
ogólnych
10
@Lundin: Dobrze, że zacząłeś przedstawiać argumenty, a nie retorykę. Ale są słabi. To, że „zapomniałeś” jedną z głównych cech C ++ (szablonów), która sprawia, że ​​kod jest bezpieczniejszy (ponieważ pozwala na wykonywanie algorytmów - a tym samym na niepowodzenie - w czasie kompilacji , eliminując błędy w czasie wykonywania), nie mówić za swoją znajomością języka, który oceniasz. Redukcja C ++ do języka OO była wcześniej krytykowana z dobrych powodów. (Poza tym klasy z deterministycznym zniszczeniem są doskonałym narzędziem i
pomagają
9
@Lundin Oczywiście nie chcesz używać, std::stringjeśli nie chcesz dynamicznej alokacji. Użyłbyś std::basic_string<char, std::char_traits<char>, some_allocator_here>.
Luc Danton,
10
@Coder: Co według nich udowodnisz? Pierwszy to po prostu zły kod (i byłoby tak samo złe zgłaszanie błędów, jak zwracane wartości), drugi argumentuje za RAII nad ręcznym czyszczeniem, do którego dopingowałby każdy pół przyzwoity programista C ++, a Joel tak samo jak ja szanuję go, powiedziałem kilka rzeczy, z którymi zdecydowanie się nie zgadzam. Jego wtyczka do pojedynczego wejścia-pojedynczego wyjścia bardzo cuchnie niedoinformowanym starym pierdnięciem, który nigdy nie zgodzi się, że to, czego nauczył się 25 lat temu, zostanie przekroczone. (Pamiętaj, że został programowania 25 lat temu, kiedy Sese był stan techniki.)
SBI
6

C to przenośny zestaw z lepszą składnią, dający programatorowi pełną kontrolę nad wszystkim .

Z drugiej strony C ++ wykonuje wiele funky magii (funkcje wirtualne, przeciążanie, automatyczna konwersja itp.), Które mogą być niepożądane, jeśli chcesz się upewnić:

  • nie używaj więcej pamięci niż chcesz
  • nie uzyskuj dostępu do stron pamięci willy nilly (vtable może być wszędzie)
  • nie wywołuj przypadkowo dużej ilości kodu

I chcesz czegoś naprawdę prostego w pracy, ponieważ koncentrujesz się na wydajności.

Po prostu nie ma niespodzianek, a to bardzo cenne.

Jeśli chcesz (i polecam), przeczytaj wskazówki dotyczące kodowania JSF na temat tego, o czym powinieneś pomyśleć pisząc C ++ do kontroli lotnictwa wojskowego. Jest tam wiele pułapek, o których musisz wiedzieć, i może cię złapać. Bjarne był częścią tego dokumentu, więc wie, o co chodzi.

Ponadto C kompiluje się jak oparzony troll uderzony piorunem. C ++, OTOH, był prawdopodobnie sponsorowany przez te same osoby, które inwestowały w firmy SSD. :)

(Osobiście wolałbym C ++, ale mi się nie podoba ...... też. ;-P)

Macke
źródło
1
Jest wiele rzeczy, nad którymi C nie oferuje kontroli. Spróbuj napisać wydajny przenośny kod, aby pomnożyć uint32_t przez uint32_t, aby uzyskać wynik uint32_t (dolne 32 bity produktu). Jeśli an intma 64 bity, należy rzucić co najmniej jeden operand, aby uint64_tzapobiec nieokreślonemu zachowaniu, ale konieczność rzutowania na 64 bity w celu obliczenia wyniku 32-bitowego jest - delikatnie mówiąc - „zaskakująca”.
supercat
To nie jest. Kompilator wykonuje takie czynności, jak przydzielanie rejestrów. Nie mogę napisać możliwego do utrzymania kodu w asemblerze, w CI może.
Nils
2

(pod warunkiem, że znasz jednakowo oba języki)

Korzystaj z C ++, chyba że na twojej platformie nie ma kompilatora C ++. Możesz pisać kod C ++ bez jakiejkolwiek części języka, który ci się nie podoba (bez klas, wyjątków, wirtualnego dziedziczenia, jakichkolwiek osobistych ograniczeń, które chcesz zastosować), a następnie w przyszłości, jeśli zdecydujesz, że chcesz trochę te funkcje w końcu można łatwo z nich korzystać. Nic w C ++ nie uniemożliwia pisania kodu w stylu C.

(biorąc pod uwagę równoważne zestawy narzędzi i wiedzę programistów) Nie ma powodu, aby wybierać C zamiast C ++, pod warunkiem, że twoja platforma ma kompilator C ++. Możesz po prostu ograniczyć się do podzbioru języka, który chcesz dzisiaj, pozostawiając otwarte drzwi do rozszerzenia później.

zaraz
źródło
1

Oba języki są doskonałe. Myślę, że wiele plakatów szczegółowo opisuje mocne strony i różne zastosowania każdego z nich. Po prostu dodam to:

Widzę, że język C jest idealny w 4 obszarach: 1) Myślę, że to najlepszy język, którego należy używać podczas nauki dowolnego rodzaju programowania [w połączeniu z pewnym asemblerem i znajomością kodu maszynowego], 2) doskonale nadaje się do pisania sterowników, 3) osadzony oprogramowanie oraz 4) oprogramowanie systemowe na najniższym poziomie.

C ++ jest językiem zorientowanym obiektowo, ale może być również proceduralny (bardzo podobnie jak C). Jeśli pracujesz nad dużymi projektami, oprogramowaniem opartym na graficznym interfejsie użytkownika, oprogramowaniem do gier i innymi rodzajami graficznie intensywnych programów, to C ++, Java, a nawet Objective-C to najlepszy wybór. Istnieje jednak wiele programów wiersza polecenia lub oprogramowania systemowego, w których C ++ może być tak dobry lub lepszy niż C.

Jonathan
źródło
0

Moim zdaniem w tej dyskusji brakuje jednego punktu: w C łatwiej jest zapewnić stabilny interfejs binarny z biblioteki. Zarówno do użytku z innymi językami, jak i C ++.

W C ++ różne kompilatory używają odmiennego nazewnictwa nazw, więc konsumenci biblioteki skompilowanej z innym kompilatorem niż biblioteka mogą mieć problemy z korzystaniem z niej. W przypadku C interfejs binarny jest zwykle standaryzowany dla platformy.

Wiem, że obecnie kompilatory często mają przełączniki do produkcji rzeczy kompatybilnych z gcc, ale to nie zawsze pomaga.

Stosunkowo często obserwuję to na Solarisie. Dystrybucja i różni dostawcy oprogramowania zazwyczaj używają Sun Studio, ponieważ, szczególnie w systemach Sparc, często zapewnia lepsze wyniki. Jednak projekty open source Man są napisane przy użyciu kodu specyficznego dla gcc. Może to być dość uciążliwe dla osób pracujących razem.

Johnnes
źródło
0

C jest prawdopodobnie lepiej niż C ++, gdy generowany jest kod C (np. W implementacjach języków wyższego poziomu). Na przykład istnieje kilka kompilatorów podobnych do Lisp, które emitują kod C (np. Chicken , Scheme48 ...), ale nie znam żadnego, który emitowałby prawdziwy kod C ++ (moje narzędzie MELT emituje kod C ++, ale nie nazywam tego kodu autentycznym Kod C ++, używa bardzo niewielu funkcji C ++).

Kod C jest również łatwiejszy do udowodnienia półautomatycznie. Analizatory statyczne, takie jak Frama-C (w których adnotacje do kodu C są opatrzone komentarzami ACSL w celu wyjaśnienia przyczyny twojego kodu) są dostępne dla C, ale nie tak bardzo dla pełnego C ++ 11.

Basile Starynkevitch
źródło