Nedideli užrašai apie rodykles C kalboje,
susidedu taip, kaip suprantamiau man. :)
Naudojama 64bit mašina, todėl visi adresų dydžiai 64bit.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10; // int kintamasis pavadinimu a, kuriam priskiriama reikšmė 10
int *p; // rodyklė į int
p = &a; // rodyklei p priskiriamas kintamojo a adresas
printf("%d\n", a); // spausdina kintamąjį a
printf("%p\n", (void*) &a); // spausdina kintamojo a adresą
printf("%p\n", (void*) p); // spausdina adresą, kuriuo rodo p
printf("%d\n\n", *p); // spausdina int vertę adresu kuris nurodytas p
char c = 'E'; // char kintamasis pavadinimu c, kuriam priskiriama reikšmė E
char *p_c; // rodyklė į char
p_c = &c; // rodyklei p priskiriamas kintamojo c adresas
printf("%c\n", c); // spausdina kintamąjį c
printf("%p\n", (void*) &c); // spausdina kintamojo c adresą
printf("%p\n", (void*) p_c); // spausdina adresą, kuriuo rodo p_c
printf("%c\n\n", *p_c); // spausdina char vertę adresu kuris nurodytas p_c
//dydžiai:
printf("%zu\n", sizeof(int)); // int dydis baitais
printf("%zu\n", sizeof a); // kintamojo a dydis baitais
printf("%zu\n", sizeof *p); // kintamojo į kurį rodo p dydis baitais
printf("%zu\n", sizeof(int*)); // rodyklės į int dydis
printf("%zu\n", sizeof &a); // kintamojo a adreso dydis
printf("%zu\n", sizeof p); // rodyklės p dydis
return 0;
}
Failas:
rodykles-1.c
gcc rodykles-1.c -o testineprograma
Rezultatas paleidus:
10
0x7ffcc69563e4
0x7ffcc69563e4
10
E
0x7ffcc69563e3
0x7ffcc69563e3
E
4
4
4
8
8
8
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a;
int *p;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
a = arr[0]; // į a įkeliama pirmo elemento arr masyve reikšmė
printf("%d\n", a); // spausdina kintamąjį a
a = arr[3]; // į a įkeliama ketvirto elemento arr masyve reikšmė
printf("%d\n", a); // spausdina kintamąjį a
p = arr; // rodyklė p rodys adresu į arr masyvo pradžia, tas pats kas į pirmą elementą
printf("%d\n", *p);
p = &arr[0]; // rodyklė p rodys adresu į pirmą elementą arr masyve
printf("%d\n", *p);
p = &arr[3]; // rodyklė p rodys adresu į ketvirtą elementą arr masyve
printf("%d\n\n", *p);
p = arr;
printf("%d ", *p);
p += 1; // (!) adresas čia pastūmiamas per vieną int dydį
printf("%d ", *p);
p += 1;
printf("%d ", *p);
p++; // inkrementas, pakelimas per 1
printf("%d\n\n", *p);
char *p_c;
char arr_c[4] = {'K','A','V','A'};
printf("%c", arr_c[0]);
printf("%c", arr_c[1]);
printf("%c", arr_c[2]);
printf("%c\n\n", arr_c[3]);
p_c = arr_c;
printf("%c", *p_c);
printf("%c", *(p_c+1)); // papildomi skliausteliai reikalingi tam, kad pridėtų prie adreso, o ne prie vertės, kuri randasi adresu p_c
printf("%c", *(p_c+2));
printf("%c\n\n", *(p_c+3));
printf("%c", *p_c);
p_c += 1; // (!) adresas čia pastūmiamas per vieną char dydį
printf("%c", *p_c);
p_c += 1;
printf("%c", *p_c);
p_c += 1;
printf("%c\n\n", *p_c);
return 0;
}
Failas:
rodykles-2.c
gcc rodykles-2.c -o testineprograma
Rezultatas paleidus:
1
4
1
1
4
1 2 3 4
KAVA
KAVA
KAVA
Funkcija, kuri gražina rodyklę
#include <stdio.h>
#include <stdlib.h>
int *TestFnc( int *p, int n )
{
return p + n;
}
int main()
{
int arr[5] = {1,2,3,4,5};
int *p = arr;
printf("%d\n", *p);
p = TestFnc( p, 2 );
printf("%d\n", *p);
return 0;
}
Failas:
rodykles-3.c
gcc rodykles-3.c -o testineprograma
Rezultatas paleidus:
1
3
Rodyklės funkcijos parametruose
Pastaba:
Kas yra funkcijos parametrai ir kas yra funkcijos argumentai ?
Parametras - tai kintamasis kuris nurodomas funkcijos apibrėžime, nurodo kokius duomenis funkcija tikisi gauti.
Argumentas - tai faktinė vertė perduota funkcijai.
Pvz.:
int Fnc( int a, int b )
{
return a + b;
}
...
int n = Fnc(2,5);
...
a ir b yra funkcijos parametrai, 2 ir 5 yra funkcijos argumentai.
#include <stdio.h>
#include <stdlib.h>
void Fnc1( char *p )
{
p++;
printf("%c\n", *p);
}
void Fnc2( char *p )
{
p++;
*p = 'e';
p++;
*p = 'p';
p++;
*p = 'e';
p++;
*p = 'l';
p++;
*p = 'i';
p++;
*p = 'n';
p++;
*p = 'a';
p++;
*p = 'i';
}
void Fnc3( char **p )
{
*p = *p + 1;
}
int main()
{
char arr[10] = {'C','E','P','E','L','I','N','A','I',0};
char *p_a;
p_a = arr;
printf("%c\n", *p_a);
Fnc1(p_a);
printf("%c\n\n", *p_a); // pastebėk, nors funkcijoje buvo pakeistas adresas, čia jis liko toks pat kaip prieš iššaukiant funkciją
for( unsigned int i = 0; i < 9; ++i )
{
printf("%c", arr[i]);
}
printf("\n");
Fnc2(p_a); // naudojntis rodykle, funkcijoje galima pakeisti vertes į ką rodyklė rodo
for( unsigned int i = 0; i < 9; ++i )
{
printf("%c", arr[i]);
}
printf("\n\n");
printf("%c\n", *p_a);
// pakeičiam adresą į kurį rodo rodyklė funkcijoje
Fnc3( &p_a );
printf("%c\n\n", *p_a);
return 0;
}
Failas:
rodykles-4.c
gcc rodykles-4.c -o testineprograma
Rezultatas paleidus:
C
E
C
CEPELINAI
Cepelinai
C
e
Vertės gražinimas per funkcijos parametrą
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void Fnc1( char *p )
{
*p = 'a';
}
bool Fnc2( char **p, unsigned int dydis )
{
*p = malloc( dydis );
if(!*p)
{
return false;
}
return true;
}
int main()
{
char a;
Fnc1( &a );
printf("%c\n\n", a);
char *ptr;
if(!Fnc2( &ptr , 100 ))
{
printf("Klaida: negaliu priskirti atminties bloko.\n");
return 1;
}
free(ptr);
printf("Gerai.\n");
return 0;
}
Failas:
rodykles-5.c
gcc rodykles-5.c -o testineprograma
Rezultatas paleidus:
a
Gerai.
Testuojam su valgrind:
in use at exit: 0 bytes in 0 blocks
total heap usage: 2 allocs, 2 frees, 1,124 bytes allocated
All heap blocks were freed -- no leaks are possible
Rodyklė į funkciją
#include <stdio.h>
#include <stdlib.h>
void Fnc( int a )
{
printf("%d\n", a );
}
int main()
{
//void (*f_p)(int);
//f_p = &Fnc;
void (*f_p)(int) = &Fnc;
(*f_p)(123);
return 0;
}
Failas:
rodykles-6.c
gcc rodykles-6.c -o testineprograma
Rezultatas paleidus:
123
Dvimatis masyvas ir rodyklės
Bandymas dinamiškai priskirti atmintį dvimačiam masyvui, jį inicijalizuoti.
Variantas 1:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **a = {0};
// Tarkim bus 3 antro lygio blokai, kaip kad int a[3][x]
a = malloc( 3 * sizeof *a );
if (!a)
{
printf("Klaida: nagaliu priskirti atminties bloko. (1)\n");
return 1;
}
// priskiriam atminti pirmam int blokui, kurį tarkim sudarys 10 elementų
a[0] = malloc( 10 * sizeof **a );
if (!a[0])
{
printf("Klaida: nagaliu priskirti atminties bloko. (2)\n");
free(a);
return 1;
}
// priskiriam atminti antram int blokui, kurį tarkim sudarys 8 elementai
a[1] = malloc( 8 * sizeof **a );
if (!a[1])
{
printf("Klaida: nagaliu priskirti atminties bloko. (3)\n");
free(a[0]);
free(a);
return 1;
}
// priskiriam atminti trečiam int blokui, kurį tarkim sudarys 4 elementai
a[2] = malloc( 4 * sizeof **a );
if (!a[2])
{
printf("Klaida: nagaliu priskirti atminties bloko. (4)\n");
free(a[0]);
free(a[1]);
free(a);
return 1;
}
// inicijalizuojam pirmą bloką
for ( unsigned int i = 0; i < 10; ++i )
{
a[0][i] = i;
}
// inicijalizuojam antrą bloką
for ( unsigned int i = 0; i < 8; ++i )
{
a[1][i] = i + 10;
}
// inicijalizuojam trečią bloką
for ( unsigned int i = 0; i < 4; ++i )
{
a[2][i] = i + 100;
}
// bandom perskaityti keletą reikšmių
printf("%d\n", a[0][0]);
printf("%d\n", a[0][3]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][7]);
printf("%d\n", a[2][0]);
printf("%d\n", a[2][3]);
// atlaisvinam atminties blokus, 3 nes nutarėm kad tiek bus antro lygio blokų
for ( unsigned int i = 0; i < 3; ++i )
{
free(a[i]);
}
free(a);
return 0;
}
Failas:
dm-rodykles-1.c
gcc dm-rodykles-1.c -o testineprograma
Rezultatas paleidus:
0
3
10
17
100
103
testuojam su valgrind:
in use at exit: 0 bytes in 0 blocks
total heap usage: 5 allocs, 5 frees, 1,136 bytes allocated
All heap blocks were freed -- no leaks are possible
Variantas 2:
Tarkim tiksliai žinom kiek bus antro lygio blokų.
Pabandom priskirti atminitį ir inicijalizuoti funkcijoje,
taip pat naudojam atskirą funkciją atminties atlaisvinimui.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ALB_SKAICIUS 3
int *a[ALB_SKAICIUS];
void Cleanup()
{
for ( unsigned int i = 0; i < ALB_SKAICIUS; ++i )
{
free(a[i]);
}
}
/*
bool TestFnc( int **p, unsigned int dydis, int sk )
{
int *p_tmp = malloc( dydis * sizeof **p );
if (!p_tmp)
{
printf("Klaida: nagaliu priskirti atminties bloko.\n");
return false;
}
for ( unsigned int i = 0; i < dydis; ++i )
{
p_tmp[i] = i + sk;
}
*p = p_tmp;
return true;
}
*/
bool TestFnc( int **p, unsigned int dydis, int sk )
{
*p = malloc( dydis * sizeof **p );
if (!*p)
{
printf("Klaida: nagaliu priskirti atminties bloko.\n");
return false;
}
for ( unsigned int i = 0; i < dydis; ++i )
{
(*p)[i] = i + sk;
}
return true;
}
int main()
{
// priskiriam atmintį pirmam blokui, kurį, tarkim, sudarys 10 elementų
if(!TestFnc( &a[0], 10, 0 ))
{
printf("Klaida: (1)\n");
Cleanup();
return 1;
}
// priskiriam atmintį antram blokui, kurį, tarkim, sudarys 8 elementai
if(!TestFnc( &a[1], 8, 10 ))
{
printf("Klaida: (2)\n");
Cleanup();
return 1;
}
// priskiriam atmintį trečiam blokui, kurį, tarkim, sudarys 4 elementai
if(!TestFnc( &a[2], 4, 100 ))
{
printf("Klaida: (3)\n");
Cleanup();
return 1;
}
// bandom perskaityti keletą reikšmių
printf("%d\n", a[0][0]);
printf("%d\n", a[0][3]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][7]);
printf("%d\n", a[2][0]);
printf("%d\n", a[2][3]);
Cleanup();
return 0;
}
Failas:
dm-rodykles-2.c
gcc dm-rodykles-2.c -o testineprograma
Rezultatas paleidus:
0
3
10
17
100
103
testuojam su valgrind:
in use at exit: 0 bytes in 0 blocks
total heap usage: 4 allocs, 4 frees, 1,112 bytes allocated
All heap blocks were freed -- no leaks are possible