Powtórzenie: wskaźniki void
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 49 z 61.
void* to sposób języka C na powiedzenie: „wskaźnik na coś, ale nie powiem ci na co”. Może przechowywać adres dowolnego typu danych: int, float, struktury lub czegokolwiek innego. Dzięki temu stanowi podstawę do pisania generycznego kodu w C.
Jest jednak pewien haczyk: nie możesz bezpośrednio dereferencjonować void*. Kompilator nie wie, ile bajtów odczytać ani jak je zinterpretować. Aby użyć danych, musisz rzutować wskaźnik z powrotem na właściwy typ:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Ta elastyczność wiąże się z odpowiedzialnością. Jeśli rzutujesz wskaźnik na niewłaściwy typ, kompilator cię przed tym nie powstrzyma, ale twój program zwróci śmieciowe dane lub ulegnie awarii. Dlatego funkcje generyczne często łączą void* ze wskaźnikiem typu (na przykład enumem lub flagą), aby funkcja wiedziała, jak poprawnie zinterpretować dane.
W nadchodzących lekcjach użyjesz void* do tworzenia kontenerów, które mogą przechowywać dane dowolnego typu, umożliwiając tworzenie naprawdę wielokrotnego użytku struktur danych.
Wyzwanie
ŁatwyNapisz funkcję o nazwie print_value, która przyjmuje dwa parametry: wskaźnik void* do danych oraz flagę typu int. Funkcja powinna interpretować i wyświetlać dane na podstawie flagi typu:
- Jeśli flaga typu ma wartość
0, rzutuj wskaźnik naint*i wyświetl wartość całkowitą - Jeśli flaga typu ma wartość
1, rzutuj wskaźnik nafloat*i wyświetl wartość zmiennoprzecinkową z dokładnością do 2 miejsc po przecinku
Twój program otrzyma dwa dane wejściowe:
- Flagę typu (
0dla liczby całkowitej,1dla liczby zmiennoprzecinkowej) - Wartość liczbową
Na podstawie flagi typu zapisz wartość w zmiennej odpowiedniego typu, a następnie wywołaj funkcję print_value, przekazując wskaźnik do tej zmiennej oraz flagę typu.
Przykładowe wyjście, gdy dane wejściowe to 0 i 42:
42Przykładowe wyjście, gdy dane wejściowe to 1 i 3.14:
3.14Przykładowe wyjście, gdy dane wejściowe to 0 i -17:
-17Przykładowe wyjście, gdy dane wejściowe to 1 i 99.5:
99.50Spróbuj swoich sił
#include <stdio.h>
// TODO: Napisz tutaj swoją funkcję print_value
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// TODO: Wywołaj print_value ze wskaźnikiem do int_value i flagą typu
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// TODO: Wywołaj print_value ze wskaźnikiem do float_value i flagą typu
}
return 0;
}Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania modularnego
Pliki nagłówkoweZabezpieczenia przed wielokrotnym dołączeniemPliki źródłoweFunkcje statycznePodsumowanie: kalkulator modularny4Enkapsulacja
Koncepcja niejawnych wskaźnikówDefiniowanie niejawnych strukturGettery i setteryWalidacja w setterachPowtórka: tajemnicze pudełko7Wskaźniki do funkcji
Deklarowanie wskaźników do funkcjiWywoływanie funkcji przez wskaźnikiTypedef dla wskaźników do funkcjiPrzekazywanie funkcji jako argumentówPodsumowanie: wybór działania kalkulatora10Kontenery generyczne
Powtórzenie: wskaźniki voidGeneryczny wrapperGeneryczna zamianaGeneryczne porównywaniePowtórzenie: tablica generyczna2Obiekty i metody
Struktury jako obiektyWskaźnik „self”Poprawność constWskaźnik czy wartośćMetody pomocniczePodsumowanie: menedżer punktów5Projekt: Proste konto bankowe
Konfiguracja projektuImplementacja konta8Polimorfizm
Wskaźniki do funkcji w strukturachSymulowanie metodKoncepcja interfejsuImplementowanie interfejsówIteracja polimorficznaPodsumowanie: Greeter11Wzorce projektowe w C
Wzorzec SingletonWzorzec fabrykiWzorzec iteratoraPodsumowanie: fabryka loggera3Cykl życia obiektu
Wzorzec konstruktoraWzorzec destruktoraInicjalizacja na stosieKopia głębokaPodsumowanie: klasa opakowująca ciąg znaków6Dziedziczenie przez kompozycję
Osadzanie strukturZasada pierwszego elementuDostęp do elementów klasy nadrzędnejKonwersja w górę hierarchiiPodsumowanie: hierarchia kształtów9Projekt: Rysownik kształtów
Przegląd projektuImplementacja kołaImplementacja prostokątaZastosowanie polimorfizmuKontener kształtówPoćwicz samodzielnie: Kompilator C online