Указатель в языке Си

Указатель на языке Си — это переменная, которая хранит адрес другой переменной. Он может иметь тип 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;

Указатель в языке Си

Преимущества указателя

  1. Указатель сокращает код и повышает производительность, он используется для извлечения строк, деревьев и т. Д. и используется с массивами, структурами и функциями.
  2. Мы можем возвращать несколько значений из функции с помощью указателя.
  3. Это позволяет вам получить доступ к любой ячейке памяти в памяти компьютера.

Использование указателя

Существует множество применений указателей на языке си.

Динамическое выделение памяти

В языке си мы можем динамически выделять память с помощью функций 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:

  1. Указатели обеспечивают прямой доступ к памяти
  2. Указатели позволяют возвращать функции более одного значения
  3. Уменьшает объем памяти и сложность программы
  4. Сокращает время выполнения программы
  5. Предоставляет альтернативный способ доступа к элементам массива
  6. Указатели могут использоваться для передачи информации между вызывающей функцией и вызываемой функцией.
  7. Указатели позволяют нам выполнять динамическое выделение и освобождение памяти.
  8. Указатели помогают нам создавать сложные структуры данных, такие как связанный список, стек, очереди, деревья, графики и т. Д.
  9. Указатели позволяют нам изменять размер динамически выделяемого блока памяти.
  10. Адреса объектов могут быть извлечены с помощью указателей

Недостатки указателей в c:

  1. Неинициализированные указатели могут вызвать ошибку сегментации.
  2. Динамически выделяемый блок должен быть освобожден явно. В противном случае это приведет к утечке памяти.
  3. Указатели работают медленнее, чем обычные переменные.
  4. Если указатели обновляются с неверными значениями, это может привести к повреждению памяти.

В принципе, ошибки указателей трудно отлаживать. Ответственность программистов за эффективное и правильное использование указателей.

Передача указателя на функцию в 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, пишите свои вопросы в комментариях

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *