logo

Arytmetyka wskaźników w C

Na wskaźnikach możemy wykonywać operacje arytmetyczne, takie jak dodawanie, odejmowanie itp. Ponieważ jednak wiemy, że wskaźnik zawiera adres, wynik operacji arytmetycznej wykonanej na wskaźniku będzie również wskaźnikiem, jeśli drugi operand jest typu całkowitego. W przypadku odejmowania wskaźnika od wskaźnika wynikiem będzie wartość całkowita. Na wskaźniku w języku C możliwe są następujące operacje arytmetyczne:

  • Przyrost
  • Zmniejszenie
  • Dodatek
  • Odejmowanie
  • Porównanie

Zwiększanie wskaźnika w C

Jeśli zwiększymy wskaźnik o 1, wskaźnik zacznie wskazywać najbliższą następną lokalizację. Różni się to nieco od ogólnej arytmetyki, ponieważ wartość wskaźnika będzie zwiększana o rozmiar typu danych, na który wskazuje wskaźnik.

Możemy przechodzić przez tablicę, używając operacji inkrementacji na wskaźniku, który będzie wskazywał każdy element tablicy, wykonywał na nim jakąś operację i aktualizował się w pętli.

Reguła zwiększania wskaźnika jest podana poniżej:

 new_address= current_address + i * size_of(data type) 

Gdzie i to liczba, o którą zwiększa się wskaźnik.

32-bitowy

W przypadku 32-bitowej zmiennej int będzie ona zwiększana o 2 bajty.

porównywalny interfejs w Javie

64-bitowy

W przypadku 64-bitowej zmiennej int będzie ona zwiększana o 4 bajty.

Zobaczmy przykład zwiększania zmiennej wskaźnikowej w architekturze 64-bitowej.

 #include int main(){ int number=50; int *p;//pointer to int p=&number;//stores the address of number variable printf('Address of p variable is %u 
',p); p=p+1; printf('After increment: Address of p variable is %u 
',p); // in our case, p will get incremented by 4 bytes. return 0; } 

Wyjście

 Address of p variable is 3214864300 After increment: Address of p variable is 3214864304 

Przechodzenie przez tablicę za pomocą wskaźnika

 #include void main () { int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; int i; printf('printing array elements...
&apos;); for(i = 0; i<5; i++) { printf('%d ',*(p+i)); } < pre> <p> <strong>Output</strong> </p> <pre> printing array elements... 1 2 3 4 5 </pre> <h2>Decrementing Pointer in C</h2> <p>Like increment, we can decrement a pointer variable. If we decrement a pointer, it will start pointing to the previous location. The formula of decrementing the pointer is given below:</p> <pre> new_address= current_address - i * size_of(data type) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will be decremented by 2 bytes.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will be decremented by 4 bytes.</p> <p>Let&apos;s see the example of decrementing pointer variable on 64-bit OS.</p> <pre> #include void main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-1; printf(&apos;After decrement: Address of p variable is %u 
&apos;,p); // P will now point to the immidiate previous location. } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After decrement: Address of p variable is 3214864296 </pre> <h2>C Pointer Addition</h2> <p>We can add a value to the pointer variable. The formula of adding value to pointer is given below:</p> <pre> new_address= current_address + (number * size_of(data type)) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will add 2 * number.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will add 4 * number.</p> <p>Let&apos;s see the example of adding value to pointer variable on 64-bit architecture.</p> <pre> #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p+3; //adding 3 to pointer variable printf(&apos;After adding 3: Address of p variable is %u 
&apos;,p); return 0; } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After adding 3: Address of p variable is 3214864312 </pre> <p>As you can see, the address of p is 3214864300. But after adding 3 with p variable, it is 3214864312, i.e., 4*3=12 increment. Since we are using 64-bit architecture, it increments 12. But if we were using 32-bit architecture, it was incrementing to 6 only, i.e., 2*3=6. As integer value occupies 2-byte memory in 32-bit OS.</p> <h2>C Pointer Subtraction</h2> <p>Like pointer addition, we can subtract a value from the pointer variable. Subtracting any number from a pointer will give an address. The formula of subtracting value from the pointer variable is given below:</p> <pre> new_address= current_address - (number * size_of(data type)) </pre> <h3>32-bit</h3> <p>For 32-bit int variable, it will subtract 2 * number.</p> <h3>64-bit</h3> <p>For 64-bit int variable, it will subtract 4 * number.</p> <p>Let&apos;s see the example of subtracting value from the pointer variable on 64-bit architecture.</p> <pre> #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-3; //subtracting 3 from pointer variable printf(&apos;After subtracting 3: Address of p variable is %u 
&apos;,p); return 0; } </pre> <p> <strong>Output</strong> </p> <pre> Address of p variable is 3214864300 After subtracting 3: Address of p variable is 3214864288 </pre> <p>You can see after subtracting 3 from the pointer variable, it is 12 (4*3) less than the previous address value.</p> <p>However, instead of subtracting a number, we can also subtract an address from another address (pointer). This will result in a number. It will not be a simple arithmetic operation, but it will follow the following rule.</p> <p>If two pointers are of the same type,</p> <pre> Address2 - Address1 = (Subtraction of two addresses)/size of data type which pointer points </pre> <p>Consider the following example to subtract one pointer from an another.</p> <pre> #include void main () { int i = 100; int *p = &amp;i; int *temp; temp = p; p = p + 3; printf(&apos;Pointer Subtraction: %d - %d = %d&apos;,p, temp, p-temp); } </pre> <p> <strong>Output</strong> </p> <pre> Pointer Subtraction: 1030585080 - 1030585068 = 3 </pre> <h2>Illegal arithmetic with pointers</h2> <p>There are various operations which can not be performed on pointers. Since, pointer stores address hence we must ignore the operations which may lead to an illegal address, for example, addition, and multiplication. A list of such operations is given below.</p> <ul> <li>Address + Address = illegal</li> <li>Address * Address = illegal </li> <li>Address % Address = illegal</li> <li>Address / Address = illegal</li> <li>Address &amp; Address = illegal</li> <li>Address ^ Address = illegal</li> <li>Address | Address = illegal</li> <li> ~Address = illegal</li> </ul> <h2>Pointer to function in C</h2> <p>As we discussed in the previous chapter, a pointer can point to a function in C. However, the declaration of the pointer variable must be the same as the function. Consider the following example to make a pointer pointing to the function. <pre> #include int addition (); int main () { int result; int (*ptr)(); ptr = &amp;addition; result = (*ptr)(); printf(&apos;The sum is %d&apos;,result); } int addition() { int a, b; printf(&apos;Enter two numbers?&apos;); scanf(&apos;%d %d&apos;,&amp;a,&amp;b); return a+b; } </pre> </p><p> <strong>Output</strong> </p> <pre> Enter two numbers?10 15 The sum is 25 </pre> <h2>Pointer to Array of functions in C</h2> <p>To understand the concept of an array of functions, we must understand the array of function. Basically, an array of the function is an array which contains the addresses of functions. In other words, the pointer to an array of functions is a pointer pointing to an array which contains the pointers to the functions. Consider the following example.</p> <pre> #include int show(); int showadd(int); int (*arr[3])(); int (*(*ptr)[3])(); int main () { int result1; arr[0] = show; arr[1] = showadd; ptr = &amp;arr; result1 = (**ptr)(); printf(&apos;printing the value returned by show : %d&apos;,result1); (*(*ptr+1))(result1); } int show() { int a = 65; return a++; } int showadd(int b) { printf(&apos;
Adding 90 to the value returned by show: %d&apos;,b+90); } </pre> <p> <strong>Output</strong> </p> <pre> printing the value returned by show : 65 Adding 90 to the value returned by show: 155 </pre> <hr></5;>

Zmniejszanie wskaźnika w C

Podobnie jak przyrost, możemy zmniejszać zmienną wskaźnikową. Jeśli zmniejszymy wskaźnik, zacznie on wskazywać poprzednią lokalizację. Poniżej podano wzór na zmniejszanie wskaźnika:

 new_address= current_address - i * size_of(data type) 

32-bitowy

W przypadku 32-bitowej zmiennej int zostanie ona zmniejszona o 2 bajty.

64-bitowy

W przypadku 64-bitowej zmiennej int zostanie ona zmniejszona o 4 bajty.

Zobaczmy przykład zmniejszania zmiennej wskaźnikowej w 64-bitowym systemie operacyjnym.

 #include void main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-1; printf(&apos;After decrement: Address of p variable is %u 
&apos;,p); // P will now point to the immidiate previous location. } 

Wyjście

 Address of p variable is 3214864300 After decrement: Address of p variable is 3214864296 

Dodatek wskaźnika C

Możemy dodać wartość do zmiennej wskaźnikowej. Poniżej podano wzór na dodanie wartości do wskaźnika:

 new_address= current_address + (number * size_of(data type)) 

32-bitowy

W przypadku 32-bitowej zmiennej int dodana zostanie liczba 2 *.

64-bitowy

W przypadku 64-bitowej zmiennej int doda liczbę 4 *.

Zobaczmy przykład dodawania wartości do zmiennej wskaźnikowej w architekturze 64-bitowej.

 #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p+3; //adding 3 to pointer variable printf(&apos;After adding 3: Address of p variable is %u 
&apos;,p); return 0; } 

Wyjście

 Address of p variable is 3214864300 After adding 3: Address of p variable is 3214864312 

