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

Czytanie kodu

Object Storage Arubacloud
+1 głos
468 wizyt
pytanie zadane 8 czerwca 2018 w C i C++ przez must Bywalec (2,980 p.)

Cześć, potrzebuje przestudiować ten kod i wyświetlić to co bezie w konsoli.

Oczywiście kod wklepałem do programu i widze co się wyswietla, ale musze napisac krok po kroku co się dzieje.

Chciałbym byście sprawdzili czy dobrze główkuję, bo w pewnym momencie nie wiem co dalej zrobić.

Linia 8: Wiadomo tworzymy statyczną tablicę dwuwymiarową pod a[0] jest KASIA, pod a[1] jest Ola Ula

Linia 9: Tak samo jak u góry

Linia 11: Tworzymy wskaźnik p na char;

Linia 12; Wyświetli nam się napis KASIA i przejdziemy do kolejnej linii.

Linia 13: Wypisze się, "Marek i ?"  Ale nie rozumiem czemu przesyłamy 

Linia 14: Pod 10 znak a[1] (czyli Ola Ula) doda się &

Linia 15: Łączymy a[1] czyli Ola Ula & z p, czyli Marek i ?. Finalnie: Ola Ula & Marek i ?

Linia 16: Wypisze to co u góry.

Linia 17: Tutaj się wypisze:

x[0]=11 

x[2]=13

I czego nie rozumiem:

4 <<<< nie czaje skąd to się bierze, czy to jest to: b[1] czy jak

Linia: 21

Wypisuje się:

1 2 3

22 12 26

Czyli nie czaje 35 linijki:

#include <stdio.h>
#include <string.h>
char *zm(char *);
int ft(int *);
int main()
{
    int i=0,j;
    static char a[2][30]= {"KASIA","Ola Ula " };
    static int b[2][3]= { {1, 2, 3},{11,12,13}}; //!!! 2 wiersze i 3 kolumny

    char *p;
    printf("%s\n",a[0]);
    printf("%s\n",p=zm(&a[1][0]));
    *(a[1]+10)='&'; //!!! znak nr 10 wiersza nr 1
    strcat( a[1],p);
    printf("%s\n",a[1]);
    printf("%u\n",ft(b[1]));
    for(i=0; i<2; i++)
    {
        for(j=0; j<3; j++)
            printf("%3d ",b[i][j]);
        printf("\n");
    }
    return 0;
}
int ft(int *x)
{
    int i;
    for (i=-1; i<2; i++)
    {
        i=i+1;
        printf("x[%d]=%d \n",i,x[i]);
        x[i] = 2*x[i];
    }
    return 0xFD & (i<<1);
}
char *zm(char *x)
{
    static char t[2][20]= {"Andrzej oraz Ola", "Marek i x " };
    *(&t[1][0]+8)='?'; // znak nr 8 wiersza nr 1
    *(x+4)='+'; // znak nr 4 tablicy a w funkcji main
    return t[1];
}

Czy przez to, że wszystko jest przekazywane przez wskaznik to zmiany faktycznie nastepuja w wywoalniu funkcji?

W Javie o ile sie nie myle, to wszystko przekazywane jest jako kopia i nie zmienia to oryginalnych wartości zmiennych,a tutaj faktycznie się zmieniają.

1
komentarz 8 czerwca 2018 przez RafalS VIP (122,820 p.)
W Javie wszystkie typt proste sa przekazywane przez wartosc czyli przez kopie, ale kazdy typ referencyjny przez referencje przez co mozesz modyfikować oryginal.
komentarz 8 czerwca 2018 przez must Bywalec (2,980 p.)
Tak właśnie. W takim razie w C kiedy byłoby przekazanie jako kopia? Gdybym po prostu przesłał zmienną jako argument a nie jako wskaźnik?
1
komentarz 8 czerwca 2018 przez RafalS VIP (122,820 p.)
Zawsze jest kopia. Przez wskaznik jest kopia wskaznika czyli masz adres pamieci gdzie siedzi zmienna wiec mozesz sie do niej dobrac, ale do funkcni dalej przekazywana jest kopia.
komentarz 8 czerwca 2018 przez must Bywalec (2,980 p.)
Czyli to wszystko wina wskaźnika :)
1
komentarz 8 czerwca 2018 przez RafalS VIP (122,820 p.)

@must, zaraz sie dobiore do lapka to Ci to rozpisze

komentarz 8 czerwca 2018 przez must Bywalec (2,980 p.)
dzieki bardzo ;)

2 odpowiedzi

+1 głos
odpowiedź 9 czerwca 2018 przez RafalS VIP (122,820 p.)
wybrane 9 czerwca 2018 przez must
 
Najlepsza
#include <stdio.h>
#include <string.h>
char *zm(char *);
int ft(int *);
int main()
{
	int i = 0, j;
	//statyczny oznacza, ze tablica będzie globalna - widoczna wszedzie
	static char a[2][30] = { "KASIA","Ola Ula " };
	static int b[2][3] = { { 1, 2, 3 },{ 11,12,13 } }; //!!! 2 wiersze i 3 kolumny

	char *p;
	//wypisanie %s dziala, mimo, ze tablica jest na 30 znakow
	//bo %s wypisuje do NULLA, a
	//"KASIA" to const char* {'K','A','S','I','A','\0'}
	printf("%s\n", a[0]);
	//przesylamy adres pierwszego znaku w drugim wierszu
	//pewnie wiesz ze tablica jest wskaznikiem do jej pierwszego elementu
	//nie calkowicie, ale tak to zadziała gdy zrobimy do niej wskaznik
	//&a[1][0] jest zatem rownowazne z a[1]
	//do wszystkiego oczywiscie pasuje typ char *
	//bo mamy wskaznik na char
	//wyrazenie nazwaZmiennej = cos zwraca cos, wiec sie wypisuje
	printf("%s\n", p = zm(&a[1][0]));
	//rownowazne z a[1][10], nigdzie tego nie widzimy bo wypisujemy
	//przy pomocy %s, które wypisuje do nulla - '\0'
	//czyli dla a[1] do 7 znaku
	*(a[1] + 10) = '&'; //!!! znak nr 10 wiersza nr 1
	//funkcja biblioteczna, dopisuje elementy tablicy drugiej do konca pierwszej
	//u nas p wskazuje na drugi wiresz tablicy a, tylko troche
	//zmodyfikowanej w funkcji
	strcat(a[1], p);
	//wypisanie pierwszego wiersza a
	printf("%s\n", a[1]);
	//wypisanie zwrocnej wartosci
	//do funkcji wysylamy drugi wiersz tablicy b
	printf("%u\n", ft(b[1]));
	for (i = 0; i<2; i++)
	{
		//wypisuje tablice, w drugim wierszu co drugi element
		//jest pomnozony przez 2 przez funkcje ft
		for (j = 0; j<3; j++)
			printf("%3d ", b[i][j]);
		printf("\n");
	}
	return 0;
}
int ft(int *x)
{
	int i;
	//zadnej magii chyba
	//mnozy x2 co drugi element tablicy x
	for (i = -1; i<2; i++)
	{
		i = i + 1;
		printf("x[%d]=%d \n", i, x[i]);
		x[i] = 2 * x[i];
	}
	//to jest niezle
	//trzeba sobie rozpisac te wartosci binarnie
	// F to 1111; D to 1101
	// i w tym miejscu ma wartosc 3 czyli binarnie 11
	// przesuwamy binarnie i o 1 w lewo co daje 110
	// i robimy binarne and (i) na tych wartosciach czyli:
	//  11111101
	// &00000110
	// =00000100
	//co rowna sie 4 :D
	return 0xFD & (i << 1);
}
char *zm(char *x)
{
	static char t[2][20] = { "Andrzej oraz Ola", "Marek i x " };
	//rownowazne z t[1][8], bo bierzemy najpierw element [1][0]
	//potem jego adres czyli t[1] dodajemy do niego 8 i gwiazdkujemy
	*(&t[1][0] + 8) = '?'; // znak nr 8 wiersza nr 1
	//rownowazne z x[4], bo przesuwamy wskaznik do pierwszego elementu o 4 i
    //wyciagamy wartosc pod tym wskaznikiem
	*(x + 4) = '+'; // znak nr 4 tablicy a w funkcji main
	return t[1];
}

Możliwe, że momentami troszke przesadziłem :D Powodzenia.

Wszelkie argumenty do funkcji w C są przesyłane przez wartość czyli przez kopię. Jednak gdy wyślesz gdzieś wskaźnik do czegoś to będziesz mógł zmodyfikować wartość która kryję się pod tym wskaznikiem. Możesz dla uproszczenia pomyśleć o wskaźniku jako o zwykłym incie, który trzyma adres w pamięci danej zmiennej. Powiedzmy, że tworzymy zmienna int a = oznacza to ze program alokuje gdzies ta zmienna w pamieci powiedzmy ze pod adresem 13, ustawiamy jej wartosc na 0 = wstawiamy 0 w blok pamieci pod adresem 13.

Teraz co się stanie gdy zrobisz tak void fun(int x); a potem wywołasz funkcje z naszą zmienną a. 
Oznacza to, że wartość bloku pamieci o adresie 13, bo tam siedzi nasz int zostanie ustawiona do nowej zmiennej x, która została stworzona czyli została wsadzona gdzieś w pamięci np pod adres 20. Teraz jeśli w funkcji przypiszesz coś do zmiennej x to wpisujesz do adresu bloku o adresie 20. Zero połączenia z naszą zmienną a z maina.

To było proste, teraz jak to działa ze wskaźnikami. Jeśli natomiast zrobisz taką funkcję void fun(int*x) i wyślesz do niej &a to zostanie zaalokowana zmienna wskaźnikowa gdzieś w pamięci powiedzmy adres 99 i wartośc pod tym adresem będzie równa adresowi zmiennej a czyli 13. Jeśli teraz zrobisz w funkcji *x = 100 to odwołuje sie do pamieci pod adresem 13 i wpisujesz tam 100. Po wyjsciu z funkcji wskaźnik pod adresem 99 jest oczywiscie niszczony, ale mysle ze juz czaisz jak to działa.

komentarz 9 czerwca 2018 przez must Bywalec (2,980 p.)
O matko! dzięki wielkie, teraz ide spać i od jutra biorę sie za czytanie, Jak nie będę czeogś wiedzieć, będe pisał:)!
komentarz 9 czerwca 2018 przez must Bywalec (2,980 p.)

@RafalS, Czaje wszystko. Ale w takim razie dlaczego jak w deklaracji funkcji jest wskaźnik na tablicę, to nie robimy przykładowo w wywowałniu tej funkcji &tab, tylko piszemy samo tab?

3
komentarz 9 czerwca 2018 przez RafalS VIP (122,820 p.)

Tablica jest poniekąd wskaźnikiem na pierwszy element:

Różnica między wskaźnikiem i tablicą p jest taka, że jak zrobisz sizeof(tab) to poda Ci size calej tablicy a dla p tylko wielkosc wskaznika. Dodatkowo taba nie możesz ruszyć, ani modyfikować:

int tab[3] = {1,2,3};
int *p = tab;
tab++; //blad
p++; //ok, teraz p jest równe &tab[1]
p = tab + 2; //ok, teraz j p jest rowne &tab[2]
p = tab + 10; //czytasz smieci za tablica, czasem sie wywali czasem nie
*p = 100; //piszesz 7 elementów za koncem tablicy, to samo

 

 

0 głosów
odpowiedź 10 czerwca 2018 przez must Bywalec (2,980 p.)

Jeszcze mam jedną czytankę. Dla mnie o niebo trudniejsza od tamtej: 

