[ Príspevkov: 11 ] 
AutorSpráva
Offline

Skúsený užívateľ
Skúsený užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 11.01.09
Prihlásený: 19.12.20
Príspevky: 1290
Témy: 9 | 9
Bydlisko: HE
NapísalOffline : 09.05.2012 21:21 | Pochopenie smernikov v jazyku C

Urcite sa zhodneme na tom, ze jeden z najvacsich strasiakov jazyka C su prave smerniky ( pointre ). Tymto clankom sa pokusim co najviac detajlne a zaroven jednoducho vysvetlit tuto problematiku, aby ju pochopil ozaj kazdy a hlavne zaciatocnici, ktori so smernikmi prvy krat prisli do kontaktu.

1. ZAKLADNA TEORIA SMERNIKOV:
Co je to smernik? V prvom rade je to premenna, ako kazda ina. Je nutne podotknut, ze kazda jedna premenna v pamati zabera urcite miesto, v zavislosti od toho, akeho typu je dana premenna. Tak napriklad typ char bezne zabera 1 bajt, typ int zabera bezne 4 bajty, typ double 8, atd ( pisem bezne, pretoze je to zavisle aj od pouziteho kompilatora, operacneho systemu, a inych faktorov ). A kedze premenne nie su v pamati hociako porozhadzovane, ale kazda ma svoje miesto, musi sa aj nejako poznat, kde zacina, kde je jej adresa. Adresa je teda udaj, ktory nam presne hovori, kde je premenna v pamati umiestnena. Je to obycajne cislo, ktore dostaneme pomocou operatora ampersand & umiestnenim pred meno premennej. Mozte si ju kludne nechat vypisat, ale zrejme z toho nic mat nebudete, hodi sa vam maximalne pri debuggovani ( ladeni programu ):
Kód:
    char premenna;
    printf( "%x\n", &premenna );    /* %x je vypis hexadecimalneho cisla, pretoze adresy sa zvyknu oznacovat v 16-kovej sustave */


Takze teraz by ste mali vediet, co je to adresa premennej. Tento poznatok je dolezity k tomu, aby sme si dalej doplnili, co je to smernik. Je to premenna, ktora nesie adresu inej premennej. V zavislosti od toho, akeho typu je premenna, ktorej adresu pozadujeme ulozit do smernika, aj samotny smernik definujeme ako smernik na urcity typ, napr smernik na char, smernik na int, a podobne. Pre ilustraciu si prezrite nasledovny priklad:
Kód:
    char    znak        = 'a';
    int     celeCislo   = 10;
    double  desCislo    = 3.14;

    char    *pZnak      = &znak;    /* pointer na typ char */
    int     *pCeleCislo;            /* pointer na typ int */
    double  *pDesCislo;             /* pointer na typ double */

    pCeleCislo = &celeCislo;        /* priradenie adresy premennej celeCislo do premennej pCeleCislo */


A pre lepsiu predstavu pomozu aj tieto obrazky:
Obr1: Pochopenie smernikov v jazyku C

Obr2: Pochopenie smernikov v jazyku C


Poznamka: tento obrazok sluzi iba ako mala pomocka pre lepsie pochopenie. Data su v pamati ukladane komlikovanejsim sposobom, hlavne co sa tyka premennych vacsich ako jeden bajt, preto to berte len ako zjednodusenu ilustraciu. Ak vas zaujimaja tato problematika, mozte sa pozriet na tieto linky:
http://en.wikipedia.org/wiki/Endianness
http://www.doc.ic.ac.uk/~eedwards/compsys/memory/index.html


Uplne v prvom riadku su nazvy premennych podla predchadzajuceho prikladu, cize znak, pZnak, celeCislo a pCeleCislo. Nazvy premennych si vyberame my, podla vlastneho vyberu. V druhom riadku, uz v tej tabulke, je adresa jednotlivych premennych. Tieto adresy prideluje operacny system, nie my, cize nad tymi cislami sa velmi nezamyslajte, ako sa tam dostali. Jeden stvorcek na obrazku predstavuje vekost jeden bajt, to znamena, ze do jedneho takehoto stvorceka mozme ulozit maximalne jeden bajt. Kedze napriklad typ int ma 4 bajty, potrebujeme na ulozenie akehokolvek cisla typu int styri taketo stvorceky v pamati. A nakoniec, v poslednom riadku, taktiez v tabulke, mozte vidiet hodnoty jednotlivych premennych, cize udaj, ktory uchovavaju tieto premenne. V pripade premennych znak a celeCislo sa nie je o com bavit. V pripade pZnak a pCeleCislo uz sa ale trocha zastavime. Vidime, ze smernik skutocne nesie adresu inej premennej ( tej, na ktoru ho priradime, ako v priklade vyssie ). A ze tato adresa ma velkost 4 bajty. Tento poznatok si zapamatajte, pretoze ci sa jedna o adresu premennej typu char alebo adresu zlozitej struktury, ktora moze mat niekolko rozne velkych poloziek, velkost adresy je stale o velkosi styroch bajtov ( aspon co sa tyka doby pisania tohto clanku ). Pevne verim, ze tieto obrazky vam pomohli lepsie si predstavit, ako to vlastne v pamati funguje.

Naco je vlastne dobre uchovavat adresy inych premennych? Odpoved je jednoducha, skusim to najprv vysvetlit na priklade zo zivota. Kazdy z nas mame svoj domov, kde byvame. Tento nas domov ma nejaku adresu. Prave pomocou tejto nasej adresy nas mozu ostatni ludia kontaktovat, posielat nam na tuto adresu nejaku postu a podobne. Rovnako ako my mame svoju adresu, kde byvame, aj premenne maju adresu, svoje umiestnenie v pamati. A rovnako, ako nas moze niekto kontaktovat pomocou nasej adresy, tak mozme aj my pristupovat k premennej skrz jej adresu ( v skutocnosti je aj nazov premennej len akysi symbol v dobe navrhu a v skutocnosti sa pracuje prave s jej adresou ). Predstavte si situaciu, ze mate funkciu, ktora ma vydelit dve cisla, ale chcete ju navrhnut tak, aby jej navratova hodnota nebola vysledok, ale aby vratila nulu v pripade, ze chcete delit nulou a jednotku v pripade, ze delenie prebehlo v poriadku. A vysledok chcete vratit v nejakej konkretnej premennej. Co v takomto pripade? Vacsina asi vie, ze nieco taketo to nevyriesi:
Kód:
#include <stdio.h>

int vydel( double delenec, double delitel, double vysledok )
{

    if ( delitel == 0 )
        return 0;                   /* nulou neviem delit, vysledok funkcie je 0 - FALSE */

    vysledok = delenec / delitel;   /* v opacnom pripade si ulozime vysledok a vratime 1 - TRUE */
    return 1;

}

int main()
{

    double vysledokDelenia = 0;

    if ( vydel( 121, 11, vysledokDelenia ) == 1 )
        printf( "Vysledok delenia je %f\n", vysledokDelenia );    /* vypise sa 0, ale to nie je spravne, vsak? */
    else
        printf( "Delenia nulou\n" );

    return 0;

}


Ti, ktori neviete, preco, tak tu je vysvetlenie: Pri volani kazdej funkcie sa cez zasobnik predaju parametre funkcie a to tak, ze sa vytvori iba ich kopia, tzn, predaju sa iba hodnoty tychto parametrov. My vo vnutri funkcie nevieme, ktorej premennej patri dana hodnota. Riesenim je pouzit smerniky. Preco? Pretoze hodnota smernika je prave adresa nejakej premennej. A teda ak predame funkcii ako parameter smernik, skopiruje sa jeho hodnota ( adresa pozadovanej premennej, ktoru nesie, na ktoru ukazuje ) a my tak mame aj vnutri funkcie pristup k premennej, ktoru potrebujeme menit. Upraveny funkcny priklad:
Kód:
#include <stdio.h>

    /* premenna vysledok je uz pozmenena na smernik */
int vydel( double delenec, double delitel, double *vysledok )
{

    if ( delitel == 0 )
        return 0;                   /* nulou neviem delit, vysledok funkcie je 0 - FALSE */

    *vysledok = delenec / delitel;  /* na adresu, na ktoru ukazuje premenna vysledok, uloz vysledok delenia */
    return 1;                       /* vrat 1 - TRUE */

}

int main()
{

    double vysledokDelenia = 0;

    if ( vydel( 121, 11, &vysledokDelenia ) == 1 )
        printf( "Vysledok delenia je %f\n", vysledokDelenia );    /* vypise sa 11 */
    else
        printf( "Delenia nulou\n" );

    return 0;

}


