Статические локальные переменные 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Статические локальные переменные



Лекция 1.

План

1. Определение алгоритма

2. Классификация языков

3. Блоки

4. Применение языка С

5. Типичный вид С-программ

6. Основные термины

 

Алгоритм – точное предписание, которое задаёт вычислительный процесс, начинающийся с произвольного исходного данного (из некоторой совокупности возможных для данного алгоритма данных) и направленный на получение полностью определяемого этим исходным данным результата.

 

 

Как правило, для данного алгоритма можно выделить 7 характеризующих его параметров:

 

1) совокупность возможных исходных данных;

2) совокупность возможных результатов;

3) совокупность возможных промежуточных результатов;

4) правило начала;

5) правило непосредственной переработки;

6) правило окончания;

7) правило извлечения результата.

 

Высокий уровень Ада Модула-2 Паскаль COBOL Фортран Бейсик
Средний уровень С++ С FORTH Макро Ассемблер
Низкий уровень Ассемблер
Структурированные   Паскаль Ада С++ С Модула-2 Неструктурированные   Фортран Бейсик COBOL

 


Блоки

 

Блок кода – это группа логически связанных операторов, которая воспринимается как модуль.

 

if (x<10) {

printf(“too low, try again”);

count++;

}

 

Применение языка С

 

· Операционные системы

· Интерпретаторы

· Редакторы

· Ассемблерные программы

· Компиляторы

· Процессоры баз данных

Типичный вид С-программ

 

глобальные объявления возвращаемый_тип main(список параметров) { последовательность операторов } возвращаемый_тип f1(список параметров) { последовательность операторов } . . . возвращаемый_тип fN(список параметров) { последовательность операторов }

Обозрение терминов

 

Исходный код Текст программы, который можно читать. Обычно подразумевается сама программа. Исходный код вводится в компилятор.
Объектный код Результат перевода исходного кода в машинный. Объектный код вводится в компоновщик.
Компоновщик Программа, компонующая отдельные откомпилированные функции в одну программу. Объединяет функции стандартной библиотеки С с кодом, написанным программистом.
Библиотека Файл, содержащий стандартные функции, которые могут использоваться программой. Данные функции содержат все операции ввода-вывода, а также другие полезные подпрограммы.
Время компиляции События, возникающие при компиляции программы
Время выполнения События, возникающие при выполнении программы

 

Идентификаторы

 

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

Корректные Некорректные
count test23 high_balance 1count hi!there high..balance

 

Типы данных

 

char

int

float

double

void

 

Модификаторы типов

 

signed

unsigned

long

short

Объявление переменных

 

Все переменные должны объявляться перед использованием.

 

тип список_переменных;

 

Локальные переменные

 

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

 

Формальные параметры

/* возвращает 1, если с является частью строки s; в противном случае – 0 */

int is_in(char *s, char c)

{

while(*s)

if(*s==c) return1;

else s++;

return 0;

}

 

Константы

Тип данных Пример константы
char int long int short int float double ‘a’ ‘\n’ ‘9’ 1 123 21000 -234 35000L -34L 10 -12 90 123.23F 4.34e-3F 123.23 12312.333 -0.987654

 


Лекция 2.

План

1. Глобальные переменные

2. Модификаторы доступа

3. Спецификаторы хранения

4. Оператор присваивания

5. Инициализация переменных

6. Константы

 

Глобальные переменные

 

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

В следующей программе переменная count объявлена вне функций. Общепринятым является объявление глобальных переменных в начале программы.

 

#include <stdio.h>

void func1(void), func2(void);

int count;

 

int main(void)

{

count = 100;

func1();

return 0;

}

 

void func1(void)

{

func2();

printf(“count is %d”, count); /* выведет 100 */

}

 

void func2(void)

{

int count;

for(count=1; count<10; count++)

putchar(‘ ‘);

}

 

Хотя ни main(), ни func1() не объявляют переменную count, но они оба могут её использовать, func2() объявляет локальную переменную count. Когда func2() обращается к count, она обращается только к локальной переменной, а не к глобальной.

 

Модификаторы доступа

 

С имеет 2 типа модификаторов, которые используются для контроля за способом доступа или модификации переменных. Эти модификаторы называются const и volatile.

Переменные типа const не могут изменяться операторами программы. Например:

 

const int a;

создаст целочисленную переменную, называемую а, которая не может быть модифицирована в программе. Она может использоваться в других типах выражений. Переменная с модификатором const получает своё значение или при инициализации, или каким-либо аппаратно-зависимым способом. Например, нижеприведённая строка присваивает count значение 100:

 

const int count = 100;


Помимо инициализации константа не может быть модифицирована программой.

Модификатор volatile используется для сообщения компилятору о возможности изменения значения способами, не определёнными в программе. Это важно, поскольку компилятор автоматически оптимизирует некоторые выражения, делая предположения, что содержимое переменных не изменяется в выражениях. Также некоторые виды оптимизации могут изменять порядок вычисления выражений во время процесса компиляции. Модификатор volatile предотвращает возникновение данных изменений.

Возможно использование этих модификаторов вместе. Например, если предполагается, что 0х30 является адресом порта, содержимое которого изменяется внешним устройством, то следующее объявление предохранит от побочных эффектов:

 

const volatile unsigned char *port = 0x30;

 


Спецификаторы хранения

Имеется 4 спецификатора хранения, поддерживаемые в С. Это

 

extern

static

register

auto

 

Они говорят компилятору, как должны храниться переменные. Спецификаторы предшествуют объявлению переменной. В общем случае это выглядит так:

 

спецификатор_хранения тип имя_переменной;

Extern

Поскольку С позволяет выполнять раздельную компиляцию модулей для большой программы, в целях ускорения компиляции и помощи управлению большими проектами, должны быть способы передачи информации о глобальных переменных файлам программы. Решение заключается в объявлении всех глобальных переменных в одном файле и использовании при объявлении в других файлах слова extern.

 

Файл 1 Файл 2
int x, y; char ch;   int main(void) { … }   void func1(void) { x = 23; } extern int x, y; extern char ch;   void func22(void) { x = y/10; }   void func23(void) { y = 10; }

 

Имеется другой вариант использования extern. Когда используется глобальная переменная внутри функции, находящейся в том же файле, где происходит объявление глобальной переменной, то можно объявлять её как extern.

Static

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

 

Статические глобальные переменные

Когда оператор static применяется к глобальной переменной, он сообщает компилятору о необходимости создания глобальной переменной, которая будет известна только в файле, где она объявлена. Это означает, что, даже если переменная является глобальной, другие подпрограммы в других файлах не будут знать о ней. Таким образом, не возникает побочных эффектов.

 


Auto

Спецификатор auto может быть задан только при определении объектов блока, например, в теле функции. Этим объектам память выделяется при входе в блок и освобождается при выходе из него. Вне блока объекты класса auto не существуют.

 

Register

Спецификатор register просит, чтобы компилятор сохранил переменную способом, позволяющим осуществлять наибыстрейший доступ. Для целых чисел и символов это обычно подразумевает размещение не в памяти, а в регистрах процессора. Для других типов переменных компилятор может использовать другие способы для уменьшения времени доступа. Компилятор может просто проигнорировать данную просьбу.

Нельзя применять register к глобальным переменным. Также, поскольку регистровая переменная может быть сохранена в регистре процессора, нельзя получить адрес регистровой переменной. (Данное ограничение присутствует только в С, но не в С++.)

 

Оператор присваивания

 

Общий вид оператора присваивания следующий:

 

имя_переменной = выражение;


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

 

Многочисленное присваивание

 

С позволяет присваивать нескольким переменным одни и те же значения путём использования многочисленных присваиваний в одном операторе. Например, данный фрагмент программы присваивает переменным x, y, z значение 0:

 

x = y = z = 0;

 

В профессиональных программах переменным часто присваиваются стандартные значения с использованием данного метода.

 


Преобразование типов при присваивании

 

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

 

Инициализация переменных

 

Во время объявления переменных можно сообщить им значение путём помещения знака равенства и константы после имени переменной. Этот процесс называется инициализацией и в общем случае имеет вид:

 

тип имя_переменной = константа;

 

Ниже приведено несколько примеров

 

char ch = ‘a’;

int first = 0;

float balance = 123.23;

 

Глобальные и статические глобальные переменные инициализируются только при запуске программы. Локальные переменные инициализируются каждый раз при входе в блок, где они были объявлены. Статические локальные переменные инициализируются только один раз, а не каждый раз при входе в блок. Глобальные и статические локальные переменные инициализируются 0, если не указано инициализационное значение. Неинициализированные нестатические локальные и регистровые переменные будут иметь неопределённое значение.

 

Строковые константы

 

C поддерживает ещё один тип констант в дополнение к предопределённым типам данных. Это строковые константы. Все строковые константы заключаются в двойные кавычки, например: “this is a test”. Не следует путать строковые константы с символами. Одиночный символ заключается в одинарные кавычки, как например: 'a'. Строки мы рассмотрим позже.

 

Лекция 3.

План

1. Арифметические операторы

2. Операторыотношения и логические операторы

3. Битовые операторы

4. Операторы указания

5. Выражения

6. Операторы управления программой

 

 

Операторы

С имеет множество встроенных операторов. Оператор – это символ, который сообщает компилятору о необходимости выполнения некоторых математических или логических действий. Имеется три больших класса операторов: арифметические, отношения, логические и битовые. Кроме этого, С имеет несколько специальных операторов для частных задач.

 

Арифметические операторы

Приоритет выполнения арифметических операций следующий:

 

высший +(унарный плюс) – (унарный минус) ++ -- * / %

низший + - (бинарные операторы)

 

Операторы, обладающие одним приоритетом, вычисляются компилятором слева направо. Круглые скобки в С устанавливают наивысший приоритет операций.

 

Битовые операторы

С поддерживает все существующие битовые операторы. Битовые операции – это считывание, установка или сдвиг битов в байте или слове, которые соответствуют стандартным типам языка С char и int. Битовые операции не могут использоваться с float, double, long double, void и другими сложными типами.

 

Оператор Действие
& И
| ИЛИ
^ Исключающее ИЛИ
~ Дополнение
>> Сдвиг вправо
<< Сдвиг влево

 

Битовые операторы И, ИЛИ, НЕ используют ту же таблицу истинности, что и их логические эквиваленты, за тем исключением, что они работают побитно. Исключающее ИЛИ имеет следующую таблицу истинности:

 

p q p^q

0 0 0

0 1 1

1 0 1

1 1 0

 

Битовое И чаще всего используется для обнуления битов. То есть любой бит установленный в 0, вызывает установку соответствующего бита в другом операнде в также в 0. Например, следующая функция читает символы из порта модема, используя функцию read_modem(), и сбрасывает бит чётности в 0.

 

char get_char_from_modem(void)

{

char ch;

ch = read_modem();

return (ch & 127);

}

 

Чётность отображается старшим битом, который устанавливается в 0 с помощью битового И, поскольку 7 младших бит равны 1.

 

Оператор?

С имеет очень мощный оператор, который можно использовать вместо if-else. Оператор? имеет следующий вид:

 

выражение1? выражение2: выражение3

 

Оператор? работает следующим образом: вычисляется выражение1, если оно истинно, то вычисляется выражение2 и всё выражение получает это значение, если ложно, то вычисляется выражение 3 и всё выражение получает это значение. Например:

 

x = 10;

y = x>9? 100: 200;

 

В данном примере y получает значение 100. Если бы х было меньше либо равно 9, то у получила бы значение 200.

Операторы указания & и *

Указатель – это адрес переменной в памяти. Указатель на переменную – это переменная, специально созданная для хранения указателя на объект определённого типа. Зная адрес переменной, можно существенно упростить работу некоторых программ. Указатели имеют три главных назначения в С:

 

1. Предоставляют быстрое обращение к элементам массива.

2. Позволяют функциям модифицировать передаваемые параметры.

3. Поддерживают динамические структуры данных.

 

Первый оператор - &. Это унарный оператор, возвращающий адрес операнда в памяти. Например:

 

m = &count;


помещает в m адрес переменной count.

Второй оператор – это *, дополняющая &. Это унарный оператор, возвращающий значение переменной по указанному адресу. Например:

 

q = *m;

 

Переменные, содержащие адреса или указатели, должны объявляться путём помещения * перед именем переменной. Например, для объявления указателя ch на символ, следует написать

 

char *ch;

 

Здесь ch - это не символ, а указатель на символ. Тип данных, на который указывает указатель, называется базовым типом указателя.

