Chcesz się kłócić?
Jako jeden z przykładów powyższego, ktoś właśnie wysłał do mnie e-mail z pytaniem, dlaczego czasami używam terminu „parametr”, a innym razem mówię „argument”. Rozważmy następującą deklarację bezsensownej funkcji:
int SillyFunction(int a, int b)
{
int y = a + b;
return y;
}
Kiedy deklarujemy funkcję, częścią tej deklaracji jest lista parametrów powiązanych z funkcją. W tym przypadku nasza funkcja ma dwa parametry: a i b. Oczywiście możliwe jest również zadeklarowanie funkcji z pustą listą parametrów.
Rozważmy teraz, kiedy wywołujemy naszą funkcję z innego miejsca w programie; na przykład:
int sillyResult = SillyFunction(40, 2);
Kiedy wywołujemy funkcję, przekazujemy listę argumentów. W tym przypadku przekazujemy dwa argumenty, 40 i 2, do funkcji SillyFunction(). Oczywiście, jeśli funkcja jest zadeklarowana z pustą listą parametrów, to gdy ją wywołamy, przekażemy pustą listę argumentów.
W rzeczywistości wiele osób używa terminów „parametry” i „argumenty” zamiennie. Tak długo, dopóki osoba, z którą rozmawiasz, rozumie wiadomość, którą próbujesz przekazać, „nie ma szkody, nie ma faulu”, jak to mówią.
Problem pojawia się, gdy rozmawiasz z profesjonalistami, którzy z wielką przyjemnością skrupulatnie wytkną Ci Twoje błędy. Osobiście nie chcę dawać im satysfakcji.
Ciekawsze i ciekawsze
Pod koniec rozdziału 1 „Przygód Alicji w Krainie Czarów” Alicja nierozsądnie wypija zawartość małej butelki z napisem „Wypij mnie” i kurczy się do zaledwie dziesięciu centymetrów wzrostu. Nieco później nieroztropna dziewczynka nie może powstrzymać się od schrupania małego ciasta z napisem „Zjedz mnie”, zrobionym z porzeczek. Na początku rozdziału 2 Alicja krzyczy „Ciekawsze i ciekawsze!”, gdy szybko rośnie do gigantycznych rozmiarów. Jeśli kiedykolwiek mi się to przytrafi (ponownie), jestem pewien, że powiem to samo (lub coś podobnego).
Powodem, dla którego o tym mówię, jest to, że coś podobnego może się zadziać z liczbami całkowitymi w C/C++ (w rzeczywistości może się to zadziać ze wszystkimi typami danych, ale na potrzeby tego tekstu skupimy się na liczbach całkowitych). Zjawisko to znane jest pod nazwą „konwersja typu” i występuje w dwóch odmianach: niejawnej i jawnej. W przypadku niejawnej konwersji typu, kompilator dokonuje tego automatycznie, bez konieczności wydawania mu przez nas instrukcji. Alternatywnie, możemy użyć jawnej konwersji typu do „rzutowania” (przekształcania) wartości z jednego typu danych na inny.
Jeśli spojrzysz na rubrykę „Sprytne porady i sztuczki…” z zeszłego miesiąca (EdW 04/2024), zobaczysz, że mamy krótkie, zwykłe i długie wersje liczb całkowitych ze znakiem i bez znaku (mamy również typy danych o stałej szerokości, takie jak uint8_t i uint32_t). Za każdym razem, gdy próbujemy wykonać operację binarną na operandach różnych typów, kompilator automatycznie konwertuje jeden z operandów na ten sam typ, co drugi. Jeśli operand przechodzi z mniejszej domeny (np. short) do większej domeny (np. long), nazywa się to promocją. Dla porównania, jeśli operand przechodzi z większej domeny do mniejszej domeny, zwie się to degradacją.
Promocja zazwyczaj nie stanowi problemu, ponieważ zakres wartości powiązanych z mniejszą liczbą całkowitą tworzy podzbiór większej domeny, do której jest promowana. W przypadku degradacji mogą jednak wystąpić problemy, jeśli degradowana wartość jest zbyt duża, aby zmieścić się w typie docelowym, w którym to przypadku wynik zostanie obcięty (oczywiście, może się okazać, że to jest dokładnie to, czego chcemy).
Różne języki radzą sobie z tym zadaniem na różne sposoby. W przypadku języka C/C++ możemy dokonać jawnej konwersji typu za pomocą operatora rzutowania, który obejmuje nazwę nowego typu danych otoczoną nawiasami. Załóżmy na przykład, że deklarujemy dwie zmienne całkowite bez znaku: jedną o szerokości 8 bitów i drugą o szerokości 32 bitów, w następujący sposób:
uint8_t myInt8;
uint32_t myInt32;