Smerniky sa dalej mozu vyuzivat aj na dynamicku alokaciu poli, kopirovanie blokov pamate, prechadzanie buniek pola atd. V mnohych pripadoch moze vhodne pouzitie smernikov aj usetrit pamat, alebo zrychlit program. Teraz, ked uz viete, kedy a preco pouzivat smerniky, este si povieme, ako ich spravne pouzivat, lebo aj s tym ma vela zaciatocnikov problemy. Napriklad ci pisat hviezdicku pred meno smernika alebo za meno, kedy pisat hviezdicku a kedy nie, atd.
Miesto, kde treba pisat hviezdicku, si zapamatate velmi jednoducho podla samotnej definicie smernika:
Kód:
    int *smernik;


Hvezdicka je stale za typom smernika a pred nazvom smernika. Preto stale, ked pracujete s adresou, ktora je ulozena v smerniku, piste hviezdicku pred meno:
Kód:
    a = b + *smernik + c;


a stale, ked pretypujete nejaky smernik na iny smernik, tak hviezdicka sa pise za typ smernika:
Kód:
    smernik = (int*) inySmernik;


Hviezdicku k smerniku piseme vtedy, ak chceme pracovat s premennou, ktorej adresa je ulozena v smerniku - ci uz chceme odtial citat, alebo zapisovat. Vtedy hovorime, ze sme smernik dereferencovali ( cize *smernik ). V pripade, ze chceme narabat so samotnym smernikom, napriklad ak tam chceme vlozit novu adresu inej premennej, pripadne pracovat s adresou ktora tam uz je, napr pricitat k nej nejake cislo a posuvat sa tak v pamati, hviezdicku nepouzivame.


2. DYNAMICKA ALOKACIA
V predchadzajucich prikladoch sme pracovali s pamatou, ktora bola alokovana staticky, to znamena, vsetky premenne, ktore sme pouzivali, mali uz v dobe kompilacie vyhradene svoje miesto v pamati presnej velkosti ( vid obrazky 1 a 2 ). A toto miesto im ostavalo pevne pocas celeho behu programu ( menil sa len, samozrejme, obsah tychto premennych ). Mnohokrat ale v nasom programe budeme potrebovat premenne, ktorych velkost dopredu nebudeme vediet, pripadne, ktorych velkost budeme potrebovat dynamicky menit, apod. Na tieto ucely sluzi dynamicka alokacia a spaja sa vylucne s pouzitim smernikov. Pri tejto alokacii sa pouziva uplne iny segment pamate, a ten nazyva sa heap. Pamat je pridelovana operacnym systemom na "poziadanie" programatora. A co je dolezite, tato pamat je aj uvolnovania na poziadanie. Ak neuvolnite alokovanu pamat pred ukoncenim programu, ostane sa pouzivat aj po ukonceni programu a vzniknu tak "prazdne miesta", ktore sa nazyvaju memory leaks. Je preto dobre hned zo zaciatku sa spravne naucit narabat s touto castou pamate. Existuje skvely nastroj na odhalovanie tychto chyb programatora a nazyva sa valgrind. Zial, tento program nie je urceny pre OS windows - aspon v sucasnosti nie. Vratme sa ale k samotnej dynamickej alokacii a ako ju pouzit. V jazyku C existuju tri zakladne funkcie pre pracu s heap-om a su to malloc, calloc a realloc. Pre uvolnenie alokovanej pamate sa pouziva jedina funkcia free. Vsetky tieto funkcie su deklarovane v hlavickovom subore stdlib.h. Pre jednoduchost nam na prikladoch postaci pouzit funkciu malloc. Ta berie iba jeden parameter a to velkost pamate v bajtoch, ktoru chceme alokovat. Operacny system sa potom pokusi tutu velkost rezervovat a v pripade, ze nema dostatok pamate, funkcia vrati NULL ( tiez zvany nulovy smernik. Oznacuje sa nim, ze smernik neukazuje na ziaden objekt, na ziadnu pamat ). V pripade, ze potrebnej pamate je dostatok, tak tuto cast pamate alokuje ( obsadi ju a "oznaci" ako pouzitu ) a funkcia vrati smernik na prvy blok tejto pamate. Nam totiz staci vediet iba to, kde je zaciatok, pretoze jej velkost vieme. Po tomto procese uz mame v smerniku adresu na cast pamate, s ktorou uz pracujeme ako v priklade pred tym. Nasleduje jednoducha ukazka:
Kód:
#include <stdio.h>
#include <stdlib.h>

int main()
{

    int     premenna;   
    int     *sm = NULL;

    sm = malloc( sizeof( int ) );           /* do smernika sm chceme priradit pamat o velkosti datoveho typu int */
    if ( sm == NULL )                       /* ak malloc vrati NULL, nastala chyba pri alokacii */
    {
        printf( "Chyba pri alokacii pamate\n" );
        return 1;
    }
   
    printf( "Adresa premennej na stacku: %x\nAdresa v casti pamati zvanej heap, ktoru sme priradili do smernika sm: %x\n",
        &premenna, sm );

    *sm = 10;
    printf( "\nSmernik = %d", *sm );
    *sm = 5;
    printf( "\nSmernik = %d\n", *sm );

    free( sm );                 /* nezabudnut uvolnit pamat pred ukoncenim programu */
    return 0;

}


Chcem este upozornit na jednu vec. Funkcia malloc vracia smernik typu void*. Ak my pouzijeme iny typ smernika, ako napr v tomto priklade int*, neodporuca sa pretypovat tuto navratovu hodnotu funkcie malloc, cize nasledujuce nerobte: sm = (int*) malloc( sizeof( int ) );
V pripade, ze vas zaujima dovod, tu si o tom mozte precitat viac ---> http://c-faq.com/malloc/mallocnocast.html Ak pouzijete pretypovanie, nie je to chyba, ale je dobre sa tomu vyhnut ( zial, v sucasnosti na skolach ucia vselijaki ucitelia a na mnohych skolach sa uci aj tento nespravny postup ). Bavime sa ale iba o pretypovani navratovej funkcie z malloc. Teraz uvediem trocha komplikovanejsi priklad, kde vyuzijeme aj pretypovanie. Vyuzijem v nom aj smernik void* ktory sa neda dereferencovat, pretoze typ void nemoze niest ziaden udaj, je to tzv prazdny datovy typ. Priklad:
Kód:
#include <stdio.h>
#include <stdlib.h>

void halt( char *msg )              /* v pripade chyby zavolame tuto funkiu, kt. ukonci program */
{
    printf( "%s\n", msg );
    exit( EXIT_FAILURE );
}

int main()
{

    void     *sm;

    sm = malloc( sizeof( int ) );   /* rezervujme si miesto pre jeden int */
    if ( sm == NULL )
        halt( "Malloc failed\n" );

    *( (int*) sm ) = 10;    /* vsimnite si tento zapis pozorne. Chceme zapisat cislo 10 do pamate, kam ukazuje
                             * smernik sm. Lenze ten je typu void* preto ho najpr musime pretypovat na typ
                             * int*, cize to je to (int*) sm. Teraz uz ho mozme dereferencovat a do pamate
                             * zapisovat hodnoty o velkosti typu int */

    printf( "Na adrese, ktoru mame v sm, je naozaj hodnota %d\n", *( (int*) sm ) );     
 
        /* teraz sa rozhodneme, ze do smernika chceme ulozit znak, nie cislo, takze povodnu pamat uvolnime */
    free( sm );                     
        /* a alokujeme novu, tentokrat pre typ char */
    sm = malloc( sizeof( char ) );
    if ( sm == NULL )
        halt( "Malloc failed\n" );

    *( (char*) sm ) = 'f';
    printf( "Tento krat tu mame znak '%c'\n", *( (char*) sm ) );

    free( sm );
    return 0;

}


V oboch prikladoch sme si ukazali iba alokaciu pamate pre jeden zakladny datovy typ. My si ale mozme pomocou funkcie malloc ( a ostatnych spomenutych ) alokovat kludne aj viac pamate a k danemu bloku pristupovat pomocou smernikov a pouzivat ho, akoby to bolo pole ( pozor - mozme ho s touto pamatou zaobchadzat, akoby to bolo pole, ale pole to nie je, viz nasledujuci bod 3 ). Najprv uvediem jednoduchy priklad, pricom predpokladam, ze pracu s poliami uz ovladate:
Kód:
#include <stdio.h>
#include <stdlib.h>

void halt( char *msg )
{
    printf( "%s\n", msg );
    exit( EXIT_FAILURE );
}

int main()
{

    int     i;
    int     *smBlokIntov;           /* vsimnite si, ze definicia smernika je aj v pripade, ze
                                     * alokujeme viac pamate rovnaka. Smernik totiz drzi iba adresu,
                                     * kde zacina nasa alokovana pamat - velkost tohto bloku totiz
                                     * pozname */

    smBlokIntov = malloc( 4 * sizeof( int ) );  /* rezervujme si miesto pre 4 prvky, pricom kazdy
                                                 * je velkosti typu int ( ktory ma 4 bajty ), cize vysledna
                                                 * pamet bude velkosti 4*4 b = 16 bajtov */
    if ( smBlokIntov == NULL )
        halt( "Malloc failed\n" );

    for ( i = 0; i < 4; i++ )
        smBlokIntov[i] = i+1;           /* do nasej pamate postupne ulozime cisla od 1 po 4. Snad netreba
                                         * pripominat, ze pole sa indexuje od nuly, nie od jednotky */

    for ( i = 0; i < 4; i++ )
        printf( "Hodnota pola na indexe %d je %d\n", i, smBlokIntov[i] );

    putchar( '\n' );
    free( smBlokIntov );
    return 0;

}



3. SMERNIKY VS POLIA:
Pole je premenna, ktora obsahuje viacero prvkov rovnakeho datoveho typu. Velmi casto sa pouziva nespravny pojem, ze pole je vlastne smernik, co nie je tak celkom pravda, su si iba velmi podobne a smernik na dynamicky alokovanu pamat mozme pouzivat ako pole. A to je asi tak vsetko. Pozrime sa na nasledujuci priklad:
Kód:
#include <stdlib.h>

void halt( char *msg )
{
    printf( "%s\n", msg );
    exit( EXIT_FAILURE );
}

int main()
{

    char    pole[4] = { 1, 2, 3, 4 };
    char    *smernik;
    int     i;

    smernik = malloc( 4 * sizeof( char ) );
    if ( smernik == NULL )
        halt( "Malloc failed\n" );

    for ( i = 0; i < 4; i++ )
        smernik[i] = i+10;

    for ( i = 0; i < 4; i++ )
    {
        printf( "Hodnota pola na indexe %d je %d\n", i, (int) pole[i] );   /* v poli mam ulozeny typ char, preto ho pretypujeme na int */
        printf( "Hodnota dynamicky alokovaneho pola na indexe %d je %d\n", i, (int ) smernik[i] );
    }

    putchar( '\n' );
    free( smernik );
    return 0;

}


Cisla sa vypisali presne take, ake sme ocakavali, takze by ste asi povedali, ze aj premenna pole aj premenna smernik su klasicke polia, vsak? A predsa tomu tak nie je. Pozrite sa na tento obrazok a hned uvidite rozdiel,
Obrazok3: Pochopenie smernikov v jazyku C

Je krasne vidiet, ze smernik, tak ako som spominal na zaciatku, nesie iba adresu, kde blok s datami zacina. Pouzivanie poli a smernikov je ale rovnake. Ci uz zavolame pole[2], alebo *(pole + 2), stale sa dostaneme na pamat, kde je ulozene cislo 3. A takisto aj zapisom smernik[2] a *(smernik + 2 ) sa dostaneme na pamat, kde je ulozene cislo 12.
Problem pri zameneni smernika s polom nastane hlavne pri dvoj a viac rozmernych poliach a tento problem je dost casty a mnohi zaciatocnici nechapu, aky je rozdiel medzi double **premenna a double premenna[10][5]. Ten rozdiel je dost velky, ale o tom napisem az v dalsej casti, ak o nu bude zaujem.

V pripade, ze ste niecomu aj tak nepochopili, pripadne mam niekde chybu, tak len smelo piste.


Offline

Skúsený užívateľ
Skúsený užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 02.07.06
Prihlásený: 27.01.21
Príspevky: 13804
Témy: 295 | 295
Bydlisko: Bratislava
NapísalOffline : 10.05.2012 9:12 | Pochopenie smernikov v jazyku C

Pekne si sa s tym pohral :)

Mozno by bolo vhodne presunut to do sekcie "Assembler, C, C++, Pascal, Java" a oznacit to ako dolezite :rolleyes:

Pre zaciatocnikov by to bolo pristupnejsie.


_________________
PODPIS BOL UPRAVENÝ / ZMAZANÝ Z DÔVODU PORUŠOVANIA PRAVIDIEL FÓRA!
Offline

Skúsený užívateľ
Skúsený užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 11.01.09
Prihlásený: 19.12.20
Príspevky: 1290
Témy: 9 | 9
Bydlisko: HE
Napísal autor témyOffline : 10.05.2012 11:42 | Pochopenie smernikov v jazyku C

Vdaka. Ak to uznaju moderatori za vhodne, tak nech sa to kludne presunie. Neskor este pridam popis dvojrozmernych poli a pridal by som aj pracu s retazcami, tam tiez robia zaciatocnici mnohe chyby.
Ale pridam to len v pripade, ze bude zaujem, naco stracat cas, ak to je vysvetlene nedostatocne, alebo komplikovane ( co dufam, ze nie je ) :)


Offline

Skúsený užívateľ
Skúsený užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 02.07.06
Prihlásený: 27.01.21
Príspevky: 13804
Témy: 295 | 295
Bydlisko: Bratislava
NapísalOffline : 10.05.2012 12:56 | Pochopenie smernikov v jazyku C