Ниже операторы * и & используются для занесения числа 10 в переменную target:

 

#include <stdio.h>

 

int main(void)

{

int target, source;

int *m;

source = 10;

m = &source;

target = *m;

printf(“%d”, target);

return 0

}

Оператор sizeof

 

sizeof – это унарный оператор, возвращающий длину в байтах переменной или типа, помещённого в скобки. Например:

 

float f;

 

printf(“%f ”, sizeof f);

printf(“%d”, sizeof(int));

 

выдаёт 4 4. (Предполагается использование 32-битных целых).

 

Выражения

Выражения в С – это любая допустимая комбинация операторов, констант и переменных.

 

Преобразования типов в выражениях.

Компилятор преобразует все выражения к типу большего операнда.

1. Все переменные типа char short int преобразуются к типу int. Все переменные типа float – к типу double.

2. Если один из пары операндов имеет тип long double, другой операнд также преобразуется к типу long double. Иначе, если один из операндов имеет тип double, другой операнд также преобразуется к double. Иначе, если один из операндов имеет тип long, другой операнд также преобразуется к типу long. Иначе, если один из операторов имеет тип unsigned, другой операнд также преобразуется к типу unsigned.

Истина и ложь в С

Большинство операторов управления программой основываются на проверке условий, определяющих, какого рода действие необходимо выполнить. В результате проверки условий можно получить истину или ложь. В С истине соответствует любое ненулевое значение, лжи соответствует ноль.

Операторы выбора

 

С поддерживает два типа оператора выбора: if и switch. Кроме того, оператор? является иногда альтернативой if.

 

Условный оператор if

Синтаксис полной формы условного оператора:

 

if (логическое выражение) оператор1;

else оператор2;

 

Если логическое выражение истинно, т.е. не равно нулю, то выполняется оператор1, иначе выполняется оператор2.

Синтаксис сокращенной формы условного оператора:

if (логическое выражение) оператор;

Оператор выполняется только в том случае, если логическое выражение не равно нулю, т.е. истинно.

Под логическим выражением понимается совокупность операций отношений и логических операций.

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

Список операторов, заключенный в фигурные скобки, называется блоком.


Лесенка if-else-if

Типичной программной конструкцией является лесенка if-else-if. Она выглядит следующим образом:

 

if(выражение)

оператор;

else if(выражение)

оператор;

else if(выражение)

оператор;

else

оператор;

 

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


switch

 

Синтаксис оператора switch:

switch (выражение)

{

case константное выражение: оператор или группа операторов;

break;

case константное выражение: оператор или группа операторов;

break;

case константное выражение: оператор или группа операторов;

break;

........

defaulf: оператор или группа операторов;

};

Результат вычисленного выражения сравнивается с каждым из константных выражений. Если находится совпадение, то управление передается оператору, связанному с данным case. Исполнение продолжается до конца тела оператора switch или пока не встретится оператор break, который передает управление из тела switch оператору, следующему за switch. Оператор или группа операторов, стоящий после default, выполняется, если выражение не соответствует ни одному из константных выражений в case.

Константные выражения должны быть целого или символьного типа. Если нескольким константным выражениям соответствует один и тот же оператор, то возможна следующая запись:

switch (выражение)

{

case константное выражение:

case константное выражение:

case константное выражение: оператор или группа операторов;

break;

};

 


Лекция 4.

План

  1. Оператор «запятая»
  2. Принудительные преобразования типов
  3. Сокращённые операторы в С
  4. Циклы
  5. Оператор break
  6. Оператор continue
  7. Метки и goto

Оператор «запятая»

Оператор «запятая» используется для связки нескольких выражений. Левая сторона оператора «запятая» вычисляется как не выдающая значения. Значение выражения, находящегося с правой стороны, станет значением разделенного запятыми выражения. Например:

x=(y=3, y+1);

Сначала присваивается 3 переменной y, а затем 4 переменной x. Скобки нужны, поскольку оператор «запятая» имеет более низкий приоритет, чем оператор присваивания.

Принудительные преобразования типов

Имеется возможность заставить выражение принять определённый тип с помощью оператора принудительных преобразований. Эта операция имеет следующий вид:

 

(тип) выражение;


