eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programmingpryszcze... › Re: pryszcze...
  • X-Received: by 10.49.117.170 with SMTP id kf10mr981qeb.36.1389781159904; Wed, 15 Jan
    2014 02:19:19 -0800 (PST)
    X-Received: by 10.49.117.170 with SMTP id kf10mr981qeb.36.1389781159904; Wed, 15 Jan
    2014 02:19:19 -0800 (PST)
    Path: news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!news.cyf-kr.edu.pl!news.nask
    .pl!news.nask.org.pl!news.unit0.net!news.glorb.com!6no11345233qao.1!news-out.go
    ogle.com!gg4ni4085qab.0!nntp.google.com!6no11345229qao.1!postnews.google.com!gl
    egroupsg2000goo.googlegroups.com!not-for-mail
    Newsgroups: pl.comp.programming
    Date: Wed, 15 Jan 2014 02:19:19 -0800 (PST)
    In-Reply-To: <lb5jt7$mlv$1@node1.news.atman.pl>
    Complaints-To: g...@g...com
    Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=89.67.189.218;
    posting-account=f7iIKQoAAAAkDKpUafc-4IXhmRAzdB5r
    NNTP-Posting-Host: 89.67.189.218
    References: <lb0plj$jfj$1@node2.news.atman.pl>
    <1...@g...com>
    <lb0rbd$l6n$1@node2.news.atman.pl>
    <7...@g...com>
    <lb0sk5$mgl$1@node2.news.atman.pl>
    <b...@g...com>
    <lb3o9l$ir1$1@node2.news.atman.pl>
    <9...@g...com>
    <lb3pl8$k6t$1@node2.news.atman.pl>
    <9...@g...com>
    <lb3ta8$o6m$1@node2.news.atman.pl> <lb3tke$oje$1@node2.news.atman.pl>
    <52d57fb0$0$2356$65785112@news.neostrada.pl>
    <a...@g...com>
    <52d5abae$0$2147$65785112@news.neostrada.pl>
    <3...@g...com>
    <lb5jt7$mlv$1@node1.news.atman.pl>
    User-Agent: G2/1.0
    MIME-Version: 1.0
    Message-ID: <f...@g...com>
    Subject: Re: pryszcze...
    From: g...@g...com
    Injection-Date: Wed, 15 Jan 2014 10:19:19 +0000
    Content-Type: text/plain; charset=ISO-8859-2
    Content-Transfer-Encoding: quoted-printable
    Xref: news-archive.icm.edu.pl pl.comp.programming:204932
    [ ukryj nagłówki ]

    W dniu środa, 15 stycznia 2014 10:20:37 UTC+1 użytkownik inny punkt siedzenia...
    napisał:
    > a czy m�g�by� co� ciekawego napisac jeszcze o wska�nikach na wska�nik?

    Nie wiem, czy to ciekawe, ale moge podac przyklad
    zastosowania wskaznika na wskaznik.

    Zakladam, ze wiesz, co robi funkcja printf -- pozwala
    na wypisanie formatowanego tekstu na standardowe wyjscie,
    np. printf("%d %s\n", 7, "samurajow") wypisze "7 samurajow"
    i znak nowej linii. Specyfikator "%s" sprawia, ze jako
    drugi argument funkcja pobiera wskaznik na char, co
    do ktorego zaklada sie, ze wskazuje na fragment pamieci,
    w ktorym znajduje sie sekwencja znakow ASCII (powiedzmy)
    zakonczona znakiem '\0' (albo po prostu liczba 0, bo to
    to samo), czyli tzw. "null-terminated string".

    Istnieje tez nieco ogolniejsza funkcja fprintf, ktora
    pozwala wybrac strumien, do ktorego bedziemy pisac.

    Istnieja tez dwie funkcje, ktore pozwalaja zapisac formatowany
    string do pamieci. Maja one nastepujace prototypy:

    int sprintf ( char * str, const char * format, ... );
    int snprintf ( char * s, size_t n, const char * format, ... );

    Pierwsza z nich pobiera wskaznik na bufor, do ktorego
    chcemy pisac. Na przyklad mozemy sobie wyobrazic taki
    fragment kodu:

    char buffer[256];
    sprintf(buffer, "mam sobie string `%s` o nieznanej dlugosci!", jakas_zmienna);

    Problem polega na tym, ze nie wiemy, jak dlugi jest
    string wskazywany przez jakas_zmienna. W szczegolnosci
    moze byc na tyle dlugi, ze nie zmiesci sie w buforze
    (tzn. docelowy string bedzie mial w typ przypadku
    wiecej niz 256 znakow), co moze spowodowac nadpisanie
    wartosci jakichs zmiennych w tej samej przestrzeni
    adresowej, co zmienna buffer. Innymi slowy, moze byc
    zle, bo po 1. moze to byc przczyna trudnych do wykrycia
    i nieprzewidwalnych bledow, a po 2. moze niekiedy
    pozwolic jakiemus hakerowi tak spreparowac dane wejsciowe
    (zakladajac, ze jakas_zmienna jest inicjalizowana danymi
    wejsciowymi), ze przejmie kontrole nad Twoim komputerem.

    Jednym z rozwiazan jest uzycie funkcji snprintf, ktora
    oprocz adresu bufora pobiera informacje o jego dlugosci,
    tak ze mozesz sobie napisac

    snprintf(buffer, 256,
    "mam sobie string `%s` o nieznanej dlugosci!", jakas_zmienna);

    Jest to jednak rozwiazanie o tyle malo satysfakcjonujace,
    ze wprawdzie bezpieczenstwo systemu wzrasta, ale wygenerowany
    string moze zostac brzydko uciety (co zreszta moze powodowac
    problemy innego rodzaju).

    Z tego powodu standard GNU wprowadza funkcje asprintf,
    o nastepujacej sygnaturze:
    int asprintf(char **strp, const char *fmt, ...);

    Jak widac, funkcja ta jako pierwszy argument pobiera
    wskaznik na wskaznik na char. Idea jest taka, ze to
    funkcja asprintf jest odpowiedzialna za to, zeby
    zaalokowac odpowiednio duzy bufor. Dzieki temu mamy
    pewnosc, ze wszystko bedzie dzialalo dobrze dopoty,
    dopoki w komputerze jest dostepna dostateczna ilosc
    pamieci. Jedyna upierdliwosc jest taka, ze musimy
    sami pozniej zwolnic te pamiec. Czyli sposob uzycia
    funkcji jest mniej wiecej nastepujacy:

    char *buffer_pointer;
    if(asprintf(&buffer_pointer, "jakis format", jakies zmienne ...) != -1) {
    // pouzywaj sobie jakos wygenerowanego tekstu
    // ...
    // a na koncu zwolnij pamiec
    free(buffer_pointer);
    }

    Analogiczny problem (i rowniez rozwiaznywany przy
    pomocy wskaznikow na wskazniki) jest zwiazany z funkcja
    [fs]?scanf.

    Tutaj pozwole sobie przekleic przyklad z manuala:

    /* scanf example */
    #include <stdio.h>

    int main ()
    {
    char str [80];
    int i;

    printf ("Enter your family name: ");
    scanf ("%79s",str);
    printf ("Enter your age: ");
    scanf ("%d",&i);
    printf ("Mr. %s , %d years old.\n",str,i);
    printf ("Enter a hexadecimal number: ");
    scanf ("%x",&i);
    printf ("You have entered %#x (%d).\n",i,i);

    return 0;
    }

    Jak widzimy, korzystamy ze specjalnego modyfikatora
    dla metody %s, dzieki ktorej zapewniamy, ze wczytywany
    tekst miesci sie w buforze. Gdyby nie bylo tej liczby,
    79, to scanf w trakcie czytania moglby wyjechac poza
    zakres bufora i znow nieprzyzwoicie namieszac.

    Jednak co jesli nie chcemy dawac ograniczen na rozmiar
    tekstu, ktory moze zostac wczytany? Tutaj znow z pomoca
    przychodza rozszerzenia GNU.

    Idea jest taka, ze zamiast adresu bufora przekazuje
    wskaznik na zmienna, ktora bedzie miala przechowywac
    adres nowozaalokowanego bufora:

    char *buf = NULL;
    scanf("%as", &buf);

    Ponownie programista musi jednak zadbac o kontrole
    bledow i o zwolnienie pamieci, gdy przestanie juz
    byc potrzebna:

    if(buf) {
    // zrob cos z zawartoscia bufora
    // ...
    free(buf);
    }

    HTH

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: