• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Ćwiczenie z rzutowania wskaźnika

Object Storage Arubacloud
0 głosów
674 wizyt
pytanie zadane 16 września 2015 w C i C++ przez Muminek Dyskutant (8,650 p.)

Cześć, 
Mam takie ćwiczenie: 
"Mamy dwa wskaźniki. Jeden z nich jest ustawiony na obiekt o nazwie szesc. 

const int szesc = 6; 
const int *wsk_c = &szesc; 
int *wsk_norm; 
Napisz instrukcję (rzutowania), która pozwoli przepisać adres ze wskaźnika wsk_c do wskanika wsk_norm" 

Wiem, że można to zrobić na dwa sposoby rzutowaniem: 
static_cast oraz reinterpret_cast, ale niestety ile razy bym próbował to program mi się wiesza. Próbowałem różnych sposób. 
- najbardziej oczywiste wydawało mi się: 
*wsk_norm = reinterpret_cast<wsk_c*>(szesc) 
Potem 
*wsk_norm = reinterpret_cast<const int>(*wsk_c) 

*wsk_norm = static_cast<const int>(wsk_c*) // tutaj też nic. 

ale nic z tego program się wiesza. Jeszcze kilku kombinacji próbowałem ale też nic. Pojawia się błąd mniej więcej ten sam przy różnych kombinacjach: 

Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp||In function 'int main()':| 
Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp|17|error: expected type-specifier before 'wsk_c'| 
Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp|17|error: expected '>' before 'wsk_c'| 
Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp|17|error: expected '(' before 'wsk_c'| 
Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp|17|error: expected primary-expression before '>' token| 
Symfonia C++\4. Operatory - ćwiczenia\cw34.cpp|17|error: expected ')' before ';' token| 
||=== Build failed: 5 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 


Program "zbudowałem" tak: 
 

#include <iostream>

/* Rozdział 4 - Operatory. Ćwiczenie 34. Strona 113
- instrukcja rzutowania ktora pozwala przepisac adres ze wskaznika wsk_c do wskaznika wsk_norm
*/

using namespace std;

int main()
{

const int szesc = 6;
const int *wsk_c = &szesc;
    cout << "Wartosc wskaznika wsk_c: " << wsk_c << endl;
    cout << "Wartosc obiektu na ktory wskazuje wskaznik *wsk_c: " << *wsk_c << endl;
int *wsk_norm;
    *wsk_norm = reinterpret_cast <wsk_c*>(szesc);
//    *wsk_norm = static_cast<const int>(wsk_c*);

cout << "\t RZUTOWANIE" << endl;
    cout << "Wartosc wskaznika wsk_norm: " << wsk_norm << endl;
    cout << "Wartosc obiektu na ktory wskazuje wskaznik *wsk_norm: " << *wsk_norm << endl;

return 0;
}

 

Ktoś mnie może nakierować? :)

1 odpowiedź

+3 głosów
odpowiedź 16 września 2015 przez Sebastian Fojcik Nałogowiec (43,020 p.)
wybrane 16 września 2015 przez Muminek
 
Najlepsza

Troszke źle kombinujesz. Pozwój, że skomentuję Twoje 2 "sposoby".

1. - najbardziej oczywiste wydawało mi się:  
*wsk_norm = reinterpret_cast<wsk_c*>(szesc)  

reinterpret_cast rzutuje wskaźnik na inny typ wskaźnika. Powyższy przykład jest w ogóle źle zapisany. Tak się rzutuje za pomocą reinterpret_cast<> (przykład)
 

int n = 5;
int * wsk_int = &n;
short int * wsk_sint = reinterpret_cast< short int* >( wsk_int );

Czytamy: przypisz wskaźnikowi typu short int adres, który posiada wskaźnik typu int i aby to przypisanie się udało, zaufaj mi drogi kompilatorze i potraktuj wsk_int jako wskaźnik na short int. W efekcie kompilator myśli, że po obu stronach znaku = stoją wskaźniki tego samego typu. W Twoim przypadku reinterpret jest niepotrzebny.

2. *wsk_norm = reinterpret_cast<const int>(*wsk_c) 
*wsk_norm = static_cast<const int>(wsk_c*) // tutaj też nic. 

I znowu źle użyty operator rzutowania. Niech odpowiedzią będzie poniższy kod, który działa tak jak chciałeś, aby działał Twój program.

#include <iostream>

using namespace std;

int main()
{
	const int szesc = 6;
	const int *wsk_c = &szesc;
	int * wsk_norm;

	wsk_norm = const_cast<int*>(wsk_c);

	cout << *wsk_norm;

	return 0;
}

