Wskaźnik czy wartość
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 9 z 61.
Gdy przekazujesz strukturę do funkcji, C daje ci dwie możliwości: przekazać ją przez wartość (skopiować całą strukturę) lub przez wskaźnik (skopiować tylko adres). Wybór ma istotny wpływ na wydajność.
Przekazywanie przez wartość tworzy pełną kopię struktury na stosie. W przypadku małej struktury z kilkoma liczbami całkowitymi jest to w porządku. Ale wyobraź sobie strukturę mającą setki bajtów: każde wywołanie funkcji kopiuje wszystkie te dane:
typedef struct {
char name[100];
int scores[50];
double average;
} Student;
// Przez wartość: kopiuje ~308 bajtów przy każdym wywołaniu
void print_by_value(Student s) {
printf("%s: %.2f\n", s.name, s.average);
}
// Przez wskaźnik: kopiuje tylko 8 bajtów (adres)
void print_by_pointer(const Student *s) {
printf("%s: %.2f\n", s->name, s->average);
}
Składnia również się różni. W przypadku parametru przekazywanego przez wartość używasz operatora kropki (s.name). W przypadku wskaźnika używasz operatora strzałki (s->name).
Wersja ze wskaźnikiem jest bardziej wydajna, ponieważ przekazuje tylko adres pamięci, zazwyczaj 8 bajtów niezależnie od rozmiaru struktury.
Dlatego programiści C niemal zawsze przekazują struktury przez wskaźnik. Użyj const, gdy funkcja nie powinna modyfikować danych, a zwykłego wskaźnika, gdy powinna. Zyskujesz zarówno wydajność, jak i jasny zamiar.
Wyzwanie
ŁatwyZbudujmy moduł Product, który pokazuje różnicę między przekazywaniem struktur przez wartość a przez wskaźnik. Utworzysz dwie funkcje wyświetlające: jedną, która otrzymuje całą strukturę jako kopię, i drugą, która otrzymuje tylko wskaźnik do niej.
Utworzysz trzy pliki:
product.h: Zadeklaruj strukturęProductz trzema polami:char name[50],double priceiint quantity. Zadeklaruj też dwie funkcje:display_by_value: przyjmujeProductprzez wartość i wyświetla jego informacjedisplay_by_pointer: przyjmujeconst Product *i wyświetla te same informacje
PRODUCT_H.product.c: Zaimplementuj obie funkcje. Zwróć uwagę na różnicę składni: wersja przekazująca przez wartość używa operatora kropki (p.name), a wersja wskaźnikowa używa operatora strzałki (p->name). Obie funkcje powinny wyświetlać informacje w tym samym formacie.main.c: Utwórz obiekt Product, a następnie wywołaj obie funkcje wyświetlające, aby pokazać, że generują identyczne dane wyjściowe mimo użycia różnych sposobów przekazywania argumentów.
Otrzymasz trzy dane wejściowe: nazwę produktu (ciąg znaków), cenę (liczbę typu double) i ilość (liczbę całkowitą).
W pliku main zainicjalizuj obiekt Product tymi wartościami, a następnie wywołaj display_by_value, po czym display_by_pointer.
Obie funkcje powinny wyświetlać informacje w tym formacie:
Product: {name}, Price: {price}, Qty: {quantity}Użyj %.2f dla ceny, aby wyświetlić ją z dokładnością do dwóch miejsc po przecinku.
Na przykład dla danych wejściowych Laptop, 999.99 i 5 dane wyjściowe będą następujące:
Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5Spróbuj swoich sił
#include <stdio.h>
#include <string.h>
#include "product.h"
int main() {
char name[50];
double price;
int quantity;
// Wczytaj dane wejściowe
scanf("%s", name);
scanf("%lf", &price);
scanf("%d", &quantity);
// TODO: Utwórz zmienną typu Product i zainicjalizuj ją wartościami wejściowymi
// Wskazówka: Użyj strcpy, aby skopiować nazwę do pola name struktury
// TODO: Wywołaj display_by_value, przekazując Product
// TODO: Wywołaj display_by_pointer, przekazując wskaźnik do Product
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łko2Obiekty 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