Jak widać, adres p to 3214864300. Ale po dodaniu 3 do zmiennej p jest to 3214864312, czyli przyrost 4*3=12. Ponieważ używamy architektury 64-bitowej, zwiększa się ona o 12. Ale jeśli korzystamy z architektury 32-bitowej, zwiększa się tylko do 6, tj. 2*3=6. Ponieważ wartość całkowita zajmuje 2 bajty pamięci w 32-bitowym systemie operacyjnym.

C Odejmowanie wskaźnika

Podobnie jak dodawanie wskaźnika, możemy odjąć wartość od zmiennej wskaźnikowej. Odjęcie dowolnej liczby od wskaźnika da adres. Poniżej podano wzór na odjęcie wartości od zmiennej wskaźnikowej:

 new_address= current_address - (number * size_of(data type)) 

32-bitowy

W przypadku 32-bitowej zmiennej int odejmie 2 * liczbę.

64-bitowy

W przypadku 64-bitowej zmiennej int odejmie 4 * liczbę.

Zobaczmy przykład odejmowania wartości od zmiennej wskaźnikowej w architekturze 64-bitowej.

 #include int main(){ int number=50; int *p;//pointer to int p=&amp;number;//stores the address of number variable printf(&apos;Address of p variable is %u 
&apos;,p); p=p-3; //subtracting 3 from pointer variable printf(&apos;After subtracting 3: Address of p variable is %u 
&apos;,p); return 0; } 

Wyjście

 Address of p variable is 3214864300 After subtracting 3: Address of p variable is 3214864288 

Jak widać po odjęciu 3 od zmiennej wskaźnikowej, jest ona o 12 (4*3) mniejsza niż poprzednia wartość adresu.

Jednak zamiast odejmować liczbę, możemy również odjąć adres od innego adresu (wskaźnik). W rezultacie otrzymasz liczbę. Nie będzie to prosta operacja arytmetyczna, ale będzie się opierać na następującej regule.

Jeśli dwa wskaźniki są tego samego typu,

 Address2 - Address1 = (Subtraction of two addresses)/size of data type which pointer points 

Rozważ następujący przykład, aby odjąć jeden wskaźnik od drugiego.

 #include void main () { int i = 100; int *p = &amp;i; int *temp; temp = p; p = p + 3; printf(&apos;Pointer Subtraction: %d - %d = %d&apos;,p, temp, p-temp); } 

Wyjście

 Pointer Subtraction: 1030585080 - 1030585068 = 3 

Nielegalna arytmetyka ze wskaźnikami

Istnieją różne operacje, których nie można wykonać na wskaźnikach. Ponieważ wskaźnik przechowuje adres, musimy zignorować operacje, które mogą prowadzić do nieprawidłowego adresu, na przykład dodawanie i mnożenie. Lista takich operacji znajduje się poniżej.

  • Adres + Adres = nielegalne
  • Adres * Adres = nielegalny
  • Adres % Adres = nielegalny
  • Adres / Adres = nielegalny
  • Adres i adres = nielegalne
  • Adres ^ Adres = nielegalny
  • Adres | Adres = nielegalny
  • ~Adres = nielegalny

Wskaźnik do działania w C

Jak omówiliśmy w poprzednim rozdziale, wskaźnik może wskazywać na funkcję w C. Jednak deklaracja zmiennej wskaźnikowej musi być taka sama jak funkcja. Rozważ następujący przykład, aby utworzyć wskaźnik wskazujący na funkcję.

 #include int addition (); int main () { int result; int (*ptr)(); ptr = &amp;addition; result = (*ptr)(); printf(&apos;The sum is %d&apos;,result); } int addition() { int a, b; printf(&apos;Enter two numbers?&apos;); scanf(&apos;%d %d&apos;,&amp;a,&amp;b); return a+b; } 

Wyjście

 Enter two numbers?10 15 The sum is 25 

Wskaźnik do tablicy funkcji w C

Aby zrozumieć koncepcję tablicy funkcji, musimy zrozumieć tablicę funkcji. Zasadniczo tablica funkcji to tablica zawierająca adresy funkcji. Innymi słowy, wskaźnik do tablicy funkcji jest wskaźnikiem wskazującym na tablicę zawierającą wskaźniki do funkcji. Rozważ następujący przykład.

 #include int show(); int showadd(int); int (*arr[3])(); int (*(*ptr)[3])(); int main () { int result1; arr[0] = show; arr[1] = showadd; ptr = &amp;arr; result1 = (**ptr)(); printf(&apos;printing the value returned by show : %d&apos;,result1); (*(*ptr+1))(result1); } int show() { int a = 65; return a++; } int showadd(int b) { printf(&apos;
Adding 90 to the value returned by show: %d&apos;,b+90); } 

Wyjście

 printing the value returned by show : 65 Adding 90 to the value returned by show: 155