Указатели в C: что такое указатель в программировании на C? Типы

Что такое указатель в C?

Команда Указатель в C — это переменная, в которой хранится адрес другой переменной. Указатель также может использоваться для ссылки на другую функцию указателя. Указатель можно увеличивать/уменьшать, т. е. указывать на следующую/предыдущую ячейку памяти. Цель указателя — сэкономить место в памяти и ускорить выполнение.

Как использовать указатели в C

Если мы объявим переменную v типа int, v фактически сохранит значение.

Как использовать указатели в C

v теперь равно нулю.

Однако каждая переменная, кроме значения, имеет еще и свой адрес (или, проще говоря, то, где она находится в памяти). Адрес можно получить, поставив амперсанд (&) перед именем переменной.

Как использовать указатели в C

Если вы выведете адрес переменной на экран, он будет выглядеть как совершенно случайное число (более того, оно может отличаться от запуска к запуску).

Давайте попробуем это на практике с указателем на примере C.

Как использовать указатели в C

Результат этой программы: -480613588.

Итак, что такое указатель? Вместо хранения значения указатель будет хранить адрес переменной.


Переменная указателя

Целое *y = &v;

ПЕРЕМЕННЫЕ УКАЗАТЕЛЬ
A ценностное хранится в названный адрес хранения/памяти A переменная которая указывает на адрес хранения/памяти другой переменная

Объявление указателя

Как и переменные, указатели в C программирование должны быть объявлены до того, как их можно будет использовать в вашей программе. Указатели могут быть названы как угодно, пока они подчиняются правилам именования языка C. Объявление указателя имеет следующую форму.

data_type * pointer_variable_name;

Здесь,

  • тип данных является базовым типом указателя среди типов переменных C и указывает тип переменной, на которую указывает указатель.
  • Звездочка (*: та же звездочка, которая используется для умножения), которая является оператором косвенности, объявляет указатель.

Давайте посмотрим на некоторые допустимые объявления указателей в этом руководстве по указателям C:

int    *ptr_thing;            /* pointer to an integer */ 
int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */
double    *ptr2;    /* pointer to a double */
float    *ptr3;      /* pointer to a float */
char    *ch1 ;       /* pointer to a character */
float  *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */

Инициализировать указатель

После объявления указателя мы инициализируем его как стандартные переменные с адресом переменной. Если указатели в программировании на языке C не инициализированы и используются в программе, результаты могут быть непредсказуемыми и потенциально катастрофическими.

Чтобы получить адрес переменной, мы используем оператор амперсанда (&), помещенный перед именем переменной, адрес которой нам нужен. Инициализация указателя выполняется с помощью следующего синтаксиса.

Синтаксис указателя

 pointer = &variable;

Ниже приведена простая программа для иллюстрации указателя:

#include <stdio.h>
int main()
{
   int a=10;    //variable declaration
   int *p;      //pointer variable declaration
   p=&a;        //store address of variable a in pointer p
   printf("Address stored in a variable p is:%x\n",p);  //accessing the address
   printf("Value stored in a variable p is:%d\n",*p);   //accessing the value
   return 0;
}

Вывод:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
оператор Смысл
* Служит 2 целям

  1. Объявление указателя
  2. Возвращает значение указанной переменной
& Служит только 1 цели

  • Возвращает адрес переменной

Типы указателей в C

Ниже приведены различные Типы указателей в C:

Нулевой указатель

Мы можем создать нулевой указатель, присвоив нулевое значение во время объявления указателя. Этот метод полезен, когда указателю не присвоен адрес. Нулевой указатель всегда содержит значение 0.

Следующая программа иллюстрирует использование нулевого указателя:

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

Вывод:

The value inside variable p is:
0

Пустой указатель

In C программирование, указатель void также называется универсальным указателем. У него нет стандартного типа данных. Указатель void создается с помощью ключевого слова void. Его можно использовать для хранения адреса любой переменной.

Следующая программа иллюстрирует использование указателя void:

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

Вывод:

The size of pointer is:4

Дикий указатель

Указатель называется диким указателем, если он ничем не инициализируется. Эти типы указателей C неэффективны, поскольку они могут указывать на какой-то неизвестный участок памяти, что может вызвать проблемы в нашей программе и привести к сбою программы. Всегда следует быть осторожным при работе с дикими указателями.

Следующая программа иллюстрирует использование дикого указателя:

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

Вывод:

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

Другие типы указателей в «c» следующие:

  • Свисающий указатель
  • Комплексный указатель
  • Указатель рядом
  • Дальний указатель
  • Огромный указатель

Указатели прямого и косвенного доступа

В C существует два эквивалентных способа доступа к содержимому переменной и манипулирования им.

  • Прямой доступ: мы используем непосредственно имя переменной
  • Косвенный доступ: мы используем указатель на переменную

Давайте разберемся в этом с помощью программы ниже

#include <stdio.h>
/* Declare and initialize an int variable */
int var = 1;
/* Declare a pointer to int */
int *ptr;
int main( void )
{
/* Initialize ptr to point to var */
ptr = &var;
/* Access var directly and indirectly */
printf("\nDirect access, var = %d", var);
printf("\nIndirect access, var = %d", *ptr);
/* Display the address of var two ways */
printf("\n\nThe address of var = %d", &var);
printf("\nThe address of var = %d\n", ptr);
/*change the content of var through the pointer*/
*ptr=48;
printf("\nIndirect access, var = %d", *ptr);
return 0;}

