Zwracanie referencji w C/Struktury

0

Hej!
Mam mały problem z zadaniem. Ma być funkcja która przyjmuje jako argumenty referencje do typu struktury. Funkcja ma sprawdzać pewne rzeczy i- zwracać referencję do pierwszego obiektu albo NULL. Pytanie i problem jest takie- jak zwrócić NULL'a? No i jak będzie wygladała deklaracja i definicja?

Struktura& foo(Struktura& obj1, Struktura& obj2)
czy
Struktura foo(Struktura& obj1, Struktura& obj2)?
Mnie się wydaje, że ta druga opcja, bo skoro przyjmujemy referencję to możemy normalnie zwrócić obj1 w returnie jeżeli zajdą te odpowiedni warunki.
Ale w przeciwnym wypadku co? Jakim cudem można zwrócić NULL'a skoro trzeba mieć w returnie l-wartość, a null jest p-wartoscia?

4

W C nie ma czegoś takiego jak referencje.

Jeżeli taka jest treść zadania to pewnie wykładowca cierpi na częsty dosyć syndrom mieszania C z C++.

0

Wiem, ale zadanie to zadanie... oficjalnie to jest C, ale to ma być "przechodzenie w C++". Więc uznajmy, że takie zadanie jest. Nie rozumiem tylko jakim cudem zwrócić NULL'a?

3

coś ci się chyba pomieszało i miało być na wskaźnikach. możesz spokojnie zwrócić wskaźnik o wartości NULL.

0
struct test* foo(const struct test* obj1, const struct test* obj2);

...i śmiało możesz zwrócić NULL.

0

Stwórz funkcję foo. Jako argumenty przyjmuje ona przez referencje
dwie zmienne typu STRUKTURA, a następnie sprawdza ... Jeżeli tak, funkcja zwraca referencję do większego obiektu. Jeśli nie, zwraca NULL.

Nie pomieszało mi się... gdyby to było na wskaźnikach to bym nie zadawał pytania. To jest zadanie, uciąłem to co niepotrzebne.

1

tylko wskaźniki mogą przyjmować null, więc zadanie jest błędne

4

Nie możesz tak zrobić!

Nie da się zwrócić nullptr jako test& jeżeli test to 'struct test'.
Tak kod zwróci błąd kompilatora:

test& foo(test& obj1, test& obj2){
    if(obj1.value > obj2.value) return obj1;
    else if(obj1.value < obj2.value) return obj2;
    return nullptr;
}

Ale taki już nie:

#include<iostream>
using namespace std;

struct test{
    int value;
    test(int val):value(val){}
};

const test* foo(const test& obj1, const test& obj2){
    if(obj1.value > obj2.value) return &obj1;
    else if(obj1.value < obj2.value) return &obj2;
    return nullptr;
}

void print(const test* obj){
    if(obj) cout << obj->value << endl;
}

int main(){
    test obj1(10);
    test obj2(10);

    print(foo(obj1,obj2));
    return 0;
}
3

Kiedy ćwiczenia z C prowadzi javoviec to wszystkie wskaźniki nazywa referencja - może to jest klucz.

2

Istnieje też szansa, że koleś po prostu podpuszcza i specjalnie każe zrobić coś czego się nie da. Więc olewając sprawę zwracania nulla definicja powinna być test& foo(test&, test&)?

0

Dzięki wielkie, można zamknąć! :)

1

@lukasson daj w ogóle znać o co temu ćwiczeniowcowi chodzilo jak już zaliczysz. Tak z ciekawości.

PS: Jeżeli w ogóle się tutaj jeszcze u nas pojawisz :-)

0

Użycie null-referencji to UB w C++, więc kompilator może - i faktycznie tak robi - zadecydować, że się to nigdy nie zdarzy i pominąć takie sprawdzenie.

http://goo.gl/b5zvnv

0

W zadaniu jest błąd, chodziło o wskaźnik, a nie referencję.
Referencję nullową można zwrócić, ale nikt tak nie robi.

Referencja to taki wskaźnik, który jak wspomniano wyżej generuje UB dla kodu który kompilator potrafi dogłębnie przetestować.
Jeśli nie potrafi, to spokojnie może przechowywać nullptr.
Taki "urok" C++.

Jak zrobić i sprawdzić bezpiecznie referencję z wartością nullptr (anty-przykład):
http://www.foundbit.com/en/resources/languages/cpp/expert/articles/cpp-avoid-null.html

0

???

/*
 Stwórz funkcję foo.
 Jako argumenty przyjmuje ona przez referencje
 dwie zmienne typu STRUKTURA,
 a następnie sprawdza ...
 Jeżeli tak, funkcja zwraca referencję do większego obiektu.
 Jeśli nie, zwraca NULL.
*/
#include <iostream>
using namespace std;

typedef struct{
	int a;
} STRUKTURA;

STRUKTURA& foo(STRUKTURA& obj1, STRUKTURA& obj2){
	if(obj1.a == obj2.a)
		return *((STRUKTURA*)NULL);
	
	return obj1.a > obj2.a ? obj1 : obj2;
}

int main(){
	STRUKTURA s1, s2;
	
	cout << "addr s1 :" << &s1 << endl;
	cout << "addr s2 :" << &s2 << endl;
	
	s1.a = 1;
	s2.a = 2;
	cout << "test 1, 2: " << &foo(s1, s2) << endl;
	
	
	s1.a = 2;
	s2.a = 1;
	cout << "test 2, 1: " << &foo(s1, s2) << endl;
	
	s1.a = 3;
	s2.a = 3;
	cout << "test 3, 3: " << &foo(s1, s2) << endl;
	
	return 0;
}
0

Tak włączona, optymalizacja psuje motyw ;)

0

Ta, trochę inne jest rozumienie referencji. Po prostu... parametr przekazany przez referencję to nie deklaracja i definicja ze znakiem &, tylko wywołanie funkcji przez znak &. Czyli tak naprawdę - przekazanie przez referencję to przekazanie przez wskaźnik, a przekazanie przez wartość to normalne odpalenie funkcji... No tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1