Rzutowanie typów w C: konwersja niejawna i jawna

⚡ Inteligentne podsumowanie

Rzutowanie typów w języku C polega na konwersji jednego typu danych na inny, albo niejawnie, gdy kompilator automatycznie promuje mniejszy, zgodny typ, albo jawnie, gdy programista wymusza konwersję za pomocą operatora rzutowania w celu kontrolowania precyzji i zapobiegania nieoczekiwanym wynikom.

  • 🔄 Dwie formy: Rzutowanie niejawne działa automatycznie; rzutowanie jawne zapisuje się za pomocą operatora rzutowania.
  • ⬆️ Promocja typu: Konwersja mniejszego typu na większy, kompatybilny, np. short na int, powoduje zachowanie wartości.
  • ✂️. Ryzyko utraty danych: Zawężające rzutowanie, takie jak float na int, powoduje pominięcie ułamka i utratę znaczenia.
  • 🎯 Składnia jawna: Zapisanie wyrażenia (typ-nazwa) wymusza konwersję, np. rzutowanie operandów całkowitych na liczby zmiennoprzecinkowe.
  • 🤖 Pomoc AI: Asystenci AI i GitHub Copilot tworzą szkice wyrażeń rzutowania i sygnalizują ryzykowne konwersje zawężające.

Rzutowanie typów w C

Co to jest rzutowanie typów w C?

Rzutowanie typów to konwersja jednego typu danych na inny. W języku C nazywane jest również konwersją danych lub konwersją typów. Jest to jedna z ważnych koncepcji wprowadzonych w programowaniu w języku C.

W programowaniu w języku C dostępne są dwa typy operacji rzutowania typów:

  • Niejawne rzutowanie typów
  • Jawne rzutowanie typów

Niejawne rzutowanie typów

Niejawne rzutowanie typów oznacza konwersję typów danych bez utraty ich pierwotnego znaczenia. Ten typ rzutowania jest niezbędny, gdy chcesz zmienić typy danych bez zmiany znaczenia wartości przechowywanych w zmienna.

Niejawna konwersja typu w C następuje automatycznie, gdy wartość jest kopiowana do zgodnego typu danych. Podczas konwersji stosowane są ścisłe reguły konwersji typu. Jeśli operandy są dwóch różnych typów danych, operand o niższym typie danych jest automatycznie konwertowany na wyższy typ danych. Ten typ konwersji typu można zobaczyć w poniższym przykładzie.

#include<stdio.h>
int main(){
	short a=10; //initializing variable of short data type
	int b; //declaring int variable
	b=a; //implicit type casting
	printf("%d\n",a);
	printf("%d\n",b);
}

Wyjście:

10
10

Niejawne rzutowanie typów

  1. W podanym przykładzie zadeklarowaliśmy zmienną o krótkim typie danych, której wartość została zainicjowana jako 10.
  2. W drugiej linii zadeklarowaliśmy zmienną typu int.
  3. W trzeciej linii przypisaliśmy wartość zmiennej s zmiennej a. W trzeciej linii wykonywana jest niejawna konwersja typu, gdy wartość zmiennej s o typie krótkim jest kopiowana do zmiennej a o typie int.

Konwersja znaku na int

Rozważmy przykład dodania znaku dekodowanego w ASCII za pomocą liczby całkowitej:

#include <stdio.h>
main() {
   int  number = 1;
   char character = 'k'; /*ASCII value is 107 */
   int sum;
   sum = number + character;
   printf("Value of sum : %d\n", sum );
}

Wyjście:

 Value of sum : 108

W tym przypadku kompilator wykonał promocję liczb całkowitych, konwertując wartość „k” na kod ASCII przed wykonaniem faktycznej operacji dodawania.

Hierarchia konwersji arytmetycznych

Kompilator najpierw przechodzi do promowania znaku do liczby całkowitej. Jeśli operandy nadal mają różne typy danych, są one konwertowane do najwyższego typu danych, który pojawia się w następującym schemacie hierarchii:

Hierarchia konwersji arytmetycznych

Aby zrozumieć tę koncepcję, rozważ poniższy przykład:

#include <stdio.h>
main() {
   int  num = 13;
   char c = 'k'; /* ASCII value is 107 */
   float sum;
   sum = num + c;
   printf("sum = %f\n", sum );}

Wyjście:

 sum = 120.000000

Najpierw zmienna c zostaje przekształcona na liczbę całkowitą, ale kompilator przekształca num i c na „float” i dodaje je, aby uzyskać wynik „float”.

Ważne uwagi dotyczące konwersji niejawnych

  • Niejawna konwersja typu jest również nazywana konwersją typu standardowego. Nie wymagamy żadnych słów kluczowych ani specjalnych instrukcji w niejawnym rzutowaniu typów.
  • Konwersja z mniejszego typu danych do większego typu danych jest również nazywana promocją typu. W powyższym przykładzie możemy również powiedzieć, że wartość s jest promowana do typu całkowitego.
  • Niejawna konwersja typów zawsze odbywa się w przypadku zgodnych typów danych.

