Wpis z mikrobloga

słowem wstępu

Od przedszkola uznawałem C za język użyteczny na równi z brainfuckiem czy lolcodem. Konieczność oglądania plików, których nazwy zakończone są sufiksem ".c" zawsze wywołuje u mnie zimne poty i senne koszmary przez wiele kolejnych nocy. Niestety czasem jednak zdarza się, że to ja wylosuję najkrótszą zapałkę i muszę zaglądać w niezbadane czeluście sterowników pisanych przez hindusów. Kontakty z C zawsze są dla mnie pouczające i o tym dziś chciałem napisać.

konkrety

W języku C, w przeciwieństwie do C++ (który trzeba szanować!) deklaracja funkcji nie jest równoznaczna z jej prototypem, co może prowadzić do bardzo nieprzyjemnych konsekwencji. Zamiast jednak opowiadać dalej, zaprezentuję przykład (w spojlerze bo monospace daje).


static int fun();


int main(int argc, char ** argv)


{


int a=fun(10.0);


printf("%d\n", a);


return 0;


}


int fun( char *arg1, int *arg2 )


{


return *arg2;


}


O dziwo takie coś kompiluje się bez zająknięcia (do momentu jak nie damy aby brak prototypów rzucał warnami. Rezultaty działania proszę sobie na własną odpowiedzialność sprawdzić.

zakończenie

Krótko dlaczego tak jest - deklaracja sprawia, że cała rodzina funkcji, o nazwie fun będzie dla nas dostępna. Korzystamy sobie z niej więc do woli w mainie. Dopiero potem podając definicję podajemy prototyp - niby nie pasuje do tego co w mainie zostało wywołane, no ale cóż, już troszkę za późno. Drugi argument, zwracany przez funkcję nigdy nie został przekazany, więc pojawią się śmieci.

#programowanie #cpp #c99
  • 20
@badasq: Jeśli uważasz, że ten kod jest zły to znaczy, że nie znasz C. W C puste nawiasy oznaczają to samo co

(...)
, czyli dowolną liczbę argumentów dowolnego typu. Jeśli funkcja ma nieprzyjmować argumentów to należy użyć

(void)
. Jeśli uważasz C++ za takie niesamowicie dobrze zaprojektowane, to powiedz mi co znaczy kod:

int main() {

MyClass my_var();

}

Jestem zaiste ciekaw, czy potrafisz odpowiedzieć dobrze.
@badasq: @Hauleth: MyClass to zapewne klasa zdefiniowana "poza ekranem", a ten kod wywołuje bezparametrowy konstruktor tej klasy, i zaraz potem jej destruktor (o ile nie ma makr zdefiniowanych poza ekranem).

EDIT: no, żeby być dokładnym to ten konstruktor może być też z parametrami z wartościami domyślnymi.
@Hauleth: no to przecież tak samo jest w c, więc nie rozumiem dlaczego to ma pokazać "gorszość" c++ względem c...

Akurat dla mnie, jak to nazwałeś "kontekstowość" nie jest wadą. Kompilator czy normalne ide pozwalają tutaj wszystko ogarniać bez żadnych problemów czy wątpliwości.

ps. gdybyś podał kontekst to bez problemu bym na to odpowiedział, nawet pod tym tagiem był temat poruszany, więc słabo...
@badasq: pokaż mi dobre IDE do C++. Takie z parsowaniem działającym dla skomplikowanych projektów z templatami, makrami, bibliotekami itp. Próbowałem CDT, KDevelop, QDeveloper, Visuala, zawsze się motają w końcu.

C++ nawet nie ma sensownego systemu modułów tylko hacki na inkludach i pierdyliard różnych systemów budowania. Jak używasz w projekcie 10 bibliotek z 4 różnymi systemami budowania, to konfiguracja IDE tak, żeby sparsował źródła poprawnie, i dało się ctrl+kliknięciem chodzić po kodzie
@Hauleth: nie ma tutaj nic niezdefiniowanego :)

wywołujesz funkcję foo zadeklarowaną 3 linijki wyżej i zdefiniowaną pod mainem.

Ja nie znam C - do czego się przyznaję, ale ty najwidoczniej nie znasz c++ ;)

edyta: wejdź w link podany przez Krzaq to dowiesz się dlaczego (standard)

edyta kolejna: link który podałeś nie działa.