C Pointers

[John W. Long]

Programmers have almost made code simplicity an art form while designers are known for spending vast amounts of time doing very tedious and repetitive work to get the effect that they want.

— John W. Long

1. Wskaźniki i adresy:

2. Wskaźniki i argumenty funkcji:

3. Wskaźniki i tablice:

int a[10];
int *pa;
pa = &a[0];

Teraz pa==a oraz a[0]==*pa, a[1]==*(pa+1), a[2]==*(pa+2), itd.

Przykład: obliczanie długości napisu.

Jeśli argumentem funkcji jest nazwa tablicy, to funkcja otrzymuje położenie początkowego elementu tej tablicy. Wewnątrz funkcji argumentowi takiemu odpowiada zmienna lokalna będąca wskaźnikiem na początek tej tablicy.

Uwaga: następujące definicje parametrów funkcji są równoważne:

char s[]
char *s

Dlatego obie deklaracje

int str_len(char s[])
int str_len(char *s)

też równoważne. Zwykle używamy char *s, ponieważ taka definicja wyraźnie sugeruje, że parametr jest wskaźnikiem.

4. Arytmetyka na adresach: obliczanie długości napisu raz jeszcze.

5. Wskaźniki znakowe i funkcje. Jaka jest różnica między definicjami:

char t[] = "XXX"
char *p = "XXX"

(tablica i wskaźnik na stałą napisową).

Przykłady funkcji działających na wskaźnikach: pfun.c.

6. Przydzielanie i zwalnianie pamięci dynamicznej:

typ void *
malloc
calloc
realloc
free

7. Przeczytać stronę manuala dotyczącą funkcji qsort. Wskaźniki do funkcji, tablice wskaźników i wskaźniki do wskaźników.

Tworzenie i rozumienie skomplikowanych deklaracji. Korzystamy z programu cdecl:

explain char (*(*x())[])()
declare x as function returning pointer to array
  of pointer to function returning char

Linki: cdecl, source code.

8. Sortowanie wierszy tekstu podanych na wejściu:

9. Tablice wielowymiarowe:

char tname[][15] = { "błędny miesiąc","styczeń", ... };
char *pname[] = { "błędny miesiąc","styczeń", ... };

Przykład, podaj dzień roku na podstawie miesiąca i dnia i na odwrót.

10. Tablice dynamiczne.

Rozmiar tablicy pobierzemy z linii poleceń:

int n = atoi(argv[1]);

W ANSI 89 korzystamy z malloc:

double *dt;
dt = malloc(n*sizeof(double));
if (dt == NULL)
  fprintf(stderr, "error: Zabrakło pamięci");

dt[2]=2.71; dt[3]=3.14;
free(dt);

A w ANSI 99 nie musimy korzystać z malloc:

int n = atoi(argv[1]);
double dt[n];

dt[2]=2.71; dt[3]=3.14;

Przykład kompilujemy tak:

cc -std=c89 -Wall       tabliced.c
cc -std=c99 -Wall -DC99 tabliced.c

Uwaga: Jeśli nie korzystamy z malloc, to tablica tworzona jest na „stosie” a nie na „stercie”. Oznacza to, że jej rozmiar ograniczony jest do wielkości stosu programu, czyli do kilkunastu megabajtów.