Nie możemy przeprowadzać ukrytego rzutowania typów danych na typy danych, które nie są ze sobą kompatybilne, takie jak:

  1. Konwersja float na int spowoduje obcięcie części ułamkowej, tracąc w ten sposób znaczenie wartości.
  2. Zamiana liczby podwójnej na zmiennoprzecinkową spowoduje zaokrąglenie cyfr.
  3. Konwersja long int na int spowoduje spadekping nadmiarowych bitów wyższego rzędu.

We wszystkich powyższych przypadkach, gdy dokonamy konwersji typów danych, wartość straci swoje znaczenie. Ogólnie rzecz biorąc, kompilator ostrzega o utracie znaczenia wartości.

Programowanie w języku „C”. zapewnia inny sposób rzutowania typów, który jest jawnym rzutowaniem typów.

Jawne rzutowanie typów

W niejawnej konwersji typu typ danych jest konwertowany automatycznie. Istnieją pewne scenariusze, w których możemy musieć wymusić konwersję typu. Załóżmy, że mamy zmienną div, która przechowuje dzielenie dwóch operandów, które są zadeklarowane jako typ danych int.

 int result, var1=10, var2=3;
result=var1/var2;

W tym przypadku po dzieleniu wykonanym na zmiennych var1 i var2 wynik zapisany w zmiennej „result” będzie w formacie całkowitym. Za każdym razem, gdy to nastąpi, wartość zapisana w zmiennej „result” traci swoje znaczenie, ponieważ nie bierze pod uwagę części ułamkowej, która jest normalnie uzyskiwana przy dzieleniu dwóch liczb.

Aby wymusić konwersję typu w takich sytuacjach, używamy jawnego rzutowania typów.

Wymaga operatora rzutowania typu. Ogólna składnia operacji rzutowania typu jest następująca:

(type-name) expression

Tutaj,

  • Nazwa typu jest standardowym typem danych języka „C”.
  • Wyrażenie może być stałą, zmienną lub rzeczywistym wyrażeniem.

Napiszmy program demonstrujący, jak rzutować na typ w C z jawnym rzutowaniem typów.

#include<stdio.h>
int main()
{
	float a = 1.2;
	//int b  = a; //Compiler will throw an error for this
	int b = (int)a + 1;
	printf("Value of a is %f\n", a);
	printf("Value of b is %d\n",b);
	return 0;
}

Wyjście:

Value of a is 1.200000
Value of b is 2

Jawne rzutowanie typów

  1. Zainicjowaliśmy zmienną „a” typu float.
  2. Następnie mamy kolejną zmienną „b” o typie danych całkowitych. Ponieważ zmienne „a” i „b” mają różne typy danych, „C” nie zezwoli na użycie takiego wyrażenia i zgłosi błąd. W niektórych wersjach „C” wyrażenie zostanie obliczone, ale wynik nie będzie pożądany.
  3. Aby uniknąć takich sytuacji, rzutowaliśmy zmienną „a” typu float. Używając jawnych metod rzutowania typów, pomyślnie przekonwertowaliśmy liczbę zmiennoprzecinkową na liczbę całkowitą typu danych.
  4. Wydrukowaliśmy wartość „a”, która nadal jest liczbą zmiennoprzecinkową
  5. Po rzutowaniu wynikiem zawsze będzie liczba całkowita „b”.

W ten sposób możemy zaimplementować jawne rzutowanie typów w programowaniu C.

FAQ

Konwersja typu to automatyczna zmiana typu wykonywana przez kompilator; rzutowanie typu to jawna zmiana żądana za pomocą operatora rzutowania. Rzutowanie jest jedną z form konwersji.

Może. Zmiana typu float na int powoduje obcięcie ułamka, double na float zaokrągla cyfry, a long na int pomija bity wyższego rzędu. Rzutowanie rozszerzające pozostaje bezpieczne.

Tak. C pozwala na rzutowanie jednego typu wskaźnika na inny, a wskaźniki obiektów konwertują się na void* i odwrotnie. Dereferencja niekompatybilnego rzutowania wskaźnika powoduje niezdefiniowane zachowanie.

Język C obsługuje wyłącznie rzutowanie wartości (typu) w stylu języka C. C++ dodaje cztery bezpieczniejsze nazwane rzutowania — static_cast, dynamic_cast, const_cast i reinterpret_cast — z jaśniejszą, sprawdzaną przez kompilator intencją.

Wartość zachowuje tylko bity niższego rzędu. Jeśli jest zbyt duża, wynik zawija się lub zmienia znak, dlatego najpierw sprawdź, czy mieści się w zakresie docelowym.

Preferuj rzutowanie rozszerzające, potwierdzaj dopasowanie wartości przed zawężaniem i rzutuj jeden operand na float przed dzieleniem całkowitym. Włącz ostrzeżenia kompilatora, aby sygnalizować ryzykowne konwersje.

Tak. Asystent AI pisze wyrażenia rzutowania z poziomu monitu, wyjaśnia zasady promocji i ostrzega, gdy konwersja może spowodować utratę danych. Zawsze kompiluj i testuj wynik.

Drugi pilot GitHub sugeruje wyrażenia rzutowania niejawne i jawne z komentarza, włączając w to składnię (nazwa-typu). RevPrzed kompilacją zapoznaj się z każdą sugestią dotyczącą możliwej utraty danych.

Podsumuj ten post następująco: