konto usunięte

Temat: Rynek IT z C C++

Piotr Pszczolkowski:
No to w takim razie wyrazenia regularne sa czescia C i tym samym C++ od
zawsze. Patrz regexp.h

Nie, bo regexp.h nie nalezy do biblioteki standardowej jezyka o ktorej wspominal Maciej.
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Rynek IT z C C++

Piotr Likus:
Co do NULL:

Do niedawna nie wiedziałem, że NULL to takie wielkie halo.
Ale ponoć dopiero nullptr ma być wskaźnikiem "do niczego" a NULL często jest definiowany jako zero(int):


#define NULL 0


tak więc może to i zgodnie ze wskaźnikami, ale na pewno nie z referencjami.

Referencje są dla mnie lepsze, bo wymuszają lepszą semantykę zarządzania pamięcią (samo się gdzieś tam zwalnia). W przypadku wskaźników nigdy nie wiadomo.


Typowe nierozumienie wskaźników : )
Wskaźnik to adres w pamięci. Adres 0 znaczy "brak adresu".
Referencja niczym nie zarządza, niczego nie zwalnia i nie ma żadnej semantyki. Referencja jest niczym jak tylko wskaźnikiem przed którym nie trzeba pisać *.

void DoSmth(int& iParam)
{
iParam = 0;
}

#define iParam (*piParam)
void DoSmth(int* piParam)
{
iParam = 0;
}


Nie ma żadnej różnicy : )
Referencja a wskaźnik różnią się jedynie zapisem i niczym więcej.

konto usunięte

Temat: Rynek IT z C C++

To żeś pojechał z tym #define :)
Mam nadzieje, że nie robisz takich u siebie w kodzie? ;)

Wielkie halo robi się w kompilatorze, nie w zrozumieniu. Ponoć jakieś brzydkie warningi, błędy generuje przy próbie użycia w niektórych przypadkach.

http://www.devx.com/cplus/10MinuteSolution/35167/0/page/2
http://www.informit.com/guides/content.aspx?g=cplusplu...

Dla mnie to jazda - null powinien być nullem a nie int'em.
Zero używane jako pusty adres? Ponoć to standard (o przepraszam, "konwencja") w C++, ale jakoś do mnie nie trafia.

Nowe słowo kluczowe ma nawet swoją stronę www:
http://nullptr.org/Piotr Likus edytował(a) ten post dnia 02.10.08 o godzinie 11:04
Mateusz Berezecki

Mateusz Berezecki no fluff, just stuff

Temat: Rynek IT z C C++

Ja tylko dodam, ze adres 0 to tez niestety jest adres :)
Powszechnie panujace niezrozumienie, powoduje powstawanie miedzy innymi takich oto publikacji:

http://www.juniper.net/solutions/literature/white_pape...
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Rynek IT z C C++

Tomasz Krzos:
Szymon Kubisiak:
Jasne, tylko złośliwy idiota podaje NULLa do funkcji przyjmującej referencje.


void f(int &i)
{
}

int main()
{
f(NULL);
return 0;
}


Taki kod u mnie w ogole sie nie kompiluje(VC++ 2003 Std). Mam wiec watpliwosci czy wg. standardu mozna przekazac NULLa do funkcji przyjmujacej referencje. Bede musial kiedys o tym poczytac.

Ech...
To co napisałeś nie ma prawa się skompilować.
Napisałeś:
f(0);
Nawet się nie otarłeś o adres czegokolwiek. (Chociaż zadziałało by z const ref)

Jak podać NULLa do referencji? A tak:

f( *((int*)NULL) );

Krok po kroku:

typedef int *LPINT;
LPINT piSmth; //wskaznik na inta
piSmth = NULL;
f(*pSmth);


Sam fakt, ze ktos przekazuje adres do funkcji nie oznacza, ze chce cos modyfikowac, wiec dalej nie bedziesz wiedzial co dzieje sie w przypadku drugiej konstrukcji.

Oczywiście że nie wiadomo czy zostało zmodyfikowane. Nawet funkcja która ma coś modyfikować może w czasie wykonywania zadecydować żeby jednak nie zmieniać. Chodzi mi o odrzucenie możliwości zmiany od razu, analizując kod linia po linii.

Na marginesie dobra rada: z własnego doświadczenia wiem że nie należy myśleć o pointerach jako o "wskaźniku na typ":
int *piCostam;// źle