где тип – это один из стандартных типов данных С или определяемый пользователем тип. Например, если необходимо, чтобы выражение x/2 имело тип float (частное со знаками после запятой), следует написать:

 

(float) x / 2

 

Сокращённые операторы в С

С имеет несколько специальных сокращённых операторов, кодирующих некоторые операторы присваивания. Например:

 

х = х + 10;


может быть кратко записано как

 

x +=10;

Циклы

 

В С и других языках программирования циклы позволяют выполнять набор инструкций до тех пор, пока не выполниться некоторое условие. Определены три разных оператора цикла:

 

Итерационный цикл for

 

Стандартный вид цикла for следующий:

for (инициализация_цикла; выражение-условие; список_выражений) оператор;

 

Оператор for имеет три главные части:

a. инициализация_цикла – это место, где обычно находится оператор присваивания, используемый для установки начального значения переменной цикла.

b. выражение-условие – это выражение, определяющее условие работы цикла.

c. список_выражений – это место где определяется характер изменения переменной цикла на каждой итерации.

Эти три важные части должны разделяться точкой с запятой. Цикл for работает до тех пор, пока условие истинно. Когда условие становится ложным, выполнение программы продолжается с оператора, следующего за циклом for.

 

Пример

 

#include <stdio.h>

 

int main(void)

{

int x;

for(x=1; x<=100; x++) printf(“%d ”,x);

return 0;

}

 

В данном примере x является переменной цикла, которая изменяется и проверяется на каждой итерации цикла.

Ниже приведён пример цикла for, повторяющего несколько операторов:

 

for(x=100; x!=65; x-=5) {

z = sqrt(x);

printf(“The square root of %d, %f”, x, z);

}

 

Как sqrt(), так и printf(), вызываются и выполняются пока x не равно 65.

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

 

Вариации цикла for

 

Одна из наиболее типичных вариаций достигается с использованием оператора «запятая», тем самым позволяя иметь две или более переменных цикла.

Например, функция reverse(). Она предназначена для копирования содержимого первого строкового аргумента во второй строковый аргумент в обратном порядке.

 

void reverse(char *s, char *r)

{

int i, j;

 

for(i=strlen(s)-1, j=0; i>=0; j++, i--)

r[i]=s[j];

r[j] = '\0';

}

 

Бесконечный цикл

 

Одним из наиболее интересных аспектов использования цикла for является создание бесконечного цикла. Поскольку не требуется ни одна из частей, можно создать бесконечный цикл путём удаления части проверки условия. Например:

 

for(;;) printf(“this loop will run forever.\n”);

 

While

while (выражение-условие)

тело цикла

 

Тело цикла – это или пустой, или простой, или составной оператор. Выражением-условием может быть любое выражение, имеющее в качестве истины ненулевое значение. Цикл выполняется, пока условие истинно. Когда условие становится ложным, выполняется строка, следующая за циклом.

Следующий пример показывает процедуру, обрабатывающую ввод с клавиатуры, работающую пока не будет введён символ ‘A’:

 

void wait_for_char(void)

{

char ch;

 

ch = ‘\0’;

while(ch!=’A’) ch = getchar();

}

 

Как и цикл for, цикл while сначала выполняет проверку, то есть тело цикла может вообще не выполняться.

Когда необходимо несколько различных условий для окончания цикла while, как правило, используют одну переменную, являющуюся результатом действия этих условий, причём значение этой переменной может устанавливаться в различных частях цикла. Например:

 

void func1(void)

{

int working = 1;

while(working) {

working = procces1();

if (working)

working = process2();

if (working)

working = process3();

}

}

 

Do/while

 

Цикл do/while проверяет условие в конце. То есть, цикл do/while всегда выполняется, хотя бы один раз. Стандартный вид цикла do/while следующий:

do {

последовательность операторов;

} while (выражение-условие);

 

Хотя в фигурных скобках нет необходимости при наличии одного оператора, они обычно используются для улучшения читабельности и устранения недоразумений (у читателя, а не у компилятора) по поводу цикла.

Возможно, наиболее типичным использованием цикла do/while является процедура выбора пунктов меню. Когда набран корректный ответ, она возвращает значение функции. Неправильный ответ приводит к повторному вводу.

 

Пример:

 

