-
51. Data: 2014-01-15 10:20:37
Temat: Re: pryszcze...
Od: "inny punkt siedzenia..." <N...@g...pl>
a czy mógłbyś coś ciekawego napisac jeszcze o wskaźnikach na wskaźnik?
-
52. Data: 2014-01-15 11:19:19
Temat: Re: pryszcze...
Od: g...@g...com
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
-
53. Data: 2014-01-15 11:48:15
Temat: Re: pryszcze...
Od: firr <p...@g...com>
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?
wskazniki-tablice to w c dosyc gleboki koncept,
w c czesciowo wskaznik 'na poczatek tablicy'
utozsamia sie z tablicą (zwyczajowo),
ostatnio mysle ze jest to bład, tablica to
jest obszar z poczatkiem i końcem (cos jak
w przykladzie z 'bytes' omawianym ostatnio na pl.c.l.c) innymi slowy jak jest taki
cos
char tab[] = "cośtam cośtam";
to identyfikator tab powinien sie 'składać'
z dwu wskaznikow albo ze wskaznika na poczatek i rozmiaru (trudno sie zdecydowac)
serio chyba nalezaloby to przerobic w c
9co wiecj mozna wtedy pomuslec o alternatywnej skladni dla indeksowania na przyklad z
zawijaniem
tab[-1] dawałoby ostatni element itp
(c2)
-
54. Data: 2014-01-15 12:05:10
Temat: Re: pryszcze...
Od: firr <p...@g...com>
W dniu środa, 15 stycznia 2014 11:48:15 UTC+1 użytkownik firr napisał:
> 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?
>
>
>
> wskazniki-tablice to w c dosyc gleboki koncept,
>
>
>
> w c czesciowo wskaznik 'na poczatek tablicy'
>
> utozsamia sie z tablicą (zwyczajowo),
>
> ostatnio mysle ze jest to bład, tablica to
>
> jest obszar z poczatkiem i końcem (cos jak
>
> w przykladzie z 'bytes' omawianym ostatnio na pl.c.l.c) innymi slowy jak jest taki
cos
>
>
>
> char tab[] = "cośtam cośtam";
>
>
>
> to identyfikator tab powinien sie 'składać'
>
> z dwu wskaznikow albo ze wskaznika na poczatek i rozmiaru (trudno sie zdecydowac)
>
>
chyba zeby informacje o rozmiarze trzymac jako czesc typu, innymi slowy tab jest typu
'tablica 12 charow'
a przekazywac wystarczy zwykle adres poczatku; to pozwaliloby tez wywalic z c stringi
konczace sie zerem ktore mz raczej powinny wlasnie zostac wywalone i zastapione
takimi wlasnie tablicami
-
55. Data: 2014-01-15 14:01:40
Temat: Re: pryszcze...
Od: Adam Klobukowski <a...@g...com>
On Wednesday, 15 January 2014 10:03:05 UTC+1, Maciej Sobczak wrote:
> W dniu środa, 15 stycznia 2014 08:03:30 UTC+1 użytkownik Paweł Kierski napisał:
>
> > Statyczna kontrola typ�w daje du�e pole do popisu dla optymalizacji
> > przez kompilator. Vide - rozwijanie szablon�w w C++.
>
> Rozwijanie szablonów nie za bardzo ma związek z systemem typów. Raczej z brutalnym
inline'owaniem a to można robić również z typami dynamicznymi.
>
> Natomiast statyczny system typów jest użyteczny chociażby przez sam fakt, że można
z góry wygenerować odpowiednie instrukcje asemblera, które będą na pewno dobre do
wykonania jakiejść operacji. Np. dodawanie zmiennych, o których z góry wiadomo, że są
32-bitowymi liczbami całkowitymi, można zwykle zrobić jedną instrukcją zamiast
tysiącem instrukcji, które najpierw pracowicie sprawdzają, jakie typy mają te zmienne
i czy przypadkiem nie chodzi o sklejanie napisów.
>
> Na dalszym poziomie statyczny system typów można wykorzystać do *eliminacji*
operacji, nawet takich, które są wymagane przez język. Np. jeśli w danym języku jest
sprawdzanie zakresów przy indeksowaniu tablic, to statyczny system typów cząsem
pozwala kompilatorowi tego sprawdzenia nie robić. Podobnie z innymi sytuacjami
brzegowymi, jak dzielenie przez 0, itp.
Nowoczesne silniki JS działające w trybie JIT generują kod funkcji JS dla zadanych
typów wejściowych, i jeśli typ danych wejściowych sie zmienia, generują nową wersję
kodu. Czyli działa to trochę jak templatowanie kodu w C++ czy dżeneriksy w Javie.
Dodatkowo, kod ten specjalnie nie jest generowany od razu optymalnie - silnik
analizuje kolejne przebiegi wywołania funkcji i optymalizuje ją z czasem. Dzięki
temu, potencjalnie może wygenerować lepszy kod niż kompilator języka statycznego
który ma skończony czas na wygenerowanie kodu i nie jest w stanie poznać
harakterystyki jego użycia.
> Problem z językiem C polega na tym, że no niby ma statyczny system typów, ale tak
kiepski, że nie da się go na tym "dalszym poziomie" wykorzystać ani do optymalizacji
ani do wykrywania potencjalnych błędów.
C ma system typów skrojony do swoich zastosowań, a przypomnijmy - było to pisanie
jąder systemów operacyjnych. Dlatego typy w C są maksymalnie zbliżone do sprzętu.
Przez długi czas nie było wystarczająco dobrych języków/kompilatorów do pisania
innych programów, dlatego wykorzystywano do tego C. Dziś takie języki/kompilatory
istnieją i faktycznie C ogranicza się do pisania jąder i/lub bibliotek
niskopoziomowych.
> > Tak na marginesie - nie spodziewa�em si� n-tej dyskusji o wy�szo�ci
> > �wi�t Bo�ego Narodzenia nad �wi�tami Wielkiej Nocy.
>
> Dlaczego? Podobnie jak te swięta, tego typu dyskusje są zjawiskiem okresowym. :-D
Podsumowując: statyczne jak i dynamiczne systemy typów mają swoje zady i walety.
Porównywanie ich bez podawania konkretnych zastosowań nie ma sensu - inaczej będziesz
pisał pakiet biurowy, inaczej sterownik niskopoziomowy a jeszcze inaczej firmware
urządzenia.
AdamK
-
56. Data: 2014-01-15 14:22:11
Temat: Re: pryszcze...
Od: g...@g...com
W dniu środa, 15 stycznia 2014 14:01:40 UTC+1 użytkownik Adam Klobukowski napisał:
> Podsumowując: statyczne jak i dynamiczne systemy typów
> mają swoje zady i walety. Porównywanie ich bez podawania
> konkretnych zastosowań nie ma sensu - inaczej będziesz
> pisał pakiet biurowy, inaczej sterownik niskopoziomowy
> a jeszcze inaczej firmware urządzenia.
Wydaje mi sie, ze taki poglad jest dosc powszechny,
ale nie do konca sluszny. Rzecz w tym, ze w istocie
rola systemu typow nie jest optymalizacja, tylko
zwiekszanie niezawodnosci oprogramowania.
Jezyk C jest pod tym wzgledem rzeczywiscie dosc
specyficzny, poniewaz system typow dodatkowo daje
pewna kontrole nad tym, w jaki sposob dane beda
zorganiozwane w pamieci. Ale to jest tylko przygodna
cecha tego akurat systemu typow, i wydaje mi sie,
ze ta cecha czesto wprowadza ludzi w blad dotyczacy
ogolnej roli systemow typow.
Dlatego dodawnie anotacji z typami w jezykach
typowanych dynamicznie, oraz narzedzi walidujacych
zgodnosc uzytych typow dla takich jezykow ma jak
najbardziej sens, i mam nadzieje, ze bedzie jak
najwiecej takich narzedzi (albo: ze tworcy jezykow
dynamicznych zaczna myslec, ze jak nie ich jezyki
nie maja statycznych type-checkerow, to troche
siara)
-
57. Data: 2014-01-15 14:49:06
Temat: Re: pryszcze...
Od: Adam Klobukowski <a...@g...com>
On Wednesday, 15 January 2014 14:22:11 UTC+1, g...@g...com wrote:
> W dniu środa, 15 stycznia 2014 14:01:40 UTC+1 użytkownik Adam Klobukowski napisał:
> > Podsumowując: statyczne jak i dynamiczne systemy typów
> > mają swoje zady i walety. Porównywanie ich bez podawania
> > konkretnych zastosowań nie ma sensu - inaczej będziesz
> > pisał pakiet biurowy, inaczej sterownik niskopoziomowy
> > a jeszcze inaczej firmware urządzenia.
>
> Wydaje mi sie, ze taki poglad jest dosc powszechny,
> ale nie do konca sluszny. Rzecz w tym, ze w istocie
> rola systemu typow nie jest optymalizacja, tylko
> zwiekszanie niezawodnosci oprogramowania.
To bardziej ułatwienie koncepcyjne. Ludziom łatwiej myśleć w kategoriach napisów,
liczb czy zbiorów niż bitów i bajtów. Języki wuższego poziomu i dynamiczne typowanie
przerzucją koszt myślenia o reprezentacji binarnej danych z programisty na
kompilator/VM. Dzięki temu programista może skupić się na logice biznesowej za którą
płaci klient ;)
> Jezyk C jest pod tym wzgledem rzeczywiscie dosc
> specyficzny, poniewaz system typow dodatkowo daje
> pewna kontrole nad tym, w jaki sposob dane beda
> zorganiozwane w pamieci. Ale to jest tylko przygodna
> cecha tego akurat systemu typow, i wydaje mi sie,
> ze ta cecha czesto wprowadza ludzi w blad dotyczacy
> ogolnej roli systemow typow.
C pozwala na pełną kontrolę nad organizacją danych w pamięci. Oczywiście,
zależnie od implementacji. To jest niezbędne jak chcesz współpracować ze
sprzętem.
> Dlatego dodawnie anotacji z typami w jezykach
> typowanych dynamicznie, oraz narzedzi walidujacych
> zgodnosc uzytych typow dla takich jezykow ma jak
> najbardziej sens, i mam nadzieje, ze bedzie jak
> najwiecej takich narzedzi (albo: ze tworcy jezykow
> dynamicznych zaczna myslec, ze jak nie ich jezyki
> nie maja statycznych type-checkerow, to troche
> siara)
To jest trochę gonienie własnego ogona. Z jednej strony dajemy programistom
dynamiczne typy i mniej zmartwień, a z drugiej dodatkowe zmartwienia jak im się coś
pogmatwa. No ale nie po to na te studia szliśmy żeby było łatwo.
AdamK
-
58. Data: 2014-01-15 15:09:42
Temat: Re: pryszcze...
Od: Maciej Sobczak <s...@g...com>
W dniu środa, 15 stycznia 2014 14:01:40 UTC+1 użytkownik Adam Klobukowski napisał:
> Nowoczesne silniki JS działające w trybie JIT [...]
> Dzięki temu, potencjalnie może wygenerować lepszy kod niż kompilator języka
statycznego który ma skończony czas na wygenerowanie kodu i nie jest w stanie poznać
harakterystyki jego użycia.
Etam. Po pierwsze, nie jest prawdą, że kompilator ma skończony czas na wygenerowanie
kodu. Nikt mu tego czasu nie ogranicza, może sobie kompilować ile tylko chce. To
właśnie JIT musi działać w (powiedzmy) "czasie rzczywistym" i nie może pozwolić sobie
na spędzanie dowolnie długiego czasu na czymkolwiek, bo jest to aktywność dodatkowa w
stosunku do tego, co chciał programista.
Po drugie, nie jest prawdą, że JIT może analizować dane w run-time do podjęcia takich
decyzji (albo lepszych), jak kompilator, bo dane w run-time mogą się zmienić. Np.
skoro przez ostatnią godzinę indeks tablicy mieścił się w dozwolonym zakresie, to co,
JIT może podjąć decyzję, że nie trzeba już sprawdzać tego zakresu? Nie może takiej
decyzji podjąć. Natomiast w systemie statycznym można tak zrobić i we wspomnianej tu
Adzie jest to zupełnie rutynowe działanie.
Te dwie sprawy to dwa główne mity nt. JIT.
JIT ma zalety, ale nie te dwie.
--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com
-
59. Data: 2014-01-15 15:17:30
Temat: Re: pryszcze...
Od: Maciej Sobczak <s...@g...com>
W dniu środa, 15 stycznia 2014 14:49:06 UTC+1 użytkownik Adam Klobukowski napisał:
> To bardziej ułatwienie koncepcyjne. Ludziom łatwiej myśleć w kategoriach napisów,
liczb czy zbiorów niż bitów i bajtów. Języki wuższego poziomu i dynamiczne typowanie
przerzucją koszt myślenia o reprezentacji binarnej danych z programisty na
kompilator/VM.
Dynamiczne typowanie nie ma związku z myśleniem o reprezentacji binarnej. Jak
najbardziej można mieć niskopoziomowy język z dynamicznym typowaniem albo
wysokopoziomowy ze statycznym.
Natomiast dynamiczne typowanie jest częstą cechą języków, które z założenia działają
w jakimś środowisku zarządzanym (interpreter, VM). Dzięki temu łatwiej jest zrobić
kompilator takiego języka - bo w szczególności można go w ogóle nie robić.
> Dzięki temu programista może skupić się na logice biznesowej za którą płaci klient
;)
Zależy od klienta i od jego biznesu. Niektórzy płacą za logikę w której pojawiają się
określenia typu "czas", "pamięć", "rozkład danych", itd. To nie zawsze są rzeczy,
które zaciemniają obraz, czasami to jest właśnie centrum obrazu.
--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com
-
60. Data: 2014-01-15 16:24:59
Temat: Re: pryszcze...
Od: A.L. <a...@a...com>
On Wed, 15 Jan 2014 08:03:30 +0100, Paweł Kierski <n...@p...net>
wrote:
>W dniu 2014-01-14 21:48, g...@g...com pisze:
>[...]
>> Po trzecie statyczny system
>> typow na pewno nie jest sposobem na
>> zwiekszenie wydajnosci czy zmniejszenie
>> zajetosci pamieci, tylko na zwiekszenie
>> niezawodnosci oprogramowania przez unikniecie
>> pewnej klasy bledow.
>
>Statyczna kontrola typów daje duże pole do popisu dla optymalizacji
>przez kompilator. Vide - rozwijanie szablonów w C++.
Szablony w C++ to zwykla makro. Mic nei ma wspolnego z systemem typow
A.L.