Myślcie jako o "typie 'wskaźnik na'"
int* piCostam;// dobrze

Najczyściej mieć odpowiednie typedefy, jak w WinDef.h
typedef int *LPINT;

I traktować wskaźniki jako obiekty typu LPINT. To naprawdę wiele upraszcza.

konto usunięte

Temat: Rynek IT z C C++

Szymon Kubisiak:
Ech...
To co napisałeś nie ma prawa się skompilować.

I o to chodzi :)
(Chociaż zadziałało by z const ref)

ale wtedy by sie nie wysypalo :)
Jak podać NULLa do referencji? A tak:

f( *((int*)NULL) );

Nie podajesz NULLa(zerowego adresu). Podajesz adres, ktory jest pod adresem zerowym.

Co wiecej: biorac pod uwage powyzszy przyklad, mozna wyjsc z zalozenia, ze wkazniki to jeszcze wieksze zlo. Jezeli mam sie bawic w rzutowania, to rownie dobrze moge napsiac:


void f(int* i)
{
if (i == NULL)
*i = 0;
}

int main()
{
f((int*)1);
return 0;
}


Efekt bedzie podobny. Roznica polega na tym, ze mniej sie napisze w drugim przypadku. Innymi slowy: jak ktos bedzie chcial na sile wszystko zepsuc, to i tak zepsuje i wskaznik Cie tu nie uratuje - wrecz przeciwnie.
Na marginesie dobra rada: z własnego doświadczenia wiem że nie należy myśleć o pointerach jako o "wskaźniku na typ":
int *piCostam;// źle

Myślcie jako o "typie 'wskaźnik na'"
int* piCostam;// dobrze

No ok :)Tomasz Krzos edytował(a) ten post dnia 02.10.08 o godzinie 11:48
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Rynek IT z C C++

Tomasz Krzos:

Nie podajesz NULLa(zerowego adresu). Podajesz adres, ktory jest pod adresem zerowym.

"Adres pod adresem zerowym" ?

Referencja JEST adresem. Tyle że go nie widzisz. Patrz na mój przykład z #define. Kompilator robi dokładnie to samo kiedy używasz referencji.

Co wiecej: biorac pod uwage powyzszy przyklad, mozna wyjsc z zalozenia, ze wkazniki to jeszcze wieksze zlo. Jezeli mam sie bawic w rzutowania, to rownie dobrze moge napsiac:


void f(int* i)
{
if (i == NULL)
*i = 0;
}

int main()
{
f((int*)1);
return 0;
}


Efekt bedzie podobny. Roznica polega na tym, ze mniej sie napisze w drugim przypadku. Innymi slowy: jak ktos bedzie chcial na sile wszystko zepsuc, to i tak zepsuje i wskaznik Cie tu nie uratuje - wrecz przeciwnie.

Teraz to już naciągasz i wcale nie jesteś zabawny.

Napisałem przykład jednolinijkowy jako czysto teoretyczną możliwość. Przykład drugi może być rozstrzelony po całym kodzie i jest znacznie bardziej realny (choć również ewidentnym bugiem).
To co Ty piszesz, się nie wywali, więc w czym problem? : )
Chodziło Ci chyba o
*((LPINT)NULL) = 5;
Ale teraz wkraczamy na obszar "jak wywalić program" i nie jest to ograniczone do wskaźników. Dzielenie przez zero też działa.

Wskaźnik możesz sprawdzić, referencję nie - naprawdę jest cała różnica pomiędzy nimi. Nie są nawet różnymi mechanizmami, to tylko 2 formy zapisu.

konto usunięte

Temat: Rynek IT z C C++

Szymon Kubisiak:
"Adres pod adresem zerowym" ?

Dokladnie tak. Do funkcji przekazywany jest adres, bo jak sam napisales referencja jest adresem. A wiec:
1) Masz NULLa - czyli wartosc 0.
2) Za pomoca wyrazenia *((int*)NULL) odwolujesz sie do wartosci, ktora jest zapisana w komorce pamieci o adresie zero.
3) Powyzsza wartosc przekazujesz do funkcji. Wartosc ta jest(nie liczac cudow) wartoscia rozna od zera, a wiec rozna od NULLa. Nie przekazujesz wiec NULLa.
Referencja JEST adresem.

