Радиоконструктор

Язык C, Часть 23

Создание указателя на массив

Указатель на 1-й элемент массива можно создать путем присваивания ему имени массива без индекса. Например, если есть объявление
int sample[10];
то в качестве указателя на 1-й элемент массива можно использовать имя sample. В следующем фрагменте программы адрес 1-го элемента массива sample присваивается указателю р:
int *p;
int sample[10];

p = sample;
В обеих переменных (р и sample) хранится адрес 1-го элемента, отличаются эти переменные только тем, что значение sample в программе изменять нельзя. Адрес первого элемента можно также получить, используя оператор получения адреса &. Например, выражения sample и &sample[0] имеют одно и то же значение. Тем не менее, в профессионально написанных программах вы не встретите выражения &sample[0]


Передача одномерного массива в функцию

В языке С нельзя передать весь массив как аргумент функции. Однако можно передать указатель на массив, т.е. имя массива без индекса. Например, в представленной программе в func1() передается указатель на массив i:
int main(void)
{
  int i[10];

  func1(i);

  /* ... */
}
Если в функцию передается указатель на одномерный массив, то в самой функции его можно объявить одним из трех вариантов: как указатель, как массив определенного размера и как массив без определенного размера. Например, чтобы функция func1() получила доступ к значениям, хранящимся в массиве i, она может быть объявлена как
void func1(int *x) /* указатель */
{
  /* ... */
}
или как
void func1(int x[10]) /* массив определенного размера */
{
  /* ... */
}
и наконец как
void func1(int x[]) /* массив без определенного размера */
{
  /* ... */
}
Эти три объявления тождественны, потому что каждое из них сообщает компилятору одно и то же: в функцию будет передан указатель на переменную целого типа. В первом объявлении используется указатель, во втором — стандартное объявление массива. В последнем примере измененная форма объявления массива сообщает компилятору, что в функцию будет передан массив неопределенной длины. Как видно, длина массива не имеет для функции никакого значения, потому что в С проверка границ массива не выполняется. Эту функцию можно объявить даже так:
void func1(int x[32])
{
  /* ... */
}
И при этом программа будет выполнена правильно, потому что компилятор не создает массив из 32 элементов, а только подготавливает функцию к приему указателя. 

Строки

Одномерный массив наиболее часто применяется в виде строки символов. Строка — это одномерный массив символов, заканчивающийся нулевым символом. В языке С признаком окончания строки (нулевым символом) служит символ '\0'. Таким образом, строка содержит символы, составляющие строку, а также нулевой символ. Это единственный вид строки, определенный в С.
На заметкуВ C++ дополнительно определен специальный класс строк, называющийся String[1], который позволяет обрабатывать строки объектно-ориентированными методами. Стандарт С не поддерживает String.
Объявляя массив символов, предназначенный для хранения строки, необходимо предусмотреть место для нуля, т.е. указать его размер в объявлении на один символ больше, чем наибольшее предполагаемое количество символов. Например, объявление массива str, предназначенного для хранения строки из 10 символов, должно выглядеть так:
char str[11];
Последний, 11-й байт предназначен для нулевого символа.
Записанная в тексте программы строка символов, заключенных в двойные кавычки, является строковой константой, например,
"некоторая строка"
В конец строковой константы компилятор автоматически добавляет нулевой символ.
Для обработки строк в С определено много различных библиотечных функций. Чаще всего используются следующие функции:
Имя функцииВыполняемое действие
strcpy(s1,s2)Копирование s2 в s1
strcat(s1,s2)Конкатенация (присоединение) s2 в конец s1
strlen(s1)Возвращает длину строки s1
strcmp(s1,s2)Возвращает 0, если s1 и s2 совпадают, отрицательное значение, если s1<s2 и положительное значение, если s1>s2
strchr(s1,ch)Возвращает указатель на первое вхождение символа ch в строку s1
strstr(s1,s2)Возвращает указатель на первое вхождение строки s2 в строку s1
Эти функции объявлены в заголовочном файле <string.h>. Применение библиотечных функций обработки строк иллюстрируется следующим примером:
#include <stdio.h>
#include <string.h>

int main(void)
{
  char s1[80], s2[80];

  gets(s1);
  gets(s2);

  printf("Длина: %d %d\n", strlen(s1), strlen(s2));

  if(!strcmp(s1, s2)) printf("Строки равны\n");

  strcat(s1, s2);
  printf("%s\n", s1);

  strcpy(s1, "Проверка.\n");
  printf(s1);
  if(strchr("Алло", 'e')) printf(" л есть в Алло\n");
  if(strstr("Привет", "ив")) printf(" найдено ив ");

  return 0;
}
Если эту программу выполнить и ввести в s1 и в s2 одну и ту же строку "Алло!", то на экран будет выведено следующее:
Длина: 5 5
Строки равны
Алло!Алло!
Проверка,
л есть в Алло
найдено ив
Следует помнить, что strcmp() принимает значение ЛОЖЬ, если строки совпадают (хоть это и несколько нелогично). Поэтому в тесте на совпадение нужно использовать логический оператор отрицания ! как в предыдущем примере.


[1]CString в среде Visual C++.



Комментарии