15 linijka: K będzie miało wartość 8

19 Linijka: Wypisze się "a", pzw = 2 + psiak(Zwierze,0);. I tutaj już nie wiem co się dzieje w tej funkcji i dlaczego wypisuje "arik". Skoro (j&&j<4) ? p[j+1] : p[0]; < to jest prawdą, czyli wywoła się p[j+1] czyli p[1] czyli Pikus.

21 i 22 linijka też nie zrozumiała.

 

Jeżeli chodzi o tę funkcję *psiak to analogicznie do góry 

*(a+j+1)='%';

to jest a[1] czyli powinno być Z%ierze

 


char *psiak(char *a, int j)
{
 
    static char *p[6]= {"Szarik","Pikus","Muszka","nieznany"};
    *(a+j+1)='%';
    return (j&&j<4) ? p[j+1] : p[0];
}
 
int main()
{
    int i;
    static char zw[20]="Zwierze";
    int j=0, k=0, n;
    char *pzw;
    for(;zw[k++];) ;
 
    do
    {
        printf("a %s\n", pzw = 2 + psiak(zw,j));
        n = 0;
        while(*pzw)
            zw[k-1+n++]=*++pzw;
        printf("b %s\n",zw);
    }
    while (++j<2);
    printf("%c---\n",zw[3]);
    system("pause");
}

 

1
komentarz 10 czerwca 2018 przez RafalS VIP (122,820 p.)
(j&&j<4)

dla j == 0 to nie jest prawda. Warunek jest równowazny z (j !=0 && j<4).

while(*pzw)

rownowazne z while (pzw != NULL)

zw[k-1+n++]=*++pzw;

k caly czas rowne 8, wiec masz 7 + n++. Czyli w obiegach petli zw[7+0], zw[7+1], zw[7+2]... a to oznacza, że znaki doklejane są 1 znak za koncem napisu czyli zaczynamy wpisywac od miejsca gdzie byl null.

*++pzw;

najpierw przesuwany jest wskaźnik pzw a potem wyciagana wartość *. Dlatego Tablica zw skończy się NULL'em i będzie można wypisać ją przez %s. Przesuwanie najpierw powoduje też to, że do zw doklejany jest rik (arik bez a).

komentarz 10 czerwca 2018 przez must Bywalec (2,980 p.)

Faktycznie 


(j&&j<4)

nie jest prawdą, więc wykonuje się p[0]

Ale pzw = 2+p[0] czyli + dwie literki od słowa Szarik? wtedy by się zgadzało, że wyświetla się arik.

Ale dalej nie mogą pojąc tego:

while(*pzw)
            zw[k-1+n++]=*++pzw;
        printf("b %s\n",zw);

Dopóki pzw nie będzie NULLEM, to się będzie wykonywało. Pzw u nas to jest "arik". Czyli pętla wykona się 5 razy?

komentarz 10 czerwca 2018 przez must Bywalec (2,980 p.)
Dobra, tę pętlę chyba ogarnąłem.
komentarz 10 czerwca 2018 przez Patrycjerz Mędrzec (192,320 p.)
To forum nie działa na podstawie postów doklejonych do wątków, tutaj jest jedno pytanie i wiele odpowiedzi. Pisanie kolejnego pytania w sekcji odpowiedzi jest niedopuszczalne. Proszę o tym pamiętać na przyszłość. Jeśli masz coś do dodania, zedytuj dotychczasowe pytanie lub stwórz nowe.

Podobne pytania

+2 głosów
1 odpowiedź 396 wizyt
pytanie zadane 2 marca 2022 w Assembler przez Dorian Bajorek Dyskutant (7,920 p.)
0 głosów
0 odpowiedzi 155 wizyt
+3 głosów
1 odpowiedź 168 wizyt
pytanie zadane 21 października 2019 w Inne języki przez JakSky Stary wyjadacz (14,770 p.)

92,551 zapytań

141,393 odpowiedzi

319,522 komentarzy

61,936 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!

...