2010/09/10

Jak zawiesic programiste ?

Uff było ciężko ...

Problem jest taki, mamy taki niewinny kod:

#include

int get_val(const int **pp)
{
    return **pp;
}

int main()
{
    int v = 10;
    int *t[] = { &v };

    printf("%i\n", get_val(t) );
}


Kompilator w linii z printf zgłasza błąd ? Dlaczego, przecież nie robię nic złego :). Deklaruje tablice wskaźników do int o wielkości jednego elementu (jeden wskaźnik), i chce go przekazać wskaźnik do tej tablicy do funkcji która zwraca wartość; Funkcja nie modyfikuje zawartości elementów wiec dodajemy const, tak dla zasady :) (bo w firmie wymagają żeby dawać const)

Poniższa strona nie za bardzo mnie przekonała:
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17

Wolałem sobie to wytłumaczyć następująco:
#include

const v = 0;
const int *p = &v;

int get_val(const int **pp)
{
    *pp = p;
    return **pp;
}

int main()
{
    int v = 10;
    int *t[] = { &v };

    //printf("%i\n", get_val(t) );

    *(t[0]) = 20; //tutaj teoretycznie modyfikujemy lokalna zmienna, a tak naprawdę funkcja podmieniła wskaźnik i modyfikujemy const ... otrzymujemy SIGSEG
    printf("%i\n", v );
}


Teraz ewidentnie widać dlaczego rzutowanie int ** na const int ** jest zabronione :)
Bład w stwierdzeniu jest następujący:
Deklaruje tablice wskaźników do int o wielkości jednego elementu (jeden wskaźnik), i chce go przekazać wskaźnik do tej tablicy do funkcji która zwraca wartość. Funkcja nie modyfikuje zawartości elementów ALE MOŻNE MODYFIKOWAĆ ZAWARTOŚĆ TABLICY :), w szczególności podmienić wskaźnik na coś czego zmieniać nie wolno (a co jest poprawnym adresem procesu).

PS: A mówią ze stałe wskaźniki są niepopularne
PS2: Teraz już wiem gdzie są wykorzystywane :P. Wykorzystywane są do męczenia biednych developerów :D
PS3: Wymiękam ... dlaczego poniższe jest problemem ? HELP!!!
int main()
{
    int v;
    int * const p = &v;
    const * const **pp = &p;
}