• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przekazywanie tablicy do funkcji (wskaźniki)

Object Storage Arubacloud
0 głosów
1,998 wizyt
pytanie zadane 22 sierpnia 2016 w C i C++ przez Paściak Arek Nowicjusz (120 p.)

Drodzy koledzy, chcę napisać prosty program, który przekazuje dynamiczną tablicę do funkcji, która każdą jej wartość powiększy o 50 korzystając ze wskaźników. Kod nawet się kompiluje, ale po wywołaniu funkcji, moja tablica wypełniona jest losowymi wartościami. Gdzie popełniam błędy?

int tab (int ile, int *tab[]){
	for (int i = 0; i < ile; i++){
		*tab+=50;
		tab++;
		}
}
int main(int argc, char** argv) {
int ile;
int *tablica;
tablica = new int [ile];


cout<<"Ile elementow tablicy?: ";
cin>>ile;
cout<<"El tablicy:\n";
for (int i = 0; i < ile; i++){
	*tablica=i;
	cout<<*tablica<<endl;
	tablica++;
}
tab(ile, &tablica);
for (int i = 0; i < ile; i++){
	cout<<tablica[i]<<endl;
}

delete [] tablica;
return 0;
}

 

komentarz 22 sierpnia 2016 przez Paściak Arek Nowicjusz (120 p.)
Napisałem kod od początku. Teraz wszystko działa jak należy.
Czy może mi ktoś wyjaśnić co działo się w tym pierwszym kodzie, kiedy w funkcji zwiększającej elementy tablicy zadeklarowałem argument int *tab[] oraz w momencie wywoływania jej w funkcji main(&tablica)?

​

​void zwiekszenie(int x, int *tab){
	for (int i = 0; i < x; i++){
		*tab+=50;
		cout<<*tab<<endl;
		tab++;
	}
}
int main(int argc, char** argv) {
int ile;
int *tablica;
tablica = new int [ile];


cout<<"Ile elementow tablicy?: ";
cin>>ile;
cout<<"El tablicy:\n";
for (int i = 0; i < ile; i++){
	tablica[i]=i;
	cout<<tablica[i]<<endl;
}

cout<<"Po zwiekszeniu:\n";
zwiekszenie(ile, tablica);

delete [] tablica;
	return 0;
}

 

komentarz 22 sierpnia 2016 przez Kasztan Dyskutant (8,080 p.)
Polecam książkę "Szkoła programowania" Stephen Prata
komentarz 22 sierpnia 2016 przez draghan VIP (106,230 p.)

Czy może mi ktoś wyjaśnić co działo się w tym pierwszym kodzie, kiedy w funkcji zwiększającej elementy tablicy zadeklarowałem argument int *tab[] oraz w momencie wywoływania jej w funkcji main(&tablica)?

Narobiłeś bałaganu, po prostu. Deklaracja funkcji postaci:

int f(int *arg[]);

opisuje funkcję, która zwraca liczbę całkowitą ze znakiem, a pobiera jako parametr tablicę wskaźników do int - innymi słowy: wskaźnik na wskaźnik. Zapomnij na razie braku zwracania wartości z funkcji, bo to jest pikuś przy Twoim ominięciu kontroli typów. :)

Chwilę po rozpoczęciu ciała rzeczonej funkcji, piszesz coś takiego:

*tab+=50;

Przypominam, że tab jest wskaźnikiem na wskaźnik - to bardzo ważne w tym wypadku. Dokonujesz dereferencji i dostajesz się "wskaźnikowy poziom niżej" - ale wciąż masz tam do czynienia z kolejnym wskaźnikiem. I dodajesz do niego pięćdziesiąt "pozycji" (w bajtach: 50 * sizeof(int*), bo tablica zawiera elementy int*).

Następnie inkrementujesz tab i znów wykonujesz powyższe. 

Nie ma to większego sensu, biorąc pod uwagę że właściwym typem danych, na którym operujesz, jest int*, nie int**.  Głównie rozchodzi się o nieprawidłowe operowanie na adresach pamięci.

Mnóstwo w Twoim kodzie jest przesuwania wskaźników, niekoniecznie zgodnie z rozsądkiem. Lepiej stosować indeksowanie - jest nieco bezpieczniejsze, bo nie przesuwa oryginalnego adresu.

3 odpowiedzi

+1 głos
odpowiedź 22 sierpnia 2016 przez criss Mędrzec (172,590 p.)
edycja 22 sierpnia 2016 przez criss

int *tab[] - to jest wskaźnik na wskaźnik (albo tablica 2d). Zdecyduj się jak chcesz oznaczyć tablice. Albo int *tab, albo int tab[].

Kompiluje się bo przesyłasz do funkcji wskaźnik na wskaźnik (&tablica), ale dlaczego - nie mam pojęcia.

Poza tym: wskaźnik tablica nie wskazuje już nawet na twoją tablice (na pierwszy element) bo:

 

for (int i = 0; i < ile; i++){

    *tablica=i;

    cout<<*tablica<<endl;

    tablica++;

}

Dlaczego nie używasz tu operatora[] tak jak w następnej pętli.. Ogólnie - napisz od nowa, bo za dużo błędów tu jest.

komentarz 22 sierpnia 2016 przez Kasztan Dyskutant (8,080 p.)
dokładnie albo jedno albo drugie oba zapisy znaczą to samo

 