void menu(void)

{

char ch;

 

printf(“1. Check Spelling\n”);

printf(“2. Correct Spelling Errors\n”);

printf(“3. Display Spelling Errors\n”);

printf(“ Enter your choice: “);

 

do{

ch = getchar();

switch(ch) {

case ‘1’:

check_spelling();

break;

case ‘2’:

correct_errors();

break;

case ‘3’:

display_errors();

break;

}

} while(ch!=’1’&&ch!=’2’&&ch!=’3’);

}

 

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

 


Оператор break

Оператор break имеет два назначения. Первое – это окончание работы оператора switch. Второе – это принудительное окончание цикла, минуя стандартную проверку условия.

Когда оператор break встречается в теле цикла, цикл завершается и выполнение программы переходит на строку, следующую за циклом.

 

Пример

 

#include <stdio.h>

 

int main(void)

{

int x;

for(x=1; x<100; x++) {

printf(“%d ”,x);

if(x==10) break;

}

 

return 0;

}

Данная программа выводит числа от 0 до 10 включительно и заканчивает работу, поскольку break вызывает немедленный выход из цикла, минуя условие x<100.

 

Оператор continue

 

Работа оператора continue чем-то похоже на работу оператора break. Но вместо форсированного окончания continue переходит к следующей итерации цикла, пропуская оставшийся код тела цикла. Например, следующая процедура выводит только положительные числа:

 

do{

scanf(“%d”, &x);

if(x<0) continue;

printf(“%d “, x);

} while(x!=100);

 

Метки и goto

 

Хотя goto уже давно не рекомендуют использовать, он по-прежнему используется в программах. goto требует наличия меток для работы. Метка – это корректный идентификатор С, завершаемый двоеточием. Метка должна находиться в той же функции, что и goto.

Лекция 5.

План

1. Одномерный массив

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

3. Строки

4. Двумерные массивы

5. Массивы строк

6. Многомерные массивы

7.

Массивы

 

Массив – это совокупность переменных одного типа, к которым обращаются с помощью общего имени. Доступ к отдельному элементу массива может осуществляться с помощью индекса. В С все массивы состоят из соприкасающихся участков памяти. Наименьший адрес соответствует первому элементу. Наибольший адрес соответствует последнему элементу. Массивы могут иметь одну или несколько размерностей.

Массивы тесно связаны с указателями.


Одномерный массив

 

Стандартный вид объявления одномерного массива следующий:

 

тип имя_переменной [ размер ];

 

В С массивы должны определяться однозначно, чтобы компилятор мог выделить под них место в памяти. Здесь тип определяет базовый тип массива и является типом каждого элемента массива. Параметр размер определяет, сколько элементов содержит массив. В одномерном массиве полный размер массива в байтах вычисляется следующим образом:

 

общее число байт = sizeof (базовый тип)* число элементов

 

У всех массивов первый элемент имеет индекс 0. Поэтому, если написать

 

char p[10];


то будет объявлен массив символов из 10 элементов, причём эти элементы адресуются индексом от 0 до 9. Следующая программа загружает целочисленный массив числами от 0 до 9 и выводит его:

 


#include <stdio.h>

 

int main(void)

{

int x[10];

int t;

 

for(t=0; t<10; ++t) x[t] = t;

 

for(t=0; t<10; ++t) printf(“%d ”, x[t]);

 

return 0;

}

В С отсутствует проверка границ массивов. Можно выйти за один конец массива и записать значение в какую-либо переменную, не относящуюся к массиву, или даже в код программы. Работа по предоставлению проверки границ возлагается на программиста.


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

 

Можно создать указатель на первый элемент массива, указав имя массива без индекса. Пусть имеется

 

int sample[10];

 

Можно создать указатель на первый элемент, используя имя sample. Следовательно, следующий фрагмент присваивает переменной p адрес первого элемента sample:

 

int *p;

int sample[10];

 

p = sample;

Можно также получить адрес первого элемента массива с помощью оператора &. Например, sample и &sample[0] приводят к одинаковому результату. Тем не менее в профессиональных программах нет почти нигде &sample[0].


Строки

 