Nemyslim, ze j to vysvetlene komplikovane. Ja sa "Ceckom" nezaoberam (uprednostnujem vyssie jazyky), ale citim akusi povinnost, chapat aspon zaklady tych nizsich.Prave dnes si idem po Heroutovu ucebnicu jazyka C, tak to budem moc porovnat :lol:

Inak pre mna to bolo velmi zrozumitelne ;)


_________________
PODPIS BOL UPRAVENÝ / ZMAZANÝ Z DÔVODU PORUŠOVANIA PRAVIDIEL FÓRA!
Offline

Užívateľ
Užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 07.04.12
Prihlásený: 27.01.21
Príspevky: 908
Témy: 54 | 54
NapísalOffline : 10.05.2012 14:26 | Pochopenie smernikov v jazyku C

Veľmi dobrý návod, keďže sa učím C, určite by som uvítal aj podobné články.


_________________
Notebook: Dell Inspiron 15-7537= i5-4200U|nVidia GT 750M 2GB|RAM 6GB|250GB Samsung 850 EVO|W8.1|Cooler Master NotePal U3
Pc: Asus Rog Strix B360-G | i7-8700 | MSI 1080 Gaming X | Crucial Ballistix 16GB 2666MHz Dual Ranked | Samsung 970 Evo | Crucial MX500 | WD Red | Fera 3 | Arctic F12 Silent | Seasonic Focus Plus 650W Gold | Fractal Design Mini C TG
Disk: Western Digital Elements 1TB USB 2.0; Seagate Expansion 2TB USB 3.0
Príslušenstvo: A4tech Bloody V3 V-Track Core 3 + A4tech Bloody B-070; A4tech Bloody B120; A4tech Bloody G501; ATH-M40x; MSI Clutch M40
Monitor: Dell U2515H
Mobil: Xiaomi Redmi Note 3 Special Edition
Offline

Užívateľ
Užívateľ
Obrázok užívateľa

Registrovaný: 14.01.12
Prihlásený: 20.07.13
Príspevky: 46
Témy: 9 | 9
NapísalOffline : 11.06.2012 10:22 | Pochopenie smernikov v jazyku C

niesom ziaden profi, ale ked som bol na samom zaciatku takyto clanok by som urcite uvital .je pisany vecne a ucelovo.n1


Offline

Užívateľ
Užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 25.11.09
Prihlásený: 14.01.21
Príspevky: 262
Témy: 32 | 32
Bydlisko: LV / Brno
NapísalOffline : 18.05.2013 23:36 | Pochopenie smernikov v jazyku C

mám teoretickú otázku, mám kód
Kód:
int main()
{
    char *buffer = malloc(1000000);
    while (1);
    free(buffer);
    return 0;
}

a ked program killnem cez Task manager, k free(buffer) sa uz program nedostane a vytvori sa mi memory leak ze?


_________________
i5 6600K @ 4,5GHz | MSI GTX 1060 6GB Armor OC | HyperX Fury 2x8GB 2133MHz
Xperia XZ2 Compact
Offline

Užívateľ
Užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 27.12.08
Prihlásený: 24.11.16
Príspevky: 1874
Témy: 96 | 96
Bydlisko: Bratislava,...
NapísalOffline : 19.05.2013 8:58 | Pochopenie smernikov v jazyku C

Na vsetkych dnes bezne pouzivanych OS ti sam OS dealokuje vsetku pamat, ktoru proces alokoval, ked proces ukonci, cize nie, ziadne memory leak-y neostavaju po skonceni procesu. Memory leak nastane vtedy, ked proces sam zabudne nejaku pamat dealokovat a strati na nu vsetky smerniky. Od tohto momentu, az po moment, ked sa proces skonci je dana pamat stratena.


_________________
~Listen to your brain, not your heart~
NB1: Lenovo Y500: CPU: Intel Core i7-3630QM; GPU: nVidia GT650M 2GB SLi; RAM: 16GB DDR3; HDD: 1TB + 256GB SSD (m4); LCD: 15,6" 1920x1080; OS: Win8.1 64-bit + Arch Linux 64-bit (UEFI Powered DualBoot)
NB2: Asus K53SJ-SX093: CPU: Intel Core i3-2310M; GPU: Intel HD3000 / nVidia GT520M 1GB Optimus; RAM: 8GB DDR3; SSD: 128GB 840Evo; LCD: 15,6" 1366x768; OS: Win 8.1 Pro 64-bit (UEFI)
Offline