swoją drogą straszny ten kod
0 głosów
odpowiedź 22 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)
Operator [] przy deklaracji argumentu stosuje się przy tablicach statycznych. Sądzę, że to jest powodem błędu. Zastosuj wskaźnik na wskaźnik.
komentarz 22 sierpnia 2016 przez draghan VIP (106,230 p.)
W jakim celu? Jakiego typu jest tablica, którą autor definiuje? :)
komentarz 22 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)

Nie rozumiem pytania.

Ja w ogóle przesyłałbym tylko wskaźnik na int, ponieważ stworzenie kopii wskaźnika kosztuje mniej, niż tworzenie wskaźnika na wskaźnik potrzebnego do korzystania z oryginalnego obiektu.

Również nie dziwi mnie fakt, że program wypisuje jakieś śmieci - przecież adres wskaźnika uniemożliwia używanie arytmetyki wskaźników, gdyż nie ma on wiele wspólnego z tablicą (po prostu kolejny pojemnik na dane).

komentarz 22 sierpnia 2016 przez draghan VIP (106,230 p.)

Pytałem, dlaczego chcesz tworzyć wskaźnik na wskaźnik, skoro potrzeba jedynie "jednowymiarowego" wskaźnika do tej prostej operacji.

Również nie dziwi mnie fakt, że program wypisuje jakieś śmieci - przecież adres wskaźnika uniemożliwia używanie arytmetyki wskaźników, gdyż nie ma on wiele wspólnego z tablicą (po prostu kolejny pojemnik na dane).

Tego nie za bardzo rozumiem, jeśli mam być szczery. :/

komentarz 22 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)
Chodzi o to, że użycie wskaźnika na wskaźnik w celu dostania się do elementu tablicy za pomocą arytmetyki wskaźników (czytaj operatora []) jest niemożliwe, gdyż ten adres nie ma nic wspólnego z tablicą.

Tak w ogóle niepotrzebnie to wcześniej napisałem, bo nie przeanalizowałem dokładnie kodu. Jak człowiek zwiększa o 50 wartość wskaźnika, a nie samej zmiennej, to nie mamy o czym gadać.
komentarz 22 sierpnia 2016 przez draghan VIP (106,230 p.)

Wybacz, nadal po Twoim tłumaczeniu mam problem ze zrozumieniem. :)

Chodzi Ci o to, że mając jednowymiarową tablicę i definiując wskaźnik na wskaźnik, który pokazuje na adres tablicy, nie dostanę się do elementów tablicy przez ten wskaźnik?

Tak w ogóle niepotrzebnie to wcześniej napisałem, bo nie przeanalizowałem dokładnie kodu. Jak człowiek zwiększa o 50 wartość wskaźnika, a nie samej zmiennej, to nie mamy o czym gadać.

Zgoda. :)

1
komentarz 22 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)

Dobra, w telegraficznym skrócie - chodzi o zapis tab++.

1
komentarz 22 sierpnia 2016 przez draghan VIP (106,230 p.)
O, widzisz - potwierdza się powiedzenie "talk is cheap, show me the code". Wszystko jasne. :)
komentarz 22 sierpnia 2016 przez Paściak Arek Nowicjusz (120 p.)
Patrycjerz, w jakim celu stosuje się wskaźnik na wskaźnik?

Linijka "*tab+=50;" przecież nie zwiększa wartości wskaźnika a samą jego wartość. By zwiększyć wartość (czyli adres) tej "szufladki trzeba by napisać "tab+=50;".
Mogę się mylić, bo dopiero raczkuję w programowaniu, ale czy nie mam racji?
komentarz 22 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)

int* tab[] to praktycznie to samo, co int** tab. Jeśli używasz zapisu *tab += 50, to zwiększasz wartość wskaźnika, nie zmiennej, gdyż przesłałeś adres wskaźnika do funkcji.

0 głosów
odpowiedź 22 sierpnia 2016 przez manjaro Nałogowiec (37,390 p.)
edycja 22 sierpnia 2016 przez manjaro

Wiem nie powinno się dawać gotowych rozwiązań. Ale to tylko przykład i warto zrozumieć w jaki sposób to realizować.

Ja bym to napisał tak. 

​#include <iostream>

using namespace std;

void tab (int iles, int *tablica){
    for (int i = 0; i < iles; i++){
        *(tablica+i)+=50;
        }
}

int main() {
cout<<"Ile elementow tablicy?: ";
int ile, *tablica;
cin>>ile;
tablica = new int [ile]();


cout<<"Elementy tablicy:\n";

for (int i=0; i<ile; i++){
    *(tablica+i)=i;
    cout<<tablica[i]<<endl;
}

cout << "\n";
tab(ile, tablica);

for (int i = 0; i < ile; i++){
    cout<<tablica[i]<<endl;
}

delete [] tablica;
return 0;
}

Podobne pytania

0 głosów
3 odpowiedzi 1,028 wizyt
pytanie zadane 14 kwietnia 2016 w C i C++ przez TheFeniks Gaduła (4,690 p.)
0 głosów
1 odpowiedź 455 wizyt
pytanie zadane 3 kwietnia 2019 w C i C++ przez mr.wo!tman Nowicjusz (120 p.)
0 głosów
0 odpowiedzi 877 wizyt
pytanie zadane 30 września 2018 w C i C++ przez Uwegi Początkujący (430 p.)

92,579 zapytań

141,432 odpowiedzi

319,663 komentarzy

61,964 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...