Tu sie zgadzamy :)
Teraz to już naciągasz i wcale nie jesteś zabawny.

Oj tam, jakis nie w humorze jestes :)
Napisałem przykład jednolinijkowy jako czysto teoretyczną możliwość.

Z tego co zrozumialem, nie podoba Ci sie referenecja ze wzgledu na bezpieczenstwo. Moim zdaniem jest dokladnie na odwrot - referencja jest na ogol bardziej bezpieczna od wskaznika.

Przykład drugi może być rozstrzelony po całym
kodzie i jest znacznie bardziej realny (choć również ewidentnym bugiem).

Oczywiscie, ze to ewidenty bug, ale podobnie jest z przykladem, ktory napisales(ten z rzutowaniem).
To co Ty piszesz, się nie wywali, więc w czym problem? : )

W niczym :)
Ale teraz wkraczamy na obszar "jak wywalić program" i nie jest to ograniczone do wskaźników.

Chodzilo mi o to, ze wskazniki nie poprawiaja bezpieczenstwa.
Wskaźnik możesz sprawdzić, referencję nie

Plus dla referencji ;)
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Piotr Likus:
Dla mnie to jazda - null powinien być nullem a nie int'em.

A od kiedy NULL jest int'em?

char *my_string = NULL;

Jak to sobie wyobrażasz na platformie 32 i 64 bitowej?
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Szymon Kubisiak:
Na marginesie dobra rada: z własnego doświadczenia wiem że nie należy myśleć o pointerach jako o "wskaźniku na typ":
int *piCostam;// źle

Co tu jest źle?

W praktyce użyjesz tego jeśli funkcja modyfikuje wartość int.

my_func(&piCostam); [in/out]

Lub jeśli potrzebujesz tablicy intów.

piCostam[0] = 1;
piCostam[1] = 2;
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Tomasz Krzos:
Szymon Kubisiak:
"Adres pod adresem zerowym" ?

Dokladnie tak. Do funkcji przekazywany jest adres, bo jak sam napisales referencja jest adresem. A wiec:
1) Masz NULLa - czyli wartosc 0.

Na jakiej platformie?
Implementacja NULL'a jest jak przepis polskiego prawa. Jego interpretacja zależy od lokalnego systemu.

NULL jest po prostu pustym wskaźnikiem. Zakładanie że NULL będzie zerem w przypadku języka C jest strzałem we własna stopę.
Chodzilo mi o to, ze wskazniki nie poprawiaja bezpieczenstwa.

Ale są fundamentem języka C. Jeśli to dla Ciebie niebezpieczne, nie pisz w C ;)

konto usunięte

Temat: Rynek IT z C C++

Piotr P.:
Na jakiej platformie?
Implementacja NULL'a jest jak przepis polskiego prawa. Jego interpretacja zależy od lokalnego systemu.

Sam dokladnie nie wiem co na to standard. Byc moze jest to nie tylko zalezne od systemu ale od kompilatora.
NULL jest po prostu pustym wskaźnikiem. Zakładanie że NULL będzie zerem w przypadku języka C jest strzałem we własna stopę.

Zgoda.
Ale są fundamentem języka C. Jeśli to dla Ciebie niebezpieczne, nie pisz w C ;)

Napisalem, ze referencje sa na ogole bezpieczniejsze od wskaznikow. W C nie mam wielkiego wyboru, bo tam nie przekaze parametru przez referencje :)

konto usunięte

Temat: Rynek IT z C C++

Piotr P.:
A od kiedy NULL jest int'em?

Teoretycznie NULL nie jest intem tylko... NULLem. Ale w praktyce to juz nie jest chyba takie proste.


std::cout << typeid(NULL).name() << std::endl;


Powyzszy kod wypisze... int :) Przynajmniej pod VS 2k5. Nie chcialbym natomiast sie spierac, bo byc moze wystapila tu jakas niejawana konwersja. Nie zmienia to jednak faktu, ze powyzszy kod daje do myslenia - bynajmniej ja sie nad tym zastanawiam.
char *my_string = NULL;

Jak to sobie wyobrażasz na platformie 32 i 64 bitowej?

Nie rozumiem co chciales przez powyzszy kod pokazac :)Tomasz Krzos edytował(a) ten post dnia 02.10.08 o godzinie 14:09
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Tomasz Krzos:

std::cout << typeid(NULL).name() << std::endl;


Powyzszy kod wypisze... int :) Przynajmniej pod VS 2k5.

W GNU C++ jest inaczej :)
Czyli dobrze jest przyjąć że NULL to NULL i nie przyjmować że ma on jakis określony typ :)
char *my_string = NULL;

Jak to sobie wyobrażasz na platformie 32 i 64 bitowej?

Nie rozumiem co chciales przez powyzszy kod pokazac :)

A chciałem pokazać że nie możesz przypisac int do char.
Nawet gdybyś rzutował to na obydwu platformach przypiszesz int do wskaźnika czyli zupełnie inne rozmiary, co oczywiście zakończy się fatalnie.

konto usunięte

Temat: Rynek IT z C C++

Piotr P.:
Tomasz Krzos:
Szymon Kubisiak:
"Adres pod adresem zerowym" ?

Dokladnie tak. Do funkcji przekazywany jest adres, bo jak sam napisales referencja jest adresem. A wiec:
1) Masz NULLa - czyli wartosc 0.

Na jakiej platformie?
Implementacja NULL'a jest jak przepis polskiego prawa. Jego interpretacja zależy od lokalnego systemu.

NULL jest po prostu pustym wskaźnikiem. Zakładanie że NULL będzie zerem w przypadku języka C jest strzałem we własna stopę.
Chodzilo mi o to, ze wskazniki nie poprawiaja bezpieczenstwa.

Ale są fundamentem języka C. Jeśli to dla Ciebie niebezpieczne, nie pisz w C ;)

Wskaźniki są patogenne. Dlatego wymyślono referencje.
Dostałem wskaźnik i co dalej? Hmm, zwolnić czy nie...
Przy referencji nie ma tego wyboru.

A co do mojego NULLa to miałem na myśli to że w C++ zamiast niego stosuje się zero (0). I to jest chore. Co do wartości makra NULL to dla mnie ona może być dowolna (np. 0xfefe).
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Tomasz Krzos:
Piotr P.:
Na jakiej platformie?
Implementacja NULL'a jest jak przepis polskiego prawa. Jego interpretacja zależy od lokalnego systemu.

Sam dokladnie nie wiem co na to standard.

eehh.... zmusiłeś mnie do wstania z fotela :)

"Wskaźniki i liczby całkowite nie są wymienne. Zero jest jedynym wyjątkiem: stałą zero można przypisać wskaźnikowi, można też porównać wskaźnik ze stałą zero. Często zamiast zera używa się stałej symbolicznej NULL, by podkreślić, że chodzi o specjalną wartość wskaźnikową"

To oczywiście C.

Faktycznie można przyjąć że NULL jest intem o specjalnej wartości wskaźnikowej :)
Piotr P.

Piotr P. Software Developer

Temat: Rynek IT z C C++

Piotr Likus:
Chodzilo mi o to, ze wskazniki nie poprawiaja bezpieczenstwa.

Ale są fundamentem języka C. Jeśli to dla Ciebie niebezpieczne, nie pisz w C ;)

Wskaźniki są patogenne. Dlatego wymyślono referencje.
Dostałem wskaźnik i co dalej? Hmm, zwolnić czy nie...
Przy referencji nie ma tego wyboru.

Kwestia podejścia i właściwie udokumentowania o co chodzi.
Jeśli w dokumentacji funkcji jest wyraźnie napisane że zwraca coś co trzeba zwolnić to trzeba zwolnić. Jeśli wyraźnie napisane, że nie zwalniać to nie zwalniać. W takim przypadku mogę "traktować" wskaźnik jako referencje.
Mam na myśli C oczywiście. Wskaźnik mi nie przeszkadza tak dlugo jak długo autor jakiegoś API dba o dobrą dokumentację.
A co do mojego NULLa to miałem na myśli to że w C++ zamiast niego stosuje się zero (0). I to jest chore. Co do wartości makra NULL to dla mnie ona może być dowolna (np. 0xfefe).

Aj. Znam ludzi którzy piszą 0 zamiast FALSE i 1 zamiast TRUE.
Chore, fakt :)

konto usunięte

Temat: Rynek IT z C C++

Piotr P.:
Aj. Znam ludzi którzy piszą 0 zamiast FALSE i 1 zamiast TRUE.
Chore, fakt :)