После компиляции программы без ошибок результат такой:

Direct access, var = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

Арифметика указателей в C

Операции с указателем обобщены на следующем рисунке.

Арифметика указателей в C
Указатель Operaных

Приоритетная операция (приоритет)

При работе с указателями C мы должны соблюдать следующие правила приоритета:

  • Операторы * и & имеют тот же приоритет, что и унарные операторы (отрицание!, приращение++, декремент–).
  • В том же выражении унарные операторы *, &,!, ++, – вычисляются справа налево.

Если указатель P указывает на переменную X, то *P можно использовать везде, где можно записать X.

Следующие выражения эквивалентны:

int X =10
int *P = &Y;
For the above code, below expressions are true
Выражение Эквивалентное выражение
Д=*П+1

*P=*P+10

*П+=2

+***П

(*П)++

Y=X+1

Х=Х+10

Х+=2

++Х

X ++

В последнем случае необходимы круглые скобки: поскольку унарные операторы * и ++ вычисляются справа налево, без скобок увеличивался бы указатель P, а не объект, на который указывает P.

В таблице ниже показаны арифметические и основные операции, которые можно использовать при работе с указателями C.

Эксплуатация объяснение
Назначение целое *P1,*P2
П1=П2;
P1 и P2 указывают на одну и ту же целочисленную переменную.
Увеличение и уменьшение Целое *P1;
P1++;P1– ;
Добавление смещения (постоянного) Это позволяет указателю перемещать N элементов в таблице.
Указатель будет увеличен или уменьшен в N раз на количество байт(ов) типа переменной.
П1+5;

Указатели и массивы C с примерами

Традиционно мы получаем доступ к элементам массива, используя его индекс, но этот метод можно исключить, используя указатели. Указатели упрощают доступ к каждому элементу массива.

#include <stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};   //array initialization
    int *p;     //pointer declaration
               /*the ptr points to the first element of the array*/

    p=a; /*We can also type simply ptr==&a[0] */
    
    printf("Printing the array elements using pointer\n");
    for(int i=0;i<5;i++)    //loop for traversing array elements
    {
        	printf("\n%x",*p);  //printing array elements
        	p++;    //incrementing to the next element, you can also write p=p+1
    }
    return 0;
}

Вывод:

1
2
3
4
5

Добавление определенного числа к указателю переместит местоположение указателя на значение, полученное в результате операции сложения. Предположим, что p — это указатель, который в данный момент указывает на ячейку памяти 0. Если мы выполним следующую операцию сложения, p+1, то она будет выполнена следующим образом:

Указатели и массивы C

Добавление/приращение указателя

Поскольку p в настоящее время указывает на ячейку 0 после добавления 1, значение станет 1, и, следовательно, указатель будет указывать на ячейку памяти 1.

Указатели и строки C с примерами

Строка представляет собой массив объектов char, заканчивающийся нулевым символом '\ 0'. Мы можем манипулировать строками с помощью указателей. Этот указатель в примере C объясняет этот раздел.

#include <stdio.h>
#include <string.h>
int main()
{
char str[]="Hello Guru99!";
char *p;
p=str;
printf("First character is:%c\n",*p);
p =p+1;
printf("Next character is:%c\n",*p);
printf("Printing all the characters in a string\n");
p=str;  //reset the pointer
for(int i=0;i<strlen(str);i++)
{
printf("%c\n",*p);
p++;
}
return 0;
}

Вывод:

First character is:H
Next character is:e
Printing all the characters in a string
H
e
l
l
o

G
u
r
u
9
9
!

Другой способ работы со строками — использование массива указателей, как в следующей программе:

#include <stdio.h>
int main(){
char *materials[ ] = {  "iron",  "copper",  "gold"};
printf("Please remember these materials :\n");
int i ;
for (i = 0; i < 3; i++) {
  printf("%s\n", materials[ i ]);}
  return 0;}

Вывод:

Please remember these materials:
iron
copper
gold

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

  • Указатели полезны для доступа к ячейкам памяти.
  • Указатели предоставляют эффективный способ доступа к элементам структуры массива.
  • Указатели используются для динамического выделения и освобождения памяти.
  • Указатели используются для формирования сложных структур данных, таких как связанный список, граф, дерево и т. д.

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

  • Указатели немного сложны для понимания.
  • Указатели могут привести к различным ошибкам, таким как ошибки сегментации, или могут получить доступ к ячейке памяти, которая вообще не требуется.
  • Если указателю присвоено неверное значение, это может привести к повреждению памяти.
  • Указатели также ответственны за утечку памяти.
  • Указатели работают сравнительно медленнее, чем переменные.
  • Программистам очень сложно работать с указателями; поэтому ответственность за осторожное манипулирование указателем лежит на программисте.

Резюме

  • Указатель — это не что иное, как ячейка памяти, в которой хранятся данные.
  • Указатель используется для доступа к ячейке памяти.
  • Существуют различные типы указателей, такие как нулевой указатель, дикий указатель, недействительный указатель и другие типы указателей.
  • Указатели можно использовать с массивами и строками для более эффективного доступа к элементам.
  • Мы можем создавать указатели на функции для динамического вызова функции.
  • С указателем можно выполнять арифметические операции, которые известны как арифметика указателей.
  • Указатели также могут указывать на функции, которые упрощают вызов различных функций в случае определения массива указателей.
  • Если вы хотите иметь дело с переменными типами данных другого типа, вы можете использовать указатель типа void.