Указатель в языке Си
Указатель на языке Си — это переменная, которая хранит адрес другой переменной. Он может иметь тип int, char, array, function или любой другой указатель. Размер указателя зависит от архитектуры. Однако в 32-битной архитектуре размер указателя составляет 2 байта.
Рассмотрим следующий пример, чтобы определить указатель, который хранит адрес целого числа.
int n = 10;
int* p = &n; // Переменная p типа указатель указывает на адрес переменной n типа integer.
Объявление указателя
Указатель на языке си может быть объявлен с помощью * (символ звездочки). Он также известен как косвенный указатель, используемый для разыменования указателя.
int *a;//указатель на int
char *c;//указатель на char
Пример использования указателей для печати адреса и значения приведен ниже.
Как вы можете видеть на приведенном выше рисунке, переменная указателя хранит адрес переменной числа, то есть fff4. Значение переменной number равно 50. Но адрес переменной указателя p-aaa3.
С помощью * (оператор косвенности) мы можем вывести значение переменной указателя p. Давайте рассмотрим пример указателя, как описано на приведенном выше рисунке.
#include<stdio.h>
int main(){
int number=50;
int *p;
p=&number;//хранит адрес числовой переменной
printf(«Адрес переменной p равен %x \n»,p); // p содержит адрес числа, поэтому печать p дает адрес числа.
printf(«Значение переменной p равно %d \n»,*p); // Поскольку мы знаем, что * используется для разыменования указателя, поэтому, если мы напечатаем *p, мы получим значение, хранящееся по адресу, содержащемуся в p.
return 0;
}
Выход
Адрес числовой переменной fff4
Адрес переменной p-fff4
Значение переменной p равно 50
Указатель на массив
intarr[10];
int *p[10]=&arr; // Переменная p типа pointer указывает на адрес целочисленного массива arr.
Указатель на функцию
voidshow (int);
void(*p)(int) = &display; // Указатель p указывает на адрес функции
Указатель на структуру
structst {
inti;
floatf;
}ref;
structst *p = &ref;
Преимущества указателя
- Указатель сокращает код и повышает производительность, он используется для извлечения строк, деревьев и т. Д. и используется с массивами, структурами и функциями.
- Мы можем возвращать несколько значений из функции с помощью указателя.
- Это позволяет вам получить доступ к любой ячейке памяти в памяти компьютера.
Использование указателя
Существует множество применений указателей на языке си.
Динамическое выделение памяти
В языке си мы можем динамически выделять память с помощью функций malloc() и calloc (), где используется указатель.
Массивы, функции и структуры
Указатели на языке си широко используются в массивах, функциях и структурах. Это сокращает код и повышает производительность.
Адрес Оператора (&)
Адрес оператора ‘&’ возвращает адрес переменной. Но нам нужно использовать %u для отображения адреса переменной.
#include<stdio.h>
int main(){
int number=50;
printf(«значение числа — %d, адрес числа — %u»,number,&number);
return 0;
}
Выход
значение числа равно 50, адрес числа-fff4
Нулевой Указатель
Указатель, которому не присвоено никакого значения, кроме NULL, называется нулевым указателем. Если у вас нет никакого адреса, который должен быть указан в указателе во время объявления, вы можете присвоить нулевое значение. Это обеспечит лучший подход.
int *p=NULL;
В большинстве библиотек значение указателя равно 0 (нулю). Указательная программа для замены двух чисел без использования 3-й переменной.
#include<stdio.h>
int main(){
int a=10,b=20,*p1=&a,*p2=&b;
printf(«Перед свопом: *p1=%d *p2=%d»,*p1,*p2);
*p1=*p1+*p2;
*p2=*p1-*p2;
*p1=*p1-*p2;
printf(«\nAfter swap: *p1=%d *p2=%d»,*p1,*p2);return0;
}
Выход
Перед свопом: *p1=10 *p2=20
После свопа: *p1=20 *p2=10
Чтение сложных указателей
Есть несколько вещей, которые должны быть приняты во внимание при чтении сложных указателей в C. Давайте посмотрим на приоритет и ассоциативность операторов, которые используются в отношении указателей.
Оператор | Приоритет | Ассоциативность |
(), [] | 1 | Слева направо |
*, идентификатор | 2 | Справа налево |
Тип данных | 3 | — |
Здесь мы должны заметить, что:
- (): Этот оператор является скобочным оператором, используемым для объявления и определения функции.
- []: Этот оператор является оператором индекса массива
- * : Этот оператор является оператором указателя.
- Идентификатор: Это имя указателя. Приоритет всегда будет отдаваться этому.
- Тип данных: Тип данных-это тип переменной, на которую должен указывать указатель. Он также включает в себя модификатор типа signedint, long и т. д.).
Как читать указатель: int (*p)[10].
Чтобы прочитать указатель, мы должны увидеть, что () и [] имеют одинаковый приоритет. Поэтому здесь необходимо учитывать их ассоциативность. Ассоциативность находится слева направо, поэтому приоритет отдается ().
Внутри скобки () оператор указателя * и имя указателя (идентификатор) p имеют одинаковый приоритет. Поэтому их ассоциативность должна быть рассмотрена здесь справа налево, поэтому приоритет идет к p, а второй приоритет идет к *.
Назначьте 3-й приоритет [], так как тип данных имеет последний приоритет. Поэтому указатель будет выглядеть следующим образом.
char -> 4
* -> 2
p -> 1
[10] -> 3
Указатель будет считываться как p-указатель на массив целых чисел размера 10.
Как прочитать следующий указатель?
int (*p)(int (*)[2], int (*)void))
Этот указатель будет считываться как p-указатель на такую функцию, которая принимает первый параметр как указатель на одномерный массив целых чисел размера два, а второй параметр как указатель на функцию, параметр которой является пустым, а тип возвращаемого значения-целым.
Преимущества (использование) указателей в c:
- Указатели обеспечивают прямой доступ к памяти
- Указатели позволяют возвращать функции более одного значения
- Уменьшает объем памяти и сложность программы
- Сокращает время выполнения программы
- Предоставляет альтернативный способ доступа к элементам массива
- Указатели могут использоваться для передачи информации между вызывающей функцией и вызываемой функцией.
- Указатели позволяют нам выполнять динамическое выделение и освобождение памяти.
- Указатели помогают нам создавать сложные структуры данных, такие как связанный список, стек, очереди, деревья, графики и т. Д.
- Указатели позволяют нам изменять размер динамически выделяемого блока памяти.
- Адреса объектов могут быть извлечены с помощью указателей
Недостатки указателей в c:
- Неинициализированные указатели могут вызвать ошибку сегментации.
- Динамически выделяемый блок должен быть освобожден явно. В противном случае это приведет к утечке памяти.
- Указатели работают медленнее, чем обычные переменные.
- Если указатели обновляются с неверными значениями, это может привести к повреждению памяти.
В принципе, ошибки указателей трудно отлаживать. Ответственность программистов за эффективное и правильное использование указателей.
Передача указателя на функцию в C с примером
В этом примере мы передаем указатель на функцию. Когда мы передаем указатель в качестве аргумента вместо переменной, вместо значения передается адрес переменной. Таким образом, любое изменение, произведенное функцией с помощью указателя, постоянно производится по адресу передаваемой переменной. Этот метод известен как вызов по ссылке в C.
Попробуйте эту же программу без указателя, вы обнаружите, что сумма бонуса не будет отражаться в зарплате, это потому, что изменение, произведенное функцией, будет сделано с локальными переменными функции.
#include<stdio.h>
voidsalaryhike(int *var, int b)
{
*var = *var+b;
}
int main()
{
intsolary=0, bonus=0;
printf(«Введите текущую зарплату сотрудника:»);
scanf(«%d», &solary);
printf(«Введите бонус:»);
scanf(«%d», &bonus);
salaryhike(&solary, bonus);
printf(«Конечная зарплата: %d», solary);
return 0;
}
Выход:
Введите текущую зарплату сотрудника:10000
Введите бонус:2000
Итоговая зарплата: 12000
Замена двух чисел с помощью указателей
Это один из самых популярных примеров, который показывает, как менять номера с помощью вызова по ссылке. Попробуйте эту программу без указателей, вы увидите, что числа не меняются местами. Причина та же, что мы видели выше в первом примере.
#include <stdio.h>
voidswapnum(int *num1, int *num2)
{
inttempnum;tempnum = *num1;
*num1 = *num2;
*num2 = tempnum;
}
int main( )
{
int v1 = 11, v2 = 77 ;
printf(«Перед заменой:»);
printf(«\nЗначение v1: %d», v1);
printf(«\nЗначение v2: %d», v2);/*вызов функции swap*/
swapnum(&v1, &v2 );printf(«\nAfter swapping:»);
printf(«\Значение v1: %d», v1);
printf(«\nЗначение v2: %d», v2);
}
Выход:
Перед обменом:
Значение v1 равно: 11
Значение v2 равно: 77После обмена:
Значение v1 равно: 77
Значение v2 равно: 11
Заключение
В этом уроке мы узнали как пользоваться указателями языка C, пишите свои вопросы в комментариях