2011/02/12

Design patterns

Polecam strone m.in. o design patterns, bardzo dobrze przygotowany materiał.

http://sourcemaking.com/

2011/01/31

ARM w SIM

Szukałem informacji na temat Cortex-M0 a tym czasem trafiłem na coś takiego:

Jak się okazuje można opchnąć 320KB flash i Cortexa-M3 w karcie SIM!!! Ciekawe czy zwykły zjadacz chleba może sobie kupić parę sztuk tych czipów. Już widzę urządzenia do podpisu cyfrowego Made In Home :D, lub inteligentne karty SIM do GSM. Ehhh ... gdyby tylko wróciły stare czasy wyciągania kluczy z SIM :)

http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATA_BRIEF/CD00252313.pdf

2011/01/30

Skróty klawiaturowe konsoli

Nie wiem czy znacie następujące skróty klawiaturowe konsoli:

!!
Powtórzenie ostatniego polecenia
!foo
Powtórzenie polecenia zaczynającego się od ‘foo…’ (np. !ps, !mysqladmin)
Ctrl-a
Skocz na początek linii
Ctrl-e
Skocz na koniec linii
Ctrl-l
Wyczyść ekran
Ctrl-r
Wyszukaj polecenie w historii (szukanie wstecz). Jeżeli chcemy edytować polecenie - wciskamy strzałkę w prawo
Alt-?
Podpowiedzi uzupełnienia komend
Ctrl-k
Wytnij tekst do końca linii
Ctrl-u
Wytnij tekst ad początku linii do kursora
Ctrl-y
Wklej wycięty tekst

ARM w pigułce

Kto chce się szybko i w skrócie zapoznać z asemblerem i kodem startowym dla ARM polecam:
http://www.bravegnu.org/gnu-eprog/index.html

Dla mnie najciekawsze było streszczenie architektury rozkazów ARM:
http://www.bravegnu.org/gnu-eprog/arm-iset.html


Do tego polecam
http://www.stm32.eu/index.php?option=com_content&view=category&layout=blog&id=35&Itemid=57

2010/12/22

Niewinne static

Czym różną się zmienne globalne oznaczone jako static:
- ich definicja nie jest dołączana do tablicy exportu
- są inicjalizowane tylko raz (podczas uruchomienia kodu startowego, domyślnie 0 (sekcja bss) lub wartością podana przy deklaracji (sekcja .data))

O ile pierwsza właściwość jest mało inwazyjna to druga ma pewne konsekwencje jeśli o niej zapomnimy.
Gdybyśmy np chcieli pisać pseudo obiektowo wykorzystując czyste C, i zapomnieli o konstruktorze statycznym a uprościli sprawę inicjalizujac zmienne współdzielone w miejscu deklaracji.

Np załóżmy ze mamy do napisania prosta klasę która ma jedna zmienna współdzielona przez wszystkie instancje oraz funkcje Create, Destroy i DoSome.

static int mod_state_variable = 10; //dla uproszczenia pomijam mutexy
typedef struct Mod_Tag
{
      int some_var;
} Mod_T;

void Mod_Creat(Mod_T *mod)
{

    mod->some_var = 0;
}

void Mod_Destroy(Mod_T *mod)
{
}

void Mod_DoSome(Mod_T *mod)
{
   if( 10 == mod_state_variable )
       mod_state_variable = 50;
   mod_state_variable++;
   mod->some_var++;
}

sekwencja
Mod_Init();
Mod_DoSome();
Mod_DoSome();
Mod_Finalize();

da wynik
mod_state_variable = 51 mod->some_var = 1 po pierwszym DoSome
mod_state_variable = 52 mod->some_var = 2 po drugim DoSome

powtórzenie sekwencji
Mod_Init();
Mod_DoSome();
Mod_DoSome();
Mod_Finalize();

da nam
mod_state_variable = 53 mod->some_var = 1 po pierwszym DoSome
mod_state_variable = 54 mod->some_var = 2 po drugim DoSome

ponieważ zmienna statyczna mod_state_variable inicjalizowana jest tylko raz.
Jeśli chcemy przywrócić pierwotny stan zmiennej współdzielonej musieli byśmy użyć coś na wzór konstruktora statycznego.

Podobnie, inicjalizacja w miejscu deklaracji nie spełni swojego zadania np w przypadku bibliotek dynamicznych które posiadają tak inicjalizowane zmienne statyczne. Dopiero odłączenie biblioteki i ponowne jej podłączenie spowoduje przeinicjalizowanie takich zmiennych.

2010/10/14

Amnezja

Czasami mam wrażenie że metodą optymalizacji zapominam co mniej istotne aspekty. Kiedyś już chyba głowiłem się nad zagadnieniem przekazywania tablic w parametrach funkcji.

Przywykłem do tego ze tablice deklarujemy w parametrach funkcji jako
fkt(int tab[])

W kodzie kolegi zobaczyłem
fkt(int tab[10])

Pierwsze skojarzenie jakie mi się nasunęło, to że ta tablica przejdzie przez stos jako kopia pamięci (40bajtow)...

Okazalo sie ze jest inaczej:
#include

struct ss {
    int field1;
    int field2;
    int tab[100];
};

void fkt(char tab[10])
{
    printf("%p\n", tab);
}

void fkt2(struct ss param)
{
    printf("%p\n", &param);
}

int main()
{
    char tab[10] = { 0, 1, 2 };
    char tab2[] = { 1, 1, 1};
    struct ss param;

    fkt(tab);
    printf("%p\n", tab);
    fkt(tab2);
    printf("%p\n", tab2);

    fkt2(param);
    printf("%p\n", &param);

    return 0;
}


Wynik:
[xzs6ts@TVBuildAlfa BWL]$ ./a
0xbfa01916
0xbfa01916
0xbfa01913
0xbfa01913
0xbfa015d0
0xbfa01778


Dlaczego przekazywanie struktur przez stos jest wykonywane jako kopia a tablic jako referencja ?
"nazwa zmiennej tablicowej jest jednoczenie wskaźnikiem do pierwszego elementu"
Z tego tez powodu w języku C nie możemy powiedzieć "przekaz tablice", bo "się po prostu nie da" :)
Za to możemy powiedzieć "przekaz strukturę" co tez kompilator czyni.

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;
}