Наиболее типичным представителем одномерного массива являются строки. Хотя С не определяет строкового типа, имеется поддержка строковых операций с помощью функций, имеющихся в любом языке. В С строка определяется как символьный массив произвольной длины, оканчивающийся нулевым символом. Нулевой символ определяется как '\0'. Поэтому необходимо объявлять символьные массивы на один символ больше, чем требуется для хранения самой длинной строки. Например, если необходимо объявить массив s, содержащий десятисимвольную строку, следует написать:

 

char s[11];

 

В результате этого выделяется место в конце строки для нулевого символа.

Не надо добавлять нулевой символ в конец строковой константы, поскольку компилятор С выполняет это автоматически.

С поддерживает множество функций для работы со строками. Наиболее типичными являются strcpy(), strcat(), strlen(), strcmp() со следующими прототипами:

 

char *strcpy(char *s1, const char *s2);

char *strcat(char *s1, const char *s2);

size_t strlen(const char *s1);

int strcmp(const char *s1, const char *s2);

 

Все функции используют заголовочный файл string.h. Функция strcpy() копирует строку, на которую указывает s2, в строку на которую указывает s1. Функция возвращает s1. Функция strcat() выполняет конкатенацию строки, на которую указывает s1, и строки на которую указывает s2. Она также возвращает s1. Функция strlen() возвращает длину строки, на которую указывает s1. Тип данных size_t определён стандартом для адресов и в настоящее время для большинства машин определяется как беззнаковое длинное целое. Функция strcmp() сравнивает строки s1 и s2. Она возвращает 0, если две строки эквивалентны, значение меньше 0, если строка s1 при лексикографическом порядке идет раньше s2 и значение больше 0, если строка s1 при лексикографическом порядке идет после s2.

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


#include <string.h>

#include <stdio.h>

int main()

{

char s1[80], s2[80];

gets(s1); gets(s2);

printf(“lengths: %d %d\n“, strlen(s1), strlen(s2));

if(!strcmp(s1, s2)) printf(“The strings are equal\n”);

strcat(s1, s2);

printf(“%s\n”, s1);

return 0;

}

Если при запуске программы ввести строки “hello” и “hello”, в результате получится:

 

lengths: 5 5

The strings are equal

hellohello

 

Для многих компиляторов существуют безопасные версии функций strcpy() и strcat() - это strcpy_s() и strcat_s(). Чтобы ими полноценно пользоваться необходимо подключить <string.h> и <errno.h>.

errno_t strcpy_s(char * strDestination, size_t sizeInBytes, const char * strSource);

errno_t strcat_s(char * strDestination, size_t sizeInBytes, const char * strSource);

Вторым параметром в этих функциях идет максимальная длина целевой строки. Функции возвращают значение ноль, если параметры корректны и не ноль, если в параметрах содержится ошибка.

 

Двумерные массивы

 

С позволяет создавать многомерные массивы. Простейшим видом многомерного массива является двумерный массив. Двумерный массив – это массив одномерных массивов. Двумерный массив объявляется следующим образом:

 

тип имя_массива [ размер второго измерения ][ размер первого измерения ];

 

В следующем примере в двумерный массив заносятся числа от 1 до 12, после этого массив выводится на экран.


#include <stdio.h>

int main()

{

int t, i, num[3][4];

 

/* загрузка чисел */

for(t=0; t<3; ++t)

for(i=0; i<4; ++i)

num[t][i] = (t*4)+i+1;

 

/* вывод чисел */

for(t=0; t<3; ++t) {

for(i=0; i<4; ++i)

printf(“%d “, num[t][i]);

printf(“\n”);

}

return 0;

}

 

В данном примере num[0][0] имеет значение 1, num[0][1] имеет значение 2, num[0][2] имеет значение 3 и так далее. num[2][3] имеет значение 12.

 

Массивы строк

 

В программировании типично использование массивов строк. Например, процессор ввода в базу данных может проверять команды пользователя в строковом массиве. Для создания массива строк используется двумерный массив символов. Левый индекс определяет число строк, а правый индекс – максимальное число символов в каждой строке. Данный фрагмент кода объявляет массив из 30 строк, каждая может содержать до 79 символов включительно:

 

char str_array [30] [80];

 

Доступ к отдельным строкам очень прост – необходимо написать имя массива только с левым индексом. Например:



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 366; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.221.187.121 (0.384 с.)