Wskaźniki i dziwna sytuacja..

0

Witam mam nietypowy proble z tamim programikiem. Gdy w programie nie ma zadnego printfa( albo innej instrukcji, nie sprawdzalem) nie zapisuje do zmiennych wartosci.

int main()
{
int Zm1=0, Zm2=0, Zm3=0, Zm4=0, Zm5=0;
int *pZm;

pZm=&Zm1;

do
{
		scanf("%d", pZm);
		pZm--;

} while(Zm5==0);
		
return 0;	
}

Gdy dodam np printfa w petli po scanfie albo po petli to juz jest wszytko okej a w przeciwnym wypadku petla sie nie konczy.

int main()
{
int Zm1=0, Zm2=0, Zm3=0, Zm4=0, Zm5=0;
int *pZm;

pZm=&Zm1;

do
{
		scanf("%d", pZm);
		pZm--;

} while(Zm5==0);
                printf("Zm1=%d Wskaznik przechowuje:%d adres zmiennej:%d\n", Zm1, pZm, &Zm1); 
		printf("Zm2=%d Wskaznik przechowuje:%d adres zmiennej:%d\n", Zm2, pZm, &Zm2);
		printf("Zm3=%d Wskaznik przechowuje:%d adres zmiennej:%d\n", Zm3, pZm, &Zm3);
		printf("Zm4=%d Wskaznik przechowuje:%d adres zmiennej:%d\n", Zm4, pZm, &Zm4);
		printf("Zm5=%d Wskaznik przechowuje:%d adres zmiennej:%d\n", Zm5, pZm, &Zm5);
		
return 0;	
}
2

Bo oszukujesz kompilator ;) gcc wygenerowało mi coś takiego:

L2:
	movl	%ebx, 4(%esp)
	subl	$4, %ebx
	movl	$LC0, (%esp)
	call	_scanf
	jmp	L2

Czyli kompilator uznał ze skoro nie modyfikujesz zmiennej to pętla jest nieskończona (mamy skok bezwarunkowy, więc nigdy z tej pętli nie wyjdziemy). No bo to co robisz z tym przesuwaniem się wskaźnikiem po stosie to jest dość nieładna operacja.
Co ciekawe w wersji drugiej kompilator wygenerował

L2:
	movl	%ebx, 4(%esp)
	subl	$4, %ebx
	movl	$LC0, (%esp)
	call	_scanf
	movl	28(%esp), %eax
	testl	%eax, %eax
	je	L2

Czyli już nie uznał że pętla jest nieskończona ;] (mamy skok warunkowy)

2

Kompilator zachował się popawnie, to:

do
{
        scanf("%d", pZm);
        pZm--;
 
} while(Zm5==0);

to UB :P (http://en.wikipedia.org/wiki/Undefined_behavior).

Czyli to o napisał Shalom.

Może kompilowanie tego na -O0 'pomoże', ale zasadniczo kompilator może sobie tak ustawiać dane na stosie jak tylko zapragnie. Jeśli chcesz zrozumieć jak działa kompilator, polecam uruchomienie jakiegoś debuggera/disasma, będziesz miał pewniejszą wiedzę niż 'oszukujący' kompilator.

0

A jakbym nie chcial nic robic tylko wczytywac za pomoca wskaznikow jakiej wartosci to jak to zrobic i zeby bylo w petli? :P

1

Tak żeby było zgodnie ze standardem? I dodatkowo prosto? Wczytuj do tablicy ;).

0

Ale mam takie zadanie od pana profesura zeby nadac kolejnym zmiennym wartosci za pomoca wskaznikow i tablicy tez. Nie moge wczytywac do zmienych, musi byc przez wskaznik. Do tablicy to nie ma klopotu ale z tymi pojedynczymi zniennymi jest lipa.

0

Prawdopodobnie nie zrozumiałeś polecenia.

0

Zadanie 3. Zobacz sobie jesli masz ochote.
http://pp2.kis.p.lodz.pl/PP2_lab2.pdf

0

Teraz, bez żadnej wątpliwości - nie zrozumiałeś polecenia.

0

To napisz co i jak?
czy moze takie cos wystarczy?

int main()
{
int Zm1=0, Zm2=0, Zm3=0, Zm4=0, Zm5=0;
int tab[5]={0};
int *pZm=NULL;
int i;

	pZm=&Zm1;
		*pZm=11;
	pZm=&Zm2;
		*pZm=12;
	pZm=&Zm3;
		*pZm=13;
	pZm=&Zm4;
		*pZm=14;
	pZm=&Zm5;
		*pZm=15;

	printf("%d %d %d %d %d\n", Zm1, Zm2, Zm3, Zm4, Zm5);
	pZm=tab;
	for (i=0;i<=5;i++)
	{
		*(pZm+i)=(110+i);
		printf("%d\n", tab[i]);;
	}
		
	return 0;	
}

Co masz na mysli piszac ze nie zrozumialem polecenia? Czy ten osatni program jest juz okej?

0

Prawie, bo nie umiesz zapisać for'a:

for(i=0;i<5;++i)
0

Czy wazne jest aby byla preinkrementacja zamiast postinrementacji?

0

Ważne żebyś iterował po istniejących elementach tablicy. Jest dość spora różnica między <5 a <=5...

0

W tym akurat miejscu, jeżeli kompilator ma optymalizacje oraz ta optymalizacja jest włączona to można zostawić postinrementacje - z tym że to bez sensu.

0

Czytalem o roznicach w post i preinkrementacji i moze faktycznie nie ma sensu uzywac i++.

0

Kiedy jest taka potrzeba to ma sens np:

while((count<max)&&(cin>>tb[count++])) {}

1 użytkowników online, w tym zalogowanych: 0, gości: 1