5wyklad5

background image

Uzupełnienie dot. przekazywania argumentów

#include <stdio.h>

#include <stdlib.h>

struct nowa { int f; char line[20000]; int k; } reprezentant;

int main()

{ void funkcja7( struct nowa x);

reprezentant.k=17; funkcja7(reprezentant);

printf(" reprezentant.k= %d\n",reprezentant.k); exit(0);

} /* koniec funkcji main */

void funkcja7( struct nowa x)

{ printf("\n funkcja7 x.k=%d\n",x.k);

x.k=-18;

printf("\n funkcja7 x.k=%d\n",x.k);

}/* koniec funkcji funkcja7 */

background image

Uzupełnienie dot. przekazywania argumentów

Program wypisze:

funkcja7 x.k=17

funkcja7 x.k=-18

reprezentant.k= 17

Wniosek: w programie wywołującym nie ma zmiany
argumentu

background image

Uzupełnienie dot. przekazywania argumentów

#include <stdio.h>

#include <stdlib.h>

int nowa[10000];

int main()

{ void funkcja6( int a[10000] ); nowa[10]=27;

funkcja6( nowa ); printf("a[10]=
%6d\n",nowa[10]);

exit(0);

} /* koniec funkcji main */

void funkcja6( int a[10000] )

{ printf("\n funkcja6 a[10]=%d\n",a[10]);

a[10]=-18;

printf("\n funkcja6 a[10]=%d\n",a[10]);

}/* koniec funkcji funkcja6 */

background image

Uzupełnienie dot. przekazywania argumentów

Program wypisze:

funkcja6 a[10]=27

funkcja6 a[10]=-18

a[10]= -18

Wniosek: w programie wywołującym jest zmiana argumentu!

background image

Przykład – wskaźnik do struktury

#include <stdio.h>

#include <stdlib.h>

struct alfa { char buf[16*16*16]; /* 4096 */ int k;

};

typedef struct alfa koral; koral array[10];

koral * wskaznik;

int main()

{ wskaznik = array;

printf("%p\n",wskaznik);

wskaznik++;

printf("%p\n",wskaznik);

exit(0);

}/* koniec main */

background image

Przykład – wskaźnik do struktury

Program wypisze:

0x8049640

0x804a644

Wniosek: wskaźnik (jego zawartość) zmodyfikowała się o ilość
bajtów

potrzebnych na jeden element typu, na który może
wskazywać

Uwaga: niech program sam wylicza, jaka ilość bajtów jest
potrzebna !

background image

adres zmiennej

Do pobrania adresu zmiennej używa się
jednoargumentowego operatora & (uwaga &
może mieć także znaczenie
dwuargumentowego operatora bitowego
iloczynu logicznego)

Jednoargumentowy operator * jest
“używany do wskazywania”, tzn. jego
argument jest adresem zmiennej.

background image

adres zmiennej - przyklad

#include <stdio.h>
#include <stdlib.h>
int main()
{
int k;
int n;
int *palec;
palec=&k;
k=10;
n=(*palec)*15;
printf("\n\nk=%5d n=%5d *palec=

%5d\n",k,n,*palec);

exit(0);
} /* koniec funkcji main */
k= 10 n= 150 *palec= 10

background image

Wskaźniki-0

Czy wskaźnik musi mieć typ ?

Czy może istnieć wskaźnik
uniwersalny?

Jeśli tak to:

Czy można się posługiwać tylko
wskaźnikami uniwersalnymi?

background image

Wskaźniki-1

#

include <stdio.h>

int main()

{

float a[10]={0.,1.,2.,3.,4.,5.,6.,7.,8.,9.};

float * f1; /* wskaźnik do float */

int * p1; /* wskaźnik do int */

void * s1; /* wskaźnik uniwersalny */

f1 = &a[3];

p1 = &a[5]; /* kompilator zgłosi zastrzeżenia */

s1 = &a[7];

background image

Wskaźniki-2

p1 = s1; /* kompilator OK */

p1 = (int *) s1; /* kompilator OK */

p1 = (int *) f1; /* kompilator OK */

/* nie ma sensu p1 = & 123L; */

printf("\n %d %p %x\n", *p1,p1,p1);

printf("\n %f\n", *f1);

return (0);

} /* koniec funkcji main */

background image

Wskaźniki-3

1077936128 0xbffffa4c bffffa4c

3.000000

background image

Wskaźniki-4

#

include <stdio.h>

int main()

{ int * p1; /* wskaźnik do int */

void * s1; /* wskaźnik uniwersalny */

p1=NULL;

printf("\n %d \n", *p1);

printf("\n %p \n", p1);

return (0);

} /* koniec funkcji main */

background image

Wskaźniki-5

wynik programu:

Segmentation fault (core dumped)

(nil)

background image

Wskaźniki-6

#include <stdio.h>

int main()

{ int * p1; /* wskaźnik do int */

void * s1; /* wskaźnik uniwersalny */

p1 = (int *) 1;

printf("\n %d \n", *p1);

printf("\n %p \n", p1);

return (0);

} /* koniec funkcji main */

0x1

background image

Wskaźnik-7

#include <stdio.h>

int main()

{ float x;

float * f2; /* wskaźnik do zmiennej typu float */

f2 = & x ; /* !!!! wskaźnik wskazuje na coś
rozsądnego */

*f2 = 23.4;

printf("\n wartość x wynosi %5.2f\n",x);

return (0);

} /* koniec funkcji main */

wynik : 23.40

background image

Wskaźniki-8

(

wskaźniki jako argument funkcji call.c

str. 213)

#include <stdio.h>

void inc_count(int *count_ptr)

{ ++(*count_ptr); /* po co nawiasy
zwykłe ? */

} /* koniec funkcji inc_count */

int main ( )

{ int count=0; /* licznik pętli */

while(count<10) inc_count(&count);

printf("\n count=%d\n",count);

}/* koniec funkcji main */

background image

Wskaźniki-9

(wskaźniki a macierze)

float as[10]; /* każdy element ma długość
4 bajtów */

float * p3;

p3 = &as[0]; /* lub */ p3=as;

*p3=7; as[0]=7;

*(p3+1)=8; as[1]=8;

background image

Wskaźniki-10

(wskaźniki a macierze)

float as[10]; /* każdy element ma długość
4 bajtów */

float * p3;

p3=as;

p3+=4; /* p3 = p3 +4 */

*p3=9; /* as[4]=9; */

/* dodawanie liczby całkowitej do wskaźnika skaluje
się automatycznie */

background image

Wskaźniki-11

(wskaźniki a macierze)

float as[10]; /* każdy element ma długość
4 bajtów */

float * p3;

*(as) = 7.3 ; /* as[0]=7.3; */

*(as+5)=-4.5; /* as[5]=-4.5; */

/* dodawanie liczby całkowitej do wskaźnika skaluje
się automatycznie */

background image

Wskaźniki-12

#include <stdio.h>

int main ( )

{ float x;

void * p2;

float * p4;

x=14;

p2=&x;

p4=&x;

/* printf("\n %f\n",*p2); !!?? błędnie! */

printf("\n %f\n",*(float *)p2);

printf("\n %f\n",*p4);

}/* koniec funkcji main */

background image

Wskaźniki-13

int main()

char bufa[100]=”Uniwersytet”;

char bufb[120];

........

copy_string(bufb,bufa);

copy_string(&bufb[0],&bufa[0]);

.....

/* koniec funkcji main */

background image

Wskaźniki-14

(str. 220 S. Oualline)

void copy_string (char *p, char *q)

{

while ( *p++ = *q++ )

} /* koniec funkcji copy_string */

/* while( *(p++) = *(q++) )
czytelniejsze! */

background image

Wskaźniki

(wskaźnik do funkcji)

#include <stdio.h>

#include <stdlib.h>

int f1(float);

int f2(float);

void zz ( int(*aa)(float), float t );

int (*f)(float); /* f jest wskaźnikiem do
funkcji ! */

int main( )

{ int n; scanf("%d",&n);

background image

Wskaźniki

(wskaźnik do funkcji)

if(n==1)

{ f=f1; zz(f, (float)n ); }

else

if(n==2)

{ f=f2; zz(f, (float)n ); }

} /* koniec funkcji main */

background image

Wskaźniki

(wskaźnik do funkcji)

int f1(float x)

{ printf("\n wewnatrz f1 x=%f\n",x);

} /* koniec funkcji f1 */

int f2(float x)

{ printf("\n wewnatrz f2 x=%f\n",x);

} /* koniec funkcji f2 */

void zz ( int(*aa)(float), float t )

{ (*aa)(t); }

background image

Wskaźniki

(wskaźnik do funkcji)

Nazwa funkcji jest jednocześnie adresem jej
początku – czyli adresem miejsca w pamięci,
gdzie zaczyna się kod odpowiadający
instrukcjom tej funkcji.

(czyli jest podobnie jak w przypadku tablic!)

background image

Wskaźnik powinien na coś wskazywać

(choćby na NULL)

float * f4 = NULL;

/* trzeba uważać by obiekt wskazywany
nie zniknął !!

*/

background image

pointer.c

#include <stdio.h>

#include <stdlib.h>

/* prototyp */

char *dec_bin (unsigned long a);

int main ()

{

char *bin_p;

bin_p = (dec_bin (119L)); /* 119 to dziesietnie znak w */

printf ("\nTeraz w main: %p\n", bin_p);

printf (" Czyli:%c\n\n", *(bin_p));

exit(0);

} /* koniec funkcji main */

char * dec_bin (unsigned long dec)

{

char *wsk;

char litera_b;

litera_b=dec;

printf ("\n wewnatrz funkcji: dec=%ld\n", dec);

wsk = &litera_b;

printf ("\nwewnatrz funkcji: %p\n", wsk);

printf (" Czyli:%c\n\n", *wsk);

return (wsk);

} /* koniec funkcji dec_bin */

background image

malloc (dynamiczna alokacja pamięci)

#include <stdio.h>

#include <stdlib.h>

struct st

{ int pole1;

int pole2;

float pole3;

double buf[100000];

} z1, *p1, *p2;

main()

{

p1= &z1;

p1->pole1=11.;

p1->pole2=13.;

p1->pole3=15.;

printf("\n");

printf(" pole1 %5d pole2 %5d pole3 %11.3f\n",z1.pole1,z1.pole2,z1.pole3);

printf(" sizeof...%d \n\n",sizeof(z1) );

while(1)

{

p2=malloc(sizeof(z1));

if( p2==NULL)

{ printf("\n .....zabraklo pamieci..."); break;

}

(*p2).pole1=21;

(*p2).pole2=22;

(*p2).pole3=23;

/* free(p2);*/

}

} /* koniec main*/

background image

malloc

void * malloc (size_t size)

funkcja ta zwraca wskaźnik do nowo

zaalokowanego bloku pamięci o długości w
bajtach size ;

w przypadku niepowodzenia funkcja zwraca

wskaźnik zerowy NULL

uwaga – blok pamięci pozostaje

niezainicjalizowany (tzn. jego zawartość
jest niezdefiniowana)

background image

free

void free (void *ptr)

funkcja ta zwalnia (dealokuje) blok pamięci

który został przydzielony przez malloc,
wskazywany przez ptr

background image

realloc

void * realloc (void *ptr, size_t newsize)
Funkcja ta zmienia wielkość bloku którego adres

jest ptr – nową wielkością jest newsize. Uwaga
– ponieważ przestrzeń za końcem bloku może
być zajęta, realloc może dokonać kopiowania
bloku pamięci do nowego adresu, tam gdzie jest
więcej wolnej pamięci. realloc zwraca adres
bloku; jak widać nie musi to być adres ptr. Jeśli
się nie uda zmienić wielkości bloku pamięci, to
wtedy realloc zwraca wskaźnik zerowy NULL.

Jeśli ptr będzie wskaźnikiem o wartośći NULL, to

realloc zadziała tak jak malloc(newsize) .

background image

Wskaźnik do struktury

struct nowa { float f1;

char line[20000];

int k;

} reprezentant;

struct nowa * pf;

pf = & reprezentant;

(*pf).f1=33.4 ; /* nawiasy są konieczne */

(*pf).k = 17;

pf -> k =34; /* operator wskaźnika
struktury */

background image

Wskaźnik do struktury-2

struct faa *ptr;

ptr = (struct faa *) malloc (sizeof
(struct faa));

if (ptr == 0) abort ();

memset (ptr, 0, sizeof (struct faa));

/* memset służy do inicjalizowania
pamięci */

background image

Wskaźnik do struktury-3

#include <stdio.h>

#include <stdlib.h>

int main()

{

struct nowa { int f;

char line[20000];

int k;

} reprezentant;

struct nowa * pf;

..........

background image

Wskaźnik do struktury-4

..........

pf = malloc(sizeof(struct nowa) );

memset(pf,1, sizeof(struct nowa) );

/* memset(pf,0, sizeof(struct nowa) ); */

printf("\n %d %d %d\n",pf->f, pf->line[10], pf-
>k);

} /* koniec funkcji main */

wynik programu 16843009 1
16843009

background image

calloc

void * calloc (size_t count, size_t eltsize)

funkcja zwraca blok pamięci dostatecznie długi
aby mógł pomieścić count elementów, każdy o
długości eltsize ;

zawartość pamięci jest zerowana ! (tzn.
inicjalizowana zerami)

background image

calloc

void * calloc (size_t count, size_t eltsize)

void * calloc (size_t count, size_t eltsize)

{ size_t size = count * eltsize;

void *value ;

value = malloc (size);

if (value != 0) memset (value, 0, size);

return value;

} /* koniec funkcji calloc */

background image

memset

void * memset (void *block, int c, size_t size)

funkcja kopiuje wartość

c

(jako unsigned char) do

size

pierwszych bajtów, począwszy od adresu

wskazywanego przez wskaźnik

block

(czyli do bloku pamięci wskazywanego przez wskaźnik

block

)

PRZYKŁAD:

struct nowa * pf;

void * wsk;

pf = malloc ( sizeof (struct nowa) );

wsk = memset(pf,1, sizeof(struct nowa) );

printf("\n\n pf, wsk %p %p\n",pf,wsk);

background image

memset

void * memset (void *block, int c, size_t size)

W przypadku powodzenia memset() zwraca
wskaźnik równy wskaźnikowi block

background image

memset

void * memset (void *block, int c, size_t size)

memset najczęściej używa się w stosunku
do pamięci dynamicznie przydzielonej
przez malloc (czy calloc), ale można jej
użyć także do np. ”wyzerowania” większej
struktury danych (przykład poniżej)

background image

memset

void * memset (void *block, int c, size_t size)

/* przyklad inicjalizowania pamieci

przygotowanej dla macierzy structur */

#include <stdio.h>

#include <stdlib.h>

struct nowa { int f;

char line[992];

int k; /* alfa[] zdefiniowana
statycznie*/

} alfa[100]; /*

kontynuacja na następnej stronie

*/

background image

memset

void * memset (void *block, int c, size_t size)

int main()

{ alfa[10].k= -223;

printf("%d\n",alfa[10].k);

memset(alfa,0,sizeof(alfa));

printf("%d %d\n",alfa[10].k,
sizeof(alfa));

exit(0);

}/* koniec funkcji main*/

/* wydruk -223

0 100000 */

background image

memcpy

Function: void * memcpy (void *to, const void
*from, size_t size)

The memcpy function copies size bytes from
the object beginning at from into the object
beginning at to. The behavior of this function
is undefined if the two arrays to and from
overlap; use memmove instead if overlapping
is possible.

The value returned by memcpy is the value of
to.

Here is an example of how you might use
memcpy to copy the contents of an array ”of
struct foo”:

struct foo *oldarray, *newarray; int
arraysize; ... memcpy (new, old, arraysize *
sizeof (struct foo));

background image

mempcpy

Funkcja: void * mempcpy (void * to, void *
from, size_t size
)

mempcpy jest bardzo podobna do funkcji
memcpy. Kopiuje size bajtów z miejsca
wskazywanego przez from do miejsca
wskazywanego przez to. Jednakże w
przypadku sukcesu zwraca wskaźnik do bajtu
następującego po ostatnim zapisanym bajcie,
to znaczy zwraca

( (void *) ( (char *) to + size) )

background image

memmove

Function: void * memmove (void *to, const
void *from, size_t size)

memmove copies the size bytes at from into
the size bytes at to, even if those two blocks
of space overlap. In the case of overlap,
memmove is careful to copy the original
values of the bytes in the block at from,
including those bytes which also belong to
the block at to.

background image

Jak czytać skomplikowane deklaracje?

(”Symfonia C++” J.Grębosz, 8.17.1)

.

void zz ( int (*aa) (float), float t );

/* co to jest za obiekt ? */

background image

Jak czytać skomplikowane deklaracje?

(”Symfonia C++” J.Grębosz, 8.17.1)

1. Zaczynamy czytanie od nazwy ”tego co jest
deklarowane”
.

2. Od tej nazwy posuwamy się w prawo. To dlatego, że
tam mogą stać najmocniejsze (jeśli chodzi o priorytet)
operatory: operator wywołania funkcji (....) bądź
operator indeksowania tablicy [] .

3. Jeśli w prawo już nic nie ma, lub natkniemy się na
zamykający nawias – wówczas zaczynamy czytanie w
lewo. Kontynuujemy tak długo, dopóki wszystkiego nie
przeczytamy, lub dopóki nie natkniemy się na
zamykający nawias.

4. Jeśli napotkamy taki nawias, to wychodzimy z
czytaniem na zewnątrz nawiasu. Znowu zaczynamy
czytać w prawo, czyli wracamy do punktu 2.

5. I tak dalej, dopóki nie przeczytamy wszystkiego w
tej deklaracji.

background image

Jak czytać skomplikowane deklaracje?

(”Symfonia C++” J.Grębosz, 8.17.1)

Jak czytamy? Słownik!

* jest wskaźnikiem mogącym pokazywać
na...

(typ1,typ2,...) jest funkcją wywoływaną z
argumentami

typ1, typ2.....

[n] jest n-elementową tablicą......

background image

Jak czytać skomplikowane deklaracje?

(”Symfonia C++” J.Grębosz, 8.17.1)

float * fp;

char * tan (float p, int s);

char (* tas ) (float p, int s);

char * (* tas) (float p, int s);

background image

Jak czytać skomplikowane deklaracje?

(”Symfonia C++” J.Grębosz, 8.17.1)

int ( * (*fw) (int a, char * b) ) [2] ;

background image

Jak czytać skomplikowane deklaracje?

struct kos { float as;

int k[10000];

} kos1;

struct kos kos2;

struct kos *fp1;

struct kos (*fp2);

struct kos (*fp3)(int a, int b);

struct kos * (*fp4[6])( struct kos *a, struct kos
(*b)(void) );

background image

argumenty wiersza poleceń

funkcja main ma dwa argumenty

main(int argc, char * argv [ ] )

(tak sa zwyczajowo nazywane, choć nie są
to nazwy obowiązujące)

background image

argumenty wiersza poleceń

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

int main (int argc, char *argv[] )

/* albo int main( int argc, char **argv) */

{ int n;

for(n=0;n<argc; ++n)

{ printf("\n n=%d param= %s",n,
argv[n]);

printf("\n to samo... n=%d param= %s",n,
*(argv+n) );

printf("\n");

} exit(0);

} /* koniec funkcji main */


Document Outline


Wyszukiwarka

Podobne podstrony:
5wykladow ByFr3di aka$$
SCIAGA 5wykład
5wykladXI2012`GrupysamopomocyAK Nieznany (2)
5wyklad zasady zachowania,energia
5wyklad55
5Wykład 9 29 04 2014 POJĘCIA ZWIAZANE Z KOSZTORYSEM
5Wykladnia prawa
zarzadz 5wyklad

więcej podobnych podstron