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
2011/01/30
ARM w pigułce
Kto chce się szybko i w skrócie zapoznać z asemblerem i kodem startowym dla ARM polecam:
http://www.b ravegnu.org/gnu-epro g/index.html
Dla mnie najciekawsze było streszczenie architektury rozkazów ARM:
http://www.brave gnu.org/gnu-eprog/ar m-iset.html
Do tego polecam
http://www.stm32.eu/index.php?option=com_content&view=category&layout=blog&id=35&Itemid=57
http://www.b
Dla mnie najciekawsze było streszczenie architektury rozkazów ARM:
http://www.brave
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.
- 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", ¶m);
}
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", ¶m);
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.
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", ¶m);
}
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", ¶m);
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;
}
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;
}
2010/08/25
Rozmowa kwalifikacyjna
Pytania z serii "rozmowa kwalifikacyjna"
jaka jest różnica między poniższymi deklaracjami tab
int function(int tab[])
{
...
}
struct SomeStruct_T
{
int tab[];
};
Odpowiedz:
deklaracja w parametrze funkcji nie alokuje pamięci na stosie, jest ona równoważna z deklaracja function(int *tab)
deklaracja w strukturze również nie alokuje pamięci ale dostęp do pola tab będzie się odbywał poprzez referencje do pamięci znajdującej sie bezpośrednio za struktura, w ten sposób można tworzyć np tablice o zmiennej długości pamiętając o alokowaniu odpowiedniej ilosci pamięci, np na stercie.
jaka jest roznica miedzy poniższmi deklaracjami field
struct SomeStruct
{
union field
{
int a;
};
}
struct SomeStruct
{
union
{
int a;
} field;
}
Odpowiedz:
pierwsza to czysta deklaracja unii o nazwie field, struktura nie allokuje przestrzeni na zadne pole
druga to deklaracja pola field o typie unii anonimowej, struktura będzie miała rozmiar sizeof(int)
jaka jest różnica między poniższymi deklaracjami tab
int function(int tab[])
{
...
}
struct SomeStruct_T
{
int tab[];
};
Odpowiedz:
deklaracja w parametrze funkcji nie alokuje pamięci na stosie, jest ona równoważna z deklaracja function(int *tab)
deklaracja w strukturze również nie alokuje pamięci ale dostęp do pola tab będzie się odbywał poprzez referencje do pamięci znajdującej sie bezpośrednio za struktura, w ten sposób można tworzyć np tablice o zmiennej długości pamiętając o alokowaniu odpowiedniej ilosci pamięci, np na stercie.
jaka jest roznica miedzy poniższmi deklaracjami field
struct SomeStruct
{
union field
{
int a;
};
}
struct SomeStruct
{
union
{
int a;
} field;
}
Odpowiedz:
pierwsza to czysta deklaracja unii o nazwie field, struktura nie allokuje przestrzeni na zadne pole
druga to deklaracja pola field o typie unii anonimowej, struktura będzie miała rozmiar sizeof(int)
2010/07/06
Dlaczego zamkniete oprogramowanie jest passé
Oto odpowiedz dlaczego producenci oprogramowania powinni gwarantować bezpieczeństwo swoich produktów. Kto wie ... może kiedyś :)
http://www.heise-online.pl/newsticker/news/item/Luki-Microsoftu-raz-Full-Disclosure-a-raz-Null-Disclosure-1033694.html
http://www.heise-online.pl/newsticker/news/item/Luki-Microsoftu-raz-Full-Disclosure-a-raz-Null-Disclosure-1033694.html
Subskrybuj:
Posty (Atom)