disther utworzono 13 sierpnia 2009 utworzono 13 sierpnia 2009 Witam, interesują mnie dwie sprawy: Po pierwsze sprawa wypisywania zawartości tablic przy pomocy wskaźników. Dwa przykłady poniżej zaczerpnąłem z Symfonii C++ Standard. Za pierwszym razem wypisuję zawartość tablicy posługując się wskaźnikiem i operatorem "*", żeby pokazać to, co zawiera tablica, w drugim przykładzie efekt jest podobny, jednak napisanie "*" jest traktowane jako błąd. Nie rozumiem, dlaczego raz poprawny jest jeden zapis, innym razem drugi - proszę o wyjaśnienie. Pierwszy kod: void funkcja_wsk2(int *wsk, int rozmiar){ cout << "\nWewnatrz funkcji funkcjia_wsk2\n"; for(int i = 0; i < rozmiar; i++) cout << *wsk[i] << "\t";} Drugi kod: #include <iostream>using namespace std;void mnozenie(double*, double*, double*, int);//=====================================================================int main(){ int size = 1000; double *tab_dbl1 = new double[size]; double *tab_dbl2 = new double[size]; double *tab_dbl3 = new double[size]; for(int i = 0; i < size; i++){ tab_dbl1[i] = i/10.0; tab_dbl2[i] = i/20.0; } mnozenie(tab_dbl1, tab_dbl2, tab_dbl3, size); //tutaj nastepuje wypisanie zawartosci tablic <-------------------- for(int i = 0; i < size; i++){ cout << "tab_dbl1[" << i << "] = " << tab_dbl1[i] << "\t" << "tab_dbl2[" << i << "] = " << tab_dbl2[i] << "\t" << "tab_dbl2[" << i << "] = " << tab_dbl3[i] << "\t"; cout << "\n---------------------------------------------------\n"; } delete [] tab_dbl1, tab_dbl2, tab_dbl3; system("pause"); return 0;}//=====================================================================void mnozenie(double *mnoznik1, double *mnoznik2, double *wynik, int t_size){ for(int i = 0; i < t_size; i++){ wynik[i] = mnoznik1[i] * mnoznik2[i]; }} Druga sprawa: w jednym z ćwiczeń należy stworzyć 10-elementową tablicę wskaźników operatorem new. Taki zapis okazał się błędny: #include <iostream>using namespace std;int main(){ char *linijka = new char*[10]; //dlaczego char** ?? system("pause"); return 0;} Dopiero dodanie drugiej gwiazdki przy definicji zmiennej linijka zaowocowało dopuszczeniem kodu do kompilacji: #include <iostream> using namespace std; int main(){ char **linijka = new char*[10]; //dlaczego char** ?? system("pause"); return 0;} Jaka jest różnica między definicją *zmienna, a **zmienna i dlaczego właśnie ta druga jest w tym przypadku poprawna?
tom300 komentarz 13 sierpnia 2009 komentarz 13 sierpnia 2009 Jeżeli chodzi o pierwszą sprawę to u mnie wywala błąd w pierwszym kodzie (u Ciebie podobno nie) a drugi jest poprawny, czyli taki jaki powinien być. Druga sprawa - pytasz dlaczego powinny być dwie gwiazdki a nie jedna. Jest tak dlatego, że w tym kodzie który podałeś tworzysz tablice wskaźników a nie zwykłych elementów typu char. Dwie gwiazdki oznaczają "wskaźnik, który wskazuje na inny wskaźnik". To chyba tyle, mam nadzieję, że zrozumiałeś 1
The ONE komentarz 13 sierpnia 2009 komentarz 13 sierpnia 2009 w Pierwszym kodzie wywal gwiazke w cout'cie na wyjściu się jej nie pisze:) ma być " cout << wsk << "\t"; "
disther komentarz 14 sierpnia 2009 Autor komentarz 14 sierpnia 2009 Faktycznie, w pierwszym kodzie jest błąd - musiałem ją przez przypadek wstawić już po kompilacji, bo teraz też wywalał błąd - bez gwiazdki działa jak należy. Jeśli jednak wsk znajdowałby się poza cout'em, żeby zmienić to, co on wypisuje w cout należałoby użyć zapisu *wsk = ..., tak? Tak, rozumiem już o co chodzi z dwoma gwiazdkami, dzięki. Co do wskaźników to mam jeszcze jedną sprawę - ten kod: #include <iostream>using namespace std;/*************************************************************/int main(){ // .... double zmienna = 0; const double stala = 3.14; double *wsk_do_zmiennej = &zmienna; // const double *wsk_do_stalej = &stala; // const double *wsk2_do_stalej; cout << "Na poczatku, stala = " << stala << endl; wsk2_do_stalej = wsk_do_zmiennej; // // wsk_do_zmiennej = wsk_do_stalej; // błąd // wsk_do_zmiennej = const_cast<double *>(wsk_do_stalej); // *wsk_do_zmiennej = -333; cout << "Potem -----> stala = " << stala << endl; // stały (nieruchomy) wskaźnik do zmiennej // usuwamy stałość stałej, a nadajemy stałość (nieruchomość) wskaźnika double * const st_wsk_do_zmiennej = const_cast<double * const> (wsk_do_stalej); // wsk_do_zmiennej = st_wsk_do_zmiennej; // // ... int * wskint; wskint = // reinterpret_cast<int*>(const_cast<double*>(wsk_do_stalej)); //...} Jest poprawnie kompilowany zarówno przez CodeBlocks 8.02 jak i MS Visual Studio 2008 Express, jednak inaczej działa - w tym pierwszym wartość stałej nie zostaje zmieniona, w drugim zostaje. Jeden z kompilatorów jest nieaktualny/niezgodny ze standardem, czy przyczyna leży gdzie indziej?
The ONE komentarz 14 sierpnia 2009 komentarz 14 sierpnia 2009 NIe wiem czy dobrze rozumiem natomiast żeby ustawić wskaźnik na jakiś obiekt (uzyskać adres obiektu) używa się znaczka "&" tzw operatora przypisania np. &jakisobiekt Istnieje też "->" dla wskaźnika do obiektu np: int zmienna=10; int *wsk; wsk=&zmienna; a co do gwiazki to znalazłem w necie dobry opis wskaźników na stronce http://kondel.ko.funpic.de/?pid=24 moze to Ci troche wyjaśni 1
disther komentarz 14 sierpnia 2009 Autor komentarz 14 sierpnia 2009 Rzeczywiście dobrze opisane, dzięki. Co sądzisz o tym kodzie powyżej? Program powinien wyświetlić stałą, potem zmienić jej wartość, a następnie znów wyświetlić, z tym, że w visualu działa tak jak powinien, a w codeblocks nie zmienia wartości stałej, czyli wyświetla dwa razy tą samą wartość.
tom300 komentarz 14 sierpnia 2009 komentarz 14 sierpnia 2009 Skompilowałem powyższy kod w Visualu i Devie (bo nie mam CodeBlocks'a) i ten sam efekt: w tym pierwszym jest tak jak należy a w tym drugim już nie. Być może tak jak powiedziałeś ten codeblocks jest niezgodny ze standardem.
The ONE komentarz 14 sierpnia 2009 komentarz 14 sierpnia 2009 Rzeczywiście dziwne:)) sprawdze jeszcze ten kod linijka po linijce moze cos uda mi sie wymyślic:)
disther komentarz 14 sierpnia 2009 Autor komentarz 14 sierpnia 2009 Codeblocks i dev bazują, jeśli się nie mylę na kompilatorze mingw (który z kolei wywodzi się z gcc), więc może z gcc/mingw jest coś nie tak, chociaż to się wydaje jakoś mało prawdopodobne.. Swoją drogą, jak już jesteśmy przy kompilatorach - jest jakaś opcja w visual c++ 2008 express edition, pozwalająca kompilować pliki źródłowe bez tworzenia projektu? Projekt jest wygodny do większych programów, ale tworzenie co rusz nowego na kilkulinijkowe programy jest męczące. Poza tym projekt tworzy kilka plików i folderów, przez co potem niewygodnie się to przegląda w eksploratorze
The ONE komentarz 14 sierpnia 2009 komentarz 14 sierpnia 2009 Sprawdziłem kod i nic takiego szczególnego nie znalazłem. Skompilowałem jeszcze w swoim Visual Studio Profesional 2008 i działa poprawnie:) Co do tworzenia małych programików bez robienia projektów to chyba się tak nie da;)
disther komentarz 14 sierpnia 2009 Autor komentarz 14 sierpnia 2009 Wygląda na to, że visual studio jest bardziej dopracowane :> Dzięki za pomoc
Wciąż szukasz rozwiązania problemu? Napisz teraz na forum!
Możesz zadać pytanie bez konieczności rejestracji - wystarczy, że wypełnisz formularz.