Są całe biblioteki na tym oparte.
Co ciekawe, jest jeszcze standard:

<0 - error
0 - success
>0 - warning


i dalej


if (!status) printf("super!");


Dlatego już w C++ masz bool, true, false.
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Rynek IT z C C++

Tomasz Krzos:
Szymon Kubisiak:
"Adres pod adresem zerowym" ?

Dokladnie tak. Do funkcji przekazywany jest adres, bo jak sam napisales referencja jest adresem. A wiec:
1) Masz NULLa - czyli wartosc 0.
2) Za pomoca wyrazenia *((int*)NULL) odwolujesz sie do wartosci, ktora jest zapisana w komorce pamieci o adresie zero.
3) Powyzsza wartosc przekazujesz do funkcji. Wartosc ta jest(nie liczac cudow) wartoscia rozna od zera, a wiec rozna od NULLa. Nie przekazujesz wiec NULLa.

Nie. Przekazuję dokładnie 0. *((int*)NULL jest wartością pod adresem zero, a referencja bierze adres na to wszystko - czyli zero. Adres-zawartość-(niejawny)adres.
Nigdzie nie odwołuję się do zawartości komórki zero, to dopiero zrobi ten kto dostanie ode mnie tak spreparowaną referencję (i się wywali)

Wskaźnik możesz sprawdzić, referencję nie

Plus dla referencji ;)

Nie wiedzieć czy jest poprawna czy nie? Jak dla mnie minus.
Mateusz Berezecki

Mateusz Berezecki no fluff, just stuff

Temat: Rynek IT z C C++

Dolacze swoje 5 groszy :)

1) Do wskaznika mozna przypisac _dowolna_ liczbe
2) Referencja nie jest wskaznikiem na poziomie semantyki jezyka programowania, ale na poziomie kodu maszynowego najczesciej (nie znam innego przypadku) sa implementowane tak samo.

Prosty przyklad:


#include <iostream>

extern "C" void ref_fun(int& a)
{
}

extern "C" void ptr_fun(int *a)
{
}

int main()
{
int a = 5;
ref_fun(a);
ptr_fun(&a);
}


Do spec. funkcji dodalem parametr
extern "C"
by kod maszynowy nie mial nazw funkcji podawanych w standardzie C++ (wiec to nie zadne szarlatanstwo - ubezpieczam sie na przyszlosc)

Ponizej prezentuje kod funkcji main


main:
.LFB1430:
pushq %rbp
.LCFI4:
movq %rsp, %rbp
.LCFI5:
subq $16, %rsp
.LCFI6:
movl $5, -4(%rbp)
leaq -4(%rbp), %rdi
call ref_fun
leaq -4(%rbp), %rdi
call ptr_fun
movl $0, %eax
leave
ret


Jak widac i referencja i wskaznik sa przekazywane w identyczny sposob: "leaq -4(%rbp), %rdi".

Wskaznik jest rejestrem a co za tym idzie mozna mu wpisac dowolny adres. To czym skutkuje odwolanie sie do takiego adresu to juz zupelnie inna historia.

Referencja jest ulatwieniem na poziomie jezyka a implementowana jest niemalze zawsze (nei znam innych przypadkow) za pomoca wskaznika.

Odnosnie zalozenia ze NULL != 0 (w jezyku C) polecam ponowna edukacje lub prosze
o kontrprzyklad ;-)

Cytujac ze standardu ISO C99 (standard jezyka C http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1336.pdf sekcja 6.3.2.3)

An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant


Ogolnie polecam zapoznanie sie ze standardami w celu rozwiania watpliwosci :-)

UPDATE:

Zapomnialem dodac ze istnieja konwersje liczb 64 bitowych na 32 bitowe i odwrotnie, 32 bitowych na 64 bitowe.

W pierwszym przypadku jest to po prostu obciecie liczby, w drugmi procesory udostepniaja dwa rodzaje instrukcji, sa to instrukcje tzw. "sign extend" lub "zero extend". Dociekliwym pozostawiam to jako zadanie domowe. Ogolnie rzecz biorac rzutowanie pointera 32 bitowego na 64 jest jak najbardziej poprawne.Mateusz Berezecki edytował(a) ten post dnia 02.10.08 o godzinie 15:19

Następna dyskusja:

Co sie dzieje w Polsce (ryn...




Wyślij zaproszenie do