- •Тема 1. 7
- •Тема 2. 22
- •Тема 3. 41
- •Тема 4. 83
- •Основные временные параметры микропроцессора кр580ик80а
- •Программное обеспечение микропроцессора
- •Команды перемещения данных
- •Представлением операнда
- •Команды переходов ( альтернативные команды )
- •Специальные команды
- •Кодирование программы
- •Архитектура последовательного интерфейса кр580ик51
- •Управления от мп
- •Архитектура программируемого таймера кр580ви53
- •И микропроцессором
- •Архитектура бис параллельного интерфейса кр580вв55
- •Сигналами ппи
- •Архитектура контроллера прямого доступа к памяти кр580вт57
- •Архитектура бис программируемого контроллера прерываний кр580вн59
- •Генератор тактовыхимпульсов кр580гф24
- •Системный контроллер и шинный формирователь кр580вк28
- •Буферные регистры кр580ир82 и кр580ир83
- •Шинные формирователи кр580ва86 и кр580ва87
- •Пример подключения микросхемы кр580ви53 к микропроцессорной системе через контроллер прерываний кр580вн59
- •Пример подключения аналого-цифрового преобразователя.
- •Пример совместного использования микросхем комплекта для управления технологическим процессом.
- •Декларирование объектов
- •Структура программы
- •Константы
- •Арифметические операции
- •Преобразование типов операндов арифметических операций
- •Побитовые логические операции, операции над битами
- •Функции вывода информации
- •Стандартные математические функции
- •Условные операторы
- •If (условие ) оператор1;
- •If (условие1) оператор1;
- •Пример использования оператора if
- •Циклические операторы while и do–while
- •Пример использования оператора for
- •Строки, как одномерные массивы символов
- •Указатели и операции над адресами
- •Операция sizeof
- •Указатели на указатели
- •Пример динамического размещения одномерного массива в с
Операция sizeof
Связь указателей и массивов
Указатели и массивы в языке С тесно связаны между собой. Имя массива является указателем на его первый элемент, т.е. для массива
int p[10],
p
p[0]
имеют одинаковые значения, т.к. адрес первого (с индексом 0) элемента массива это адрес начала последовательно расположенных элементов массива. Рассмотрим обращение к элементам массива на примере. Пусть объявлены - массив из 100 бъектов типа float и указатель на объект типа float:
float p[100];
float *q;
int i;
если выполнить операцию q=p;
то обращения к элементу массива p: p[i] *(q+i) и *(p+i) эквивалентны.
Таким образом, для любых указателей можно использовать две эквивалентные формы выражений для доступа к элементам массива: q[i] и *(q+i). Первая форма удобнее для читаемости текста, но вторая обычно эффективнее по быстродействию программы.
Очевидна эквивалентность выражений
&q[0] <-> &(*q) <-> q // адрес нулевого элемента массива
*q <-> q[0] // значение нулевого элемента массива
Для определения размера памяти, необходимого для размещения объектов в языке С используется унарная операция:
intsizeof(параметр);
параметр – тип объекта или его идентификатор (только не имя функции). Операция sizeof возвращает размер памяти в байтах, отводимый под объект.
Если указан идентификатор сложного объекта (массив, структура, объединение), то результатом является размер всего сложного объекта.
Например:
sizeof(int) результат 2 байта,
int b[5]; sizeof(b) результат 10 байт;
int c[3][4]; sizeof(c) результат 24 байта.
Нарпимер:
char *m[]={"Winter","Spring","Summer","Automn"};
k=sizeof(m)/sizeof(*m);
printf("\n Количество строк = %d",k);
Пример 1: Упорядочить по алфавиту массив строк (не более 20) длиной не более 10 символов в каждой:
#include<conio.h>
#include<stdio.h>
#include<string.h>
void main()
{
char s[20][10],r[10];
int i,j,n;
clrscr();
puts(" Веди количество слов \n";
scanf(“%d”,&n);
for(i=0;i<n;i++)
scanf("%s",&s[i]);
for(i=0;i<(n-1);i++)
for(j=(i+1);j<n;j++)
if(strcmp(s[i],s[j])>0)
{
strcpy(r,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],r);
}
for(i=0;i<n;i++)
printf("\n %s",s[i]);
getch();
}
Пример 2: Проверить, является ли введенная строка полиндромом (справа-налево читается также как и слева-направо).
#include <stdio.h>
#include <string.h>
#include <conio.h>
void main(void)
{
char *s,*s1; // Обьявление строки указателем
int i, k;
clrscr();
puts(" Введите исходную строку");
gets(s);
k=strlen(s);
puts("РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ\n");
for (i=0; i<k; i++)
printf("%c",s1[i]=s[k-i-1]); // Переворачиваем строку s
s1[k]=’\0’; // Устанавливаем конец строки
printf(“ %s\n”,strcpy(s1,s) ? ” YES - Polindrom!”:” NO !”)
printf("\n Press any key...");
getch();
}
Указатели на указатели
Массивы указателей
Пример программы
Краткие теоретические сведения
Многомерные массивы, динамическое распределение памяти
Кроме одномерных массивов возможна работа с многомерными массивами. Объявление многомерного массива:
<тип><имя>[<размер 1 >][<размер 2 >]…[<размер N>]={{список начальных значений}, {список начальных значений},…};
Наиболее быстро изменяется последний индекс элементов массива, поскольку многомерные массивы размещаются в памяти компьютера в последовательности столбцов.
Например, элементы двухмерного массива b[2][1] размещаются в памяти в следующем порядке:
b[0][0], b[0][1], b[1][0], b[1][1], b[2][0], b[2][1].
Следующий пример иллюстрирует определение массива целого типа, состоящего из трех строк и четырех столбцов, с инициализацией начальных значений:
int a[3][4] = {{0,1,2,0},{9,-2,0,0},{-7,1,6,8}};
Если в какой-то группе {…} отсутствует значение, то соответствующему элементу присваивается 0. Предыдущий оператор будет эквивалентен следующему определению:
int a[3][4] = {{0,1,2},{9,-2},{-7,1,6,8}};
Создать двумерный массив целых чисел NxM (N и M не более 50), используя функцию rand и вывести на экран в форме матрицы, N,M ввести с клавиатуры:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define rnd (rand()/ 32768.0) // rand - генератор случайных чисел от 0 до int, rnd – от 0 до 1
void main(void)
{ int i,j,n,m,a[50][50];
puts(“\n Input n, m:”); scanf(“%d %d”,&n,&m);
printf(“\n Array a \n”);
for(i=0; i<n; i++)
for(j=0; j<m; j++) {
a[i][j]=rnd*10-5; // диапазон от –5 до 5
printf(“%d%c“, a[i][j], (j= =m-1)?’\n’:’ ‘);
}
getch();
}
В языке С/C++ можно использовать массивы указателей, элементы которых содержат, как правило, указатели на строковые данные. Объявляется такой массив например так: char *m[5]. Здесь массив m[5] – массив, который может содержать пять адресов данных типа char.
Массив указателей можно при объявлении инициализировать, т.е. назначать его элементам конкретные адреса заданных строк.
В качестве примера приведена программа, формирующая массив указателей с одновременной инициализацией его элементов. Программа распечатывает номер строки, ее адрес и значение.
#include <stdio.h>
#include <conio.h>
void main(void)
{
int i,k;
char *m[]={"Winter","Spring","Summer","Automn"};
k=sizeof(m)/sizeof(*m);
printf("\n Количество строк = %d",k);
for(i=0; i<k; i++)
printf("\n Номер - %d; Адрес - %p; Строка: %s", i+1, m[i], m[i]);
getch();
}
В результате получим:
Количество строк = 4
Номер - 1; Адрес - 0042007C; Строка: Winter
Номер - 2; Адрес - 00420074; Строка: Spring
Номер - 3; Адрес - 0042006C; Строка: Summer
Номер - 4; Адрес - 00420064; Строка: Automn
Конкретные значения адресов зависят от ряда причин: архитектура компьютера, тип и размер оперативной памяти и т.д.
Связь указателей и массивов с одним измерением справедливо и для массивов с большим числом измерений. Например, рассмотрим двумерный массив
float m[5][10];
Если рассматривать его как массив пяти массивов размерностью по десять элементов каждый, то очевидна схема его размещения в памяти - последовательное размещение «строк» элементов. Обращению к элементам m[i][j] соответствует эквивалентное выражение *(*(m+i)+j), а объявление этого массива указателем будет:
float **m;
Таким образом, имя двумерного массива - имя указателя на указатель.
Например, двухмерный массив m(3х4) компилятор рассматривает как массив трех указателей, каждый из которых указывает на начало массива со значениями размером по четыре элемента каждый (рис. 1).
|
m |
|
значения |
|
|
|
|
Ука- |
m[0] |
→ |
m[0][0] |
m[0][1] |
m[0][2] |
m[0][3] |
*(*(m+i)+j) |
за- |
m[1] |
|
m[1][0] |
m[1][1] |
m[1][2] |
m[1][3] |
|
тели |
m[2] |
|
m[2][0] |
m[2][1] |
m[2][2] |
m[2][3] |
|
рис. 1
Cхема размещения такого массива в памяти - последовательное (друг за другом) размещение строк - одномерных массивов со значениями.
Аналогичным образом можно установить соответствие между указателями и массивами с произвольным числом измерений. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:
int a=5;
int *p1=&a;
int **pp1=&p1;
int ***ppp1=&pp1;
Теперь присвоим целочисленной переменной а новое значение, например 10. Одинаковое присваивание произведут следующие операции:
a=10;
*p1=10;
**pp1=10;
***ppp1=10;
Для доступа к области памяти, отведенной под переменную а можно использовать и индексы. Справедливы следующие аналоги:
*p1 равносильно p1[0]
**pp1 равносильно pp1[0][0]
***ppp1 равносильно ppp1[0][0][0]
Таким образом, указатели на указатели – это имена многомерных массивов.
Очевидна эквивалентность выражений:
&name[0][0] <-> &(**name) <-> name // адрес нулевого элемента матрицы
**name <-> name[0][0] // значение нулевого элемента матрицы
Пример программы:
#include <stdio.h>
int x0[4]={ 1, 2, 3, 4};
int x1[4]={11,12,13, 14}; // Декларация и инициализация
int x2[4]={21,22,23, 24}; // массивов целых чисел
int *y[3]={x0, x1, x2}; // Создание массива указателей
void main(void)
{
int i,j;
for (i=0; i<3; i++)
{
printf("\n %2d)",i);
for (j=0; j<4; j++) printf(" %2d",y[i][j]);
}
}
Результаты работы программы:
0) 1 2 3 4
1) 11 12 13 14
2) 21 22 23 24
Такие же результаты получим и при следующем объявлении массива:
int y[3][4]={{1,2,3,4},{11,12,13,14},{21,22,23,24}}; // Декларация и инициализация матрицы целых чисел
В последнем случае массив указателей на массивы создается компилятором. Здесь собственно данные массива располагаются в памяти последовательно по строкам, что является основанием для объявления y в виде
z[3][4]={ 1, 2, 3, 4, 11,12,13,14, 21,22,23,24}; // Декларация и инициализация матрицы целых чисел
скобочного выражения z[3][4] на z[12] здесь не допускается, так массив указателей в данном случае создан не будет.