Užívateľ
Užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 06.06.12
Prihlásený: 24.06.15
Príspevky: 64
Témy: 19 | 19
Bydlisko: Michalovce
NapísalOffline : 08.10.2014 20:16 | Pochopenie smernikov v jazyku C

Velmi perfektne napisane, cital som knihu o C avsak tam som smernikom celkom nerozumel, teda pochopil som to ze pointer je nejaka premenna ktora len ukazuje na adresu druhej premennej, ale to dynamicke alokovanie pamate som vobec nechapal. TERAZ mi to uz je zrejme :) som rad ze tu je taky prispevok a mohol som sa nim "dusevne obohatit" :D. Bolo by fajn ak by vznikalo este viac takychto prispevkov. Napisal si ze ak by bol zaujem. Samozrejme ze asi kvoli jednemu cloveku to nenapises, ale ako som uz spominal, bolo by fajn ak by si v takychto veciach pokracoval. Bud v tom co si mal napisane na konci

Citujem:,,aky je rozdiel medzi double **premenna a double premenna[10][5]. Ten rozdiel je dost velky, ale o tom napisem az v dalsej casti, ak o nu bude zaujem."

alebo ja osobne by som prijal ak by si napriklad napisal clanok o pointeroch ukazujucich na funkcie, teda v kocke ako je to s funkciami a pointerami dokopy, v tom mam este celkom bordel aj doteraz (take tie veci ako... " double (*p_fd)(); " a pod.)
Inac ale vzdavam hold ;) bolo to kratke, vystizne, poucne ;)

ODPORUCAM!


Offline

Skúsený užívateľ
Skúsený užívateľ
Pochopenie smernikov v jazyku C

Registrovaný: 11.01.09
Prihlásený: 19.12.20
Príspevky: 1290
Témy: 9 | 9
Bydlisko: HE
Napísal autor témyOffline : 08.10.2014 22:54 | Pochopenie smernikov v jazyku C

Vdaka za kladny ohlas, ale asi ta trocha sklamem - programovaniu sa uz nevenujem a zabudnut som to sice nezabudol, ale ak nieco necvicis, tak je konkurencia daleko za tebou. A v sucasnosti je na fore kopec novych ( samozrejme aj starych ) sikovnych ludi v tomto smere, preto pevne verim, ze sa niekto aspon spolky tak ochotny, ako som bol stale ja, najde a pomoze doplnit tento clanok.
Ako som spomenul, vedel by som ti tuto problematiku vysvetlit, lebo zabudnut sa to jednoducho neda a ochotu pomahat stale mam, ale uz by to nebolo pisane od cloveka, ktory sa pohybuje v tomto obore, to je akoby ta ucil opravovat auto nie mechanik ale volajaky stolar. Stafetu podavam dalej :)


Offline

Skúsený užívateľ
Skúsený užívateľ
Obrázok užívateľa

Registrovaný: 17.07.11
Prihlásený: 29.12.20
Príspevky: 1516
Témy: 3 | 3
NapísalOffline : 09.10.2014 8:24 | Pochopenie smernikov v jazyku C

dablik415, pri pointeroch na funkcie ide len a len o syntax - tvar zápisu, nemusíš v tom hľadať nejaký extra zmysel. Ja to z času na čas použijem, ale aj tak sa pozriem na internet, ako sa to presne zapisuje, lebo si to proste nepamätám. Pri tomto konkrétne stačí vedieť, že sa to dá a na čo to je dobré.

Pritom syntax je jednoduchá, ale pri viacerých hviezdičkách môže vyzerať zložito
Kód:
// majme takuto funkciu
navratovyTyp nazovFunkcie( argTyp1 argMeno1, argTyp2 argMeno2, argTyp3 argMeno3, ...)
{
}

// teraz si urobime premennu
navratovyTyp (*nazovPremennej) (argTyp1, argTyp2, argTyp3, ...) = &nazovFunkcie;
Ampersand v C funguje ako "daj adresu", takže nič prekvapivé. Hviezdičku pred nazovPremennej nejako prekúsneme a proste ju tam budeme písať.

Takže napríklad
Kód:
int scitaj(int a, int b) { return a+b; }
->
int (*fscitaj) (int, int) = &scitaj; //vytvori premennu fscitaj, ukazujucu na pociatok funkcie scitaj
int a = fscitaj(5,6); // a pouzivam ako beznu funkciu


