Inne działy

 

 

Język C wskaźniki a typ zmiennej

 

Jest to ważne z kilku powodów. Różne typy zajmują w pamięci różną wielkość. Przykładowo, jeżeli w zmiennej typu
unsigned int zapiszemy liczbę 65530, to w pamięci będzie istnieć jako:


+-----------+----------+
|komórka1|komórka2|
+-----------+----------+
|11111111|11111010| = (unsigned int) 65530
+-----------+----------+


Wskaźnik do takiej zmiennej (jak i do dowolnej innej) będzie wskazywać na pierwszą komórkę, w której ta zmienna ma swoją wartość. Jeżeli teraz stworzymy drugi wskaźnik do tego adresu, tym razem typu unsigned char*,
to wskaźnik przejmie ten adres prawidłowo, lecz gdy spróbujemy odczytać wartość na jaką wskazuje ten wskaźnik to zostanie odczytana tylko pierwsza komórka i wynik będzie równy 255:


+-----------+
|komórka1|
+-----------+
|11111111| = (unsigned char) 255
+-----------+

Gdybyśmy natomiast stworzyli inny wskaźnik do tego adresu tym razem typu unsigned long* to przy próbie odczytu odczytane zostaną dwa bajty z wartością zapisaną w zmiennej unsigned int oraz dodatkowe dwa bajty z niewiadomą zawartością i wówczas wynik będzie równy 65530 * 65536 + przypadkowa wartość:


+-----------+----------+-----------+-----------+
|komórka1|komórka2|komórka3|komórka4|
+-----------+----------+-----------+-----------+
|11111111|11111010|????????  |????????  |
+-----------+----------+-----------+-----------+


Ponadto, zapis czy odczyt poza przydzielonym obszarem pamięci może prowadzić do nieprzyjemnych skutków takich jak zmiana wartości innych zmiennych czy wręcz natychmiastowe przerwanie programu. Jako przykład można podać ten (błędny) program:

 

#include <stdio.h>
int main(void)
{
unsigned char tab[10] = { 100, 101, 102, 103, 104, 105, 106, 107, 108, 109 };
unsigned short *ptr = (unsigned short*)&tab[2];
unsigned i;
*ptr = 0xffff;
for (i = 0; i < 10; ++i) {
printf("%d\n", tab[i]);
tab[i] = tab[i] - 100;
}
printf("poza tablica: %d\n", tab[10]);
tab[10] = -1;
return 0;
}

 

Nie można również zapominać, że na niektórych architekturach dane wielobajtowe muszą być odpowiednio wyrównane w pamięci. Np. zmienna dwubajtowa może się znajdować jedynie pod parzystymi adresami. Wówczas, gdybyśmy chcieli adres zmiennej jednobajtowej przypisać wskaźnikowi na zmienną dwubajtową mogłoby dojść do nieprzewidzianych błędów wynikających z próby odczytu niewyrównanej danej.


Zaskakujące może się okazać, że różne wskaźniki mogą mieć różny rozmiar. Np.wskaźnik na char może być większy od wskaźnika na int, ale również na odwrót. Co więcej, wskaźniki różnych typów mogą się różnić reprezentacją adresów. Dla przykładu wskaźnik na char może przechowywać adres do bajtu natomiast wskaźnik na int ten adres podzielony przez 2. Podsumowując, różne wskaźniki to różne typy i nie należy beztrosko rzutować wyrażeń
pomiędzy różnymi typami wskaźnikowymi, bo grozi to nieprzewidywalnymi błędami

 

 

Zobacz nasze wszystkie kursy

WWW


HTML
HTML - Znaczniki
CSS - Tutorial
CSS - Selektory
PHP
JavaScript

XML

XSLT

Bazy danych


SQL
SQLite
MySQL
PostgreSQL

 

 

Programowanie


C
C++
C#
Java
VisualBasic
Python

Linux


Podstawy Linuxa
Bash
Linuks artykuły

Windows


Excel funkcje
Windows wskazówki
Outlook

Pozotałe działy


Programy
Rozrywka

 

 

 

This email address is being protected from spambots. You need JavaScript enabled to view it.