Komentarz do linijki: 

wsk_norm = const_cast<int*>(wsk_c);

Przypisz do wsk_norm wartość wskaźnika wsk_c. Wiem drogi kompilatorze, że wsk_c pokazuje na const, a ja próbuję przypisać jej adres wskaźnikowi, który nie gwarantuje, że nie zmieni jej wartości. Dlatego proszę cię kompilatorze, potraktuj wsk_c jak wskaźnik na zwykły int <int*> i daj mi spokój ;-)
Wobec czego kompilator myśli, że po obu stronach znaku = stoją zwykłe wskaźniki typu int. Dlatego takie przypisanie się może udać.

Oczywiście nie muszę chyba dodawać, że korzystanie z tej sztuczki, aby  zmieniać wartości stałych, to programistyczny grzech niewybaczalny :P

Mam nadzieję, że pomogłem. Pozdrawiam :-)

komentarz 16 września 2015 przez Sebastian Fojcik Nałogowiec (43,020 p.)

Przegladając kod któy wysłałeś znalazłem jeszcze jeden błąd.

int *wsk_norm;
*wsk_norm = reinterpret_cast <wsk_c*>(szesc);

Pomijam to, co wpisałeś wewnątrz <...>, bo już wyjaśniłem co powinno tam być.
Ale dlaczego w drugiej linijce przy *wsk_norm postawiłeś gwiazdkę?
Jak chcesz aby jeden wskaźnik pokazywał na to samo co drugi, to jest zwyczajnie przyrównujesz:

int * wsk_1;
int * wsk_2;

wsk_1 = wsk_2;

Napisanie:

*wsk_1 = wsk_2;

sprawi, to na co pokazuje wsk_1 będzie miało wpisany adres przechowywany przez wsk_2.
A to chyba efekt nieporządany :-)

komentarz 16 września 2015 przez Muminek Dyskutant (8,650 p.)

Dzięki serdeczne Kolego :) nie mogłem tego zrozumieć bo uparłem się na operator reinterpret_cast... W każdym razie, obszerne wyjaśnienie. Zdecydowanie mi pomogło. Nie wiem dlaczego też zignorowałem przedrostek const i próbowałem użyć static_cast skoro w teorii wiem, że musi być const_cast, ale żeby z teorii zrobiła się praktyka trzeba pisać, pisać pisać... :)

Kto szuka nie błądzi, kto pyta ten wie :)

komentarz 17 września 2015 przez Sebastian Fojcik Nałogowiec (43,020 p.)

Domyśliłem się, że tam gdzie static miało być const. Choć bardziej skupiłem się na tym co wpisałeś w ostre nawiasy <...>. Widzę, że czytasz Symofnię C++. Bardzo dobry wybór, ale przeczytaj jeszcze raz na spokojnie o trzech operatorach rzutowania, które poznałeś. (dynamic_cast<> przyda Ci się dopiero jak ogarniesz polimorfizm na 100%)
static_cast<...> rzutuje typ na inny
reinterpret_cast<...> rzutuje typ wskaźnika na inny
const_cast<...> pozwala zignorować przydomek const (lub go nadać)
 Tam w Symfonii jest nawet pokazany przykład jak rzutować typ wskaźnika na inny, przy jednoczesnym zignorowaniu const. Wtedy robi się kombo dwóch operatorów, jeden w drugim :P. Aby to dobrze ogarnąć, jak sam napisałeś, trzeba pisać, pisać, pisać.

Napiszę Ci szczerze, że operatora const_cast<> użyłem drugi raz w życiu. Pierwszy jak go poznałem 1,5 roku temu i drugi dzisiaj, jak Tobie napisałem kod. Programista powinien jednak potrafić zastosować wszystkie :-)

Bardzo podoba mi się ta sentencja:
Kto szuka nie błądzi, kto pyta ten wie 

Używałem bardzo podobnej, ale Twoja jest o niebo lepsza. Pozwolisz, że będę z niej korzystał od teraz :-D

Podobne pytania

0 głosów
1 odpowiedź 282 wizyt
pytanie zadane 29 kwietnia 2018 w C# przez DODO Bywalec (2,950 p.)
0 głosów
1 odpowiedź 212 wizyt
pytanie zadane 14 kwietnia 2018 w C# przez logus Nowicjusz (120 p.)
0 głosów
3 odpowiedzi 725 wizyt
pytanie zadane 4 października 2017 w C i C++ przez Kamil Początkujący (430 p.)

92,566 zapytań

141,420 odpowiedzi

319,615 komentarzy

61,952 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...