No a na čo je to dobré, väčšinou na nič :D Respektive funguje vďaka tomu úplne všetko, ale stretneš sa s tým typicky až v hlbších hlbinách programovania, v základoch iba málokedy.
Zvykne sa tým "simulovať" objektové programovanie procedurálnym spôsobom - tj. štruktúra, ktorá má nejaké členy ako premenné a nejaké ako ukazatele na funkcie.
Ďalej sa to využíva, keď chceš nejaký výpočet "zovšeobecniť" - typický príklad je radenie prvkov, ktorému definuješ vlastnú funkciu porovnania dvoch prvkov. Funkcia radenia je tak vždy rovnaká, no môže sa správať inak, v závislosti na tej funkcii porovnania (napr. si tak môžem korigovať, či chcem zostupné, alebo vzostupné radenie).
Ďalej sa to veľa využíva v jadre Unixu pri tvorbe ovládačov/modulov jadra, v implementácií komunikačných protokolov, prekladačoch a podobných srandách.

Za normálnych okolností to nebudeš k svojmu životu potrebovať a je dobré sa tomu čo najviac vyvarovať, tj. používať len keď je to už fakt nutné.


_________________
Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám!
 [ Príspevkov: 11 ] 


Pochopenie smernikov v jazyku C



Podobné témy

 Témy  Odpovede  Zobrazenia  Posledný príspevok 
V tomto fóre nie sú ďalšie neprečítané témy.

pochopenie zlozitejsieho .htaccess

v Ostatné

0

315

23.11.2010 15:33

baumax

V tomto fóre nie sú ďalšie neprečítané témy.

DYNAMICKE vs. STATICKE pole smernikov !!!SUUURNE!!!

v Assembler, C, C++, Pascal, Java

6

1908

11.05.2009 8:48

sangokoko

V tomto fóre nie sú ďalšie neprečítané témy.

Problem s hladanima mazanim u smernikov - Pascal

v Assembler, C, C++, Pascal, Java

6

372

10.05.2010 17:37

jahoda09

V tomto fóre nie sú ďalšie neprečítané témy.

Suma členov matice pomocou smerníkov ( v C-ečku )

v Assembler, C, C++, Pascal, Java

1

913

28.03.2009 10:05

neutronmind

V tomto fóre nie sú ďalšie neprečítané témy.

Staticke pole smernikov a jeho polozky - alokacia pamate

v Assembler, C, C++, Pascal, Java

6

1192

27.03.2009 17:42

programator

V tomto fóre nie sú ďalšie neprečítané témy.

Piercing v jazyku

[ Choď na stránku:Choď na stránku: 1 ... 7, 8, 9 ]

v Život, životný štýl, móda, bývanie

256

33888

30.11.2009 22:01

RRRaaadddooo

V tomto fóre nie sú ďalšie neprečítané témy.

v ako jazyku tvorit

v HTML, XHTML, XML, CSS

10

1346

04.08.2006 16:23

JanoF

V tomto fóre nie sú ďalšie neprečítané témy.

Myslime v jazyku C++

v Ostatné

0

769

07.06.2010 20:58

Johnnny

V tomto fóre nie sú ďalšie neprečítané témy.

vyhľadavač v inom jazyku

v Operačné systémy Microsoft

16

359

28.09.2016 22:11

Yacko

V tomto fóre nie sú ďalšie neprečítané témy.

Myslíme v jazyku C++

v Kúpim

0

188

06.10.2015 14:17

z4jko

V tomto fóre nie sú ďalšie neprečítané témy.

Akemu jazyku sa venovat?

v Assembler, C, C++, Pascal, Java

18

475

25.06.2014 22:06

Tiger1403

V tomto fóre nie sú ďalšie neprečítané témy.

hladam programatora v jazyku C

v Ponuka práce

1

356

09.04.2018 18:25

Miso122

V tomto fóre nie sú ďalšie neprečítané témy.

zbierka uloh v jazyku JAVA

v Assembler, C, C++, Pascal, Java

1

475

21.02.2012 15:19

Johnnny

V tomto fóre nie sú ďalšie neprečítané témy.

vytiahnut data v spravnom jazyku

v JavaScript, VBScript, Ajax

5

395

26.10.2010 2:51

DeeJay3

V tomto fóre nie sú ďalšie neprečítané témy.

pomoc v programovacom jazyku R

v Kôš

1

31

09.03.2019 12:05

michalesku

V tomto fóre nie sú ďalšie neprečítané témy.

IT++ kniznica v jazyku C

v Assembler, C, C++, Pascal, Java

1

603

17.10.2007 15:57

Codik



© 2005 - 2021 PCforum, edited by JanoF