Разделы презентаций


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

Содержание

где в качестве выступают ключевые слова, определяющие тип значений, хранимых по адресу, задаваемому переменной-указателем. Примеры:int *px, qy, *tq;char *str0, string1;short l, *k, z;В первом операторе идентификаторы px и

Слайды и текст этой презентации

Слайд 1ЛЕКЦИЯ №6
ЯЗЫК ПРОГРАММИРОВАНИЯ СИ
(ПРОДОЛЖЕНИЕ)


Представлен материал, который имеет отношение к основам

программирования на алгоритмическом языке СИ (рассматриваются указатели и массивы, передача

параметров по ссылке и т.д.). Приводятся примеры программ, иллюстрирующие работу с указателями и массивами

Указатели
Ссылки и адреса. Как уже упоминалось ранее, указатель – это адрес памяти. При этом пользователь должен помнить, что значение указателя сообщает о том, где размещен объект, но ничего не говорит о самом объекте.
В языке СИ символ ‘*’ применяется для задания указателя на какую-либо переменную. Например, оператор описания
float *fx;
обозначает то, что переменная fx является ссылкой на вещественное (переменная с именем fx хранит адрес какой-то другой переменной, принимающей значение типа float).
В соответствии с основным правилом языка СИ все переменные типа "указатель", используемые в программе, должны быть описаны с помощью оператора следующего вида:
<тип> *имя;

ЛЕКЦИЯ №6ЯЗЫК ПРОГРАММИРОВАНИЯ СИ(ПРОДОЛЖЕНИЕ)Представлен материал, который имеет отношение к основам программирования на алгоритмическом языке СИ (рассматриваются указатели

Слайд 2
где в качестве выступают ключевые слова, определяющие тип

значений, хранимых по адресу, задаваемому переменной-указателем.
Примеры:
int *px,

qy, *tq;
char *str0, string1;
short l, *k, z;
В первом операторе идентификаторы px и tq являются ссылками на целое, во втором имя переменной str0 – указателем на символьное, в третьем k является указателем на короткое целое.
Над переменными-указателями в СИ определены операции. Наиболее важная из них – операция обращения по адресу * (иначе ее называют операцией снятия ссылки) и операция определения адреса &. С помощью операции обращения по адресу можно использовать задаваемый адрес для выборки содержимого ячейки, определяемой им. Так, в соответствии с первым оператором описания, из приведенного выше примера можем записать
qy = *tq;
Здесь переменной qy присваивается значение содержимого ячейки памяти ПЭВМ, на которую указывает переменная tq.
Операция же определения адреса & дает адрес памяти операнда, на который она действует. Операндом этой операции всегда должна быть переменная, например:
px = &qy;
Записи вида &(qy+5) или &9 недопустимы. Согласно правилам действия описанных операций справедливо следующее:




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

Слайд 3k = &z;
l = *k;
Причем данные два оператора по своему

действию эквивалентны одному оператору присваивания
l = z;
Итак, операции * и

& позволяют Вам определять значения переменных-указателей и считывать значение из ячейки с адресом, который определяется ими.
Для того чтобы понять работу со ссылками и введенными ранее операциями, проанализируем результаты, получаемые с помощью приведенной далее программы:
Программа 19:
#include
void main (void)
{
int x, y, *px, *py;
void pr01 (int, int, int *, int *);
x = 100;
y = 200;
px = &x;
py = &y;
printf ("\n");
pr01 (x, y, px, py);
py = px;
y = x;


k = &z;l = *k;Причем данные два оператора по своему действию эквивалентны одному оператору присваиванияl = z;Итак,

Слайд 4

pr01 (x, y, px, py);
}
void pr01

(int x, int y, int *px, int *py)
{

printf ("Значение x = %d и значение y = %d\n",x,y);
printf ("Значение адреса x = %p
и значение адреса y = %p\n",px,py);
  }
Программа первый раз выведет на экран дисплея с помощью функции pr01 такую информацию:
Значение x = 100 и значение y = 200
Значение адреса x = FFF4 и значение адреса y = FFF2
Во второй раз появится информация вида
Значение x = 100 и значение y = 100
Значение адреса x = FFF4 и значение адреса y = FFF4
Инициализация ссылок. Как уже упоминалось ранее, необходимы определенные навыки и осторожность, аккуратность при работе со ссылками. В большинстве случаев ошибки при работе со ссылками обусловлены инициализацией (присвоением начальных значений) переменных-указателей. Ошибки такого рода могут приводить к серьезным последствиям.
В качестве примера рассмотрим простейшую программу.
pr01 (x, y, px, py); }void pr01 (int x, int y, int *px, int

Слайд 5
Программа 20:
#include
/* Программа с

ошибкой */
/* Где она скрыта? */


void main (void)
{
int *s, *t, f, q;
/* s = &q; Ошибка здесь (активизируйте оператор) */
*s = 5;
f = 5;
t = &f;
q = f;
printf ("\n");
printf ("Выделяемая память для s = %d\n", sizeof(s));
printf ("Указатель s = %p\n", s);
printf ("Значение по адресу s = %d\n", *s);
printf ("Адрес переменной f = %p\n", &f);
printf ("Адрес переменной q = %p\n", &q);
printf ("Значение по адресу t = %d\n", *t);
}
Программа 20:#include /*  Программа с ошибкой  *//*   Где она скрыта?

Слайд 6 Она выдаст на экран сообщение:

Выделяемая память для s

= 2
Указатель s = 0000
Значение по адресу s = 185
Адрес переменной f = FFF4
Адрес переменной q = FFF2
Значение по адресу t = 5
Согласно тексту данной программы указатели s и t заданы так, что они указывают на переменные типа int, а переменные и объявлены целыми (int). Оператор *s = 185; означает, что по адресу, определяемому переменной-указателем s, помещается значение 185 (поскольку в нем операция * используется как операция снятия ссылки). Далее переменной f присваивается значение 5. Потом с помощью оператора t = &f указателю t присваивается значение адреса переменной f, что с точки зрения синтаксиса языка СИ вполне справедливо. Ссылка t указывает на тип int (т. е. содержит адрес переменной целого типа). По этому адресу уже занесено значение 5 оператором f = 5. Следовательно, значение указателя t со снятой ссылкой *t равно 5. Программа при помощи первого обращения к функции printf выведет на экран монитора строку
Выделяемая память для s = 2
Так как в ней используются близкие указатели, то для их хранения будет отведено по два байта. Затем выводится адрес s в виде целого без знакового числа и за ним значение, помещенное по этому адресу, а именно
Значение по адресу s = 185
Она выдаст на экран сообщение:         Выделяемая

Слайд 7Далее идут сообщения об адресах переменных f и q и

c помощью последнего вызова функции printf выводится значение указателя со

снятой ссылкой *t, равное 5.
Однако в данной программе имеется серьезная ошибка, которая может нарушить нормальную работу компьютера. Укажем каким образом она проявляется. Данная ошибка связана с тем, что в программе описан указатель s на переменную типа int. В таком случае компилятор отводит память в два байта для хранения адреса. Однако сама переменная, значение которой должно храниться по этому адресу, не описана и, следовательно, компилятор не отведет соответствующего объема памяти для хранения ее значения. Так как значением является целое число, то для его хранения необходимо два байта оперативной памяти. В подобной ситуации, когда программист хочет по адресу, описываемому ссылкой, поместить целое значение, как в нашем примере, то он сам он сам должен позаботиться о выделении необходимого объема памяти для этой цели. Таким образом, ответственность за инициализацию указателей ложится на самого программиста.
Представленный пример демонстрирует то, что существует проблема инициализации указателей, которую в любой конкретной программе, решающей некоторую прикладную задачу, обязан решать сам программист.
И, наконец, основной вывод, вытекающий из рассмотренного примера, состоит в том, чтобы пользователь (программист) усвоил и надежно зафиксировал в своей памяти то, что любое описание переменной-указателя в программе не приводит к его инициализации разумным значением и также к резервированию памяти для значения переменной, хранящейся по адресу, указанному им.
Далее идут сообщения об адресах переменных f и q и c помощью последнего вызова функции printf выводится

Слайд 8 Сама проблема задания начального значения переменной-указателю, не

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

Первый способ состоит в том, что переменную указатель можно описать как статическую переменную (static). Тогда ей автоматически присваивается нулевой адрес памяти. Кроме того, программист, перед тем как начнет пользоваться указателем, обязан выделить память под значение, которое будет храниться по этому адресу.
Второй способ основан на том, чтобы указателю присвоить адрес уже описанной переменной. Поскольку компилятор отводит память в момент описания, то описанная выше процедура гарантирует, что необходимый объем памяти будет автоматически отведен. Естественно, что после проведения операции снятия ссылки над таким указателем его значение будет совпадать со значением переменной, адрес которой присваивался указателю.
Третий способ таков: указателю присваивается значение другого указателя, который к этому моменту уже инициализирован. При этом одному адресу памяти как бы даются разные имена (идентификаторы указателей). Если значение, на которое будут ссылаться оба указателя, изменится с помощью оператора присваивания, где используется один из указателей, то изменится и значение, получаемое при помощи другого указателя.
Рассмотренная в последнем случае ситуация называется двойным указанием (один объект имеет два различных имени) и может приводить к определенным проблемам. Рассмотрим до некоторой степени следующий искусственный пример, иллюстрирующий возможные неприятности, которые обусловлены двойным указанием.
Сама проблема задания начального значения переменной-указателю, не противоречащему смысловому содержанию решаемой задачи, может быть

Слайд 9 Программа 21:
#include
#include
void main (void)
{

extern void printval (int , int , int);

int *aa = (int *) malloc (sizeof (int)),
*bb = (int *) malloc (sizeof (int)),
*cc = (int *) malloc (sizeof (int)),
*aa = 144;
*bb = 155;
*cc = 166;
printval (*aa, *bb, *cc);
*cc = *aa;
printval (*aa, *bb, *cc);
bb = aa; /* Двойное указание */
printval (*aa, *bb, *cc);
*aa = -144;
*bb = -155;
*cc = -166;
printval (*aa, *bb, *cc);
printf ("\n");
}
Программа 21:#include #include void main (void) {  extern void printval (int , int

Слайд 10void printval (int a, int b, int c)
{

printf ("\n a = %d b = %d c =

%d", a, b, c);
}
Оператор описания типа int *aa = (int *) malloc (sizeof (int)) приводит к тому, что переменная aa описана, как указатель на целое, и начальное значение адреса этого указателя равно адресу, которое возвращается функцией malloc, содержащейся в библиотеке .
Результаты работы программы таковы. При первом вызове функции printval будет выведена следующая информация:
a =144 b = 155 c = 166
в соответствии с тремя операторами присваивания, выполненными до этого момента.
Выполнение оператора *cc = *aa приведет к тому, что значения *cc и *aa будут одинаковы, и поэтому в результате второго обращения к функции printval получим
a =144 b = 155 c = 144
как следует из комментария программы, стоящего после оператора bb = aa, выполнение которого будет обозначать, что переменные-указатели bb и aa имеют одно и то же значение, а именно адрес одной и той же ячейки оперативной памяти. Следовательно, операции снятия ссылки, проведенные над bb и aa, дадут один и тот же результат, о чем свидетельствует информация, полученная при третьем обращении к функции printval
a =144 b = 144 c = 144
Далее в программе проводится обновление значений по адресам соответствующих переменным-указателям aa, bb и cc операторами присваивания, которые меняют
void printval (int a, int b, int c) {  printf (

Слайд 11начальные значения на отрицательные. Однако получается неожиданный результат

a = -155 b

= -155 c = -166
такой результат является следствием работы оператора bb = aa потому, что операторы присваивания *aa = -144 и *bb = -155, выполняемые последовательно, обновляют значение по одному и тому же адресу и, следовательно, значение, равное -155, будет выведено с помощью операции снятия ссылки, применяемой к переменным-указателям aa и bb. Такого рода неожиданные результаты являются следствием двойного указания, что, несомненно, демонстрирует важность процедуры инициализации переменных-указателей, которую программист должен проводить аккуратно и с особой тщательностью.
Четвертый способ задания начального значения указателю основан на использовании функции автоматического распределения памяти malloc из библиотеки . она имеет следующее описание:
void *malloc (int size)
Она отводит size байт памяти. При этом если для запрашиваемой переменной отводимой памяти не достаточно, то она возвращает нулевое значение, в противном случае возвращает указатель на блок выделяемой памяти. После использования выделенной памяти ее необходимо освободить, что осуществляется вызовом функции free, описанной следующим образом
void free (void *block);
Эта функция применяется в паре с функцией malloc.

начальные значения на отрицательные. Однако получается неожиданный результат        a =

Слайд 12 Следующая распространенная ошибка, связанная с указателями непосредственно

связана с присвоением переменной-указателю адресного значения (конкретный адрес какой-либо ячейки

памяти). Компилятор не запрещает такие операции, но, тем не менее, подобными вещами пользоваться нужно аккуратно, поскольку таким образом можно вторгнуться в ту часть оперативной памяти, где храниться информация, обеспечивающая работу операционной системы и тем самым нарушить нормальную работу самого компьютера.
Еще один вид ошибок связан с возвратом адресов автоматических переменных функциями. Это так же может привести к сбою в работе программного обеспечения, установленного на Вашем компьютере.
Отметим, что применение переменных-указателей требует жесткой дисциплины при выполнении правил их использования, а также особой тщательности и внимания при анализе различного рода программных ситуаций.
Ссылки и массивы. Достаточно часто при решении конкретных задач возникает ситуация, когда набор значений одной и той же величины должен выступать в роли одного и того же объекта программы. Известно, что для скалярных величин одному значению в программе соответствует какой-либо идентификатор. Ну, а как же быть выше упомянутом случае? Для этого во всех языках программирования вводится сложный тип данных – массив. Под массивом понимается некоторый однотипный набор значений, который в программе описывается одним именем, а для того, чтобы указать на один из элементов данного набора, как правило, используется индексная переменная. Ее значение определяет порядковый номер элемента в рассматриваемом наборе.
Следующая распространенная ошибка, связанная с указателями непосредственно связана с присвоением переменной-указателю адресного значения (конкретный

Слайд 13 Подобным же образом вводится понятие массива в

языке СИ, однако благодаря наличию указателей возможным стало организовать новую

технологию работы с его элементами.
Согласно основному правилу языка СИ, все переменные должны быть описаны, в том числе и массивы, для которых оператор описания имеет вид
<тип> имя массива [размер массива];
В данной конструкции под словом <тип> понимается одно из ключевых слов, указывающий на тип принимаемых значений элементами массива. Под именем массива следует понимать идентификатор, который как бы выделяет его среди других объектов программы. В квадратных скобках, следующих за идентификатором, указывается размер массива – количество элементов, входящих в него. Приведем примеры операторов описания массивов:
double s[375];
int i[131], k[15];
char text [38], text1 [12];
В первом операторе массив с именем s содержит в себе 375 элементов, которые принимают значения типа double. Компилятор обрабатывая такой оператор, отведет для хранения всех элементов массива память объемом в 3000 байт, так как для хранения одного элемента требуется 8 байт. При обработке второго оператора будут введены в программе два массива, состоящих из 131 и 15 элементов и принимающих целочисленные значения, с именами i и k соответственно. Для хранения всех элементов массива i будет отведена память объемом 262, а для массива k – 30 байт. Как уже говорилось массивы индексируются для того, чтобы обеспечить возможность доступа к его отдельному элементу.
Подобным же образом вводится понятие массива в языке СИ, однако благодаря наличию указателей возможным

Слайд 14 В языке СИ по умолчанию массивы индексируются

с нуля. Так, например, для 375 элементов массива s имеем:

s[0], s[1], …, s[374]. Для того чтобы сослаться на какой-либо j-ый элемент массива, необходимо указать имя массива и следом за ним в квадратных скобках его номер (т. е. j-1). Учитывая что индексация начинается с нуля, имеем s[j-1].
Примеры:
i [35] – тридцать шестой элемент массива i.
text [8] – девятый элемент массива text.
Таким образом, с помощью индексной переменной, принимающей целочисленные значения, можно обращаться в программе к отдельному элементу любого массива. Такая технология работы с массивами и его элементами используется во всех языках программирования высокого уровня: fortran, pascal, basic и другие. Приведем примеры программ, иллюстрирующие такую технологию работы с массивами.
Задача. Требуется найти сумму всех элементов массива, принимающих значения типа float. Количество элементов массива задано.
Программа 22:
#include
#define NSIZE 20 /* Максимальный размер массива */
viod main (void)
{
int i, n;
float s [NSIZE], sum;
printf ("\nВведите количество элементов массива n = ");
l1:scanf )"%d", &n);
В языке СИ по умолчанию массивы индексируются с нуля. Так, например, для 375 элементов

Слайд 15
if ((n NSIZE))
{
printf

("\n0 < n

= ", NSIZE);
goto l1;
}
sum = 0;
for (i=0; i<=n; i++)
{
printf ("Введите элемент массива s[%d] = ", i);
scanf ("%f", &s[i]);
sum = sum + s[i];
}
printf ("\nСумма элементов массива sum = %f", sum);
}
Основная идея алгоритма заключается в том, чтобы организовать цикл, с помощью которого, используя индексную переменную i, программа вводила бы очередной элемент массива и одновременно накапливала бы сумму его элементов в переменной sum.
Другой способ работы с элементами массива основан на использовании указателей. Такая возможность обусловлена тем, что имя массива является константой-указателем на адрес ячейки памяти, занимаемой первым элементом рассматриваемого массива.
if ((n NSIZE))  {   printf (

Слайд 16
Здесь важно усвоить, что имя массива – константа-указатель и ему

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

первого элемента массива) определяется самим компилятором в момент обработки оператора описания массива, и оно уже никогда в процессе работы программы не может изменить свое значение. Данную особенность (связь имени массива со ссылками) нужно четко понимать для того, чтобы грамотно и эффективно использовать ссылки при работе с элементами массива.
В памяти ПЭВМ элементы массива хранятся последовательно, а поскольку начальный адрес массива соответствует первому его элементу, то в соответствии с типом принимаемых значений можно указать (найти) адреса ячеек, где хранятся других элементов массива, кроме первого. Разница в адресах будет кратна количеству байт, отводимых под хранение значения данного типа. Ранее шла речь об одномерных массивах, элементы которых можно описать одной индексной переменной. По аналогии можно ввести многомерные массивы, требующие для своего описания одно имя и несколько индексных переменных. Широкое применение нашли двумерные массивы, математическим аналогом которых являются таблицы значений, или матрицы. Многомерные массивы объявляются следующим образом
<тип> имя массива [размер по 1 инд. пер.][размер по 2 инд. пер.] …[размер по k инд. пер.];
В отличие от описания одномерного массива здесь в квадратных скобках должны указываться размерности по каждой индексной переменной. Рассмотрим такие примеры:
int l [15][10];
float b [35][18][41];
Здесь важно усвоить, что имя массива – константа-указатель и ему нельзя присваивать значение какой-либо другой переменной-указателя. Ее

Слайд 17 В первом операторе объявляется целочисленный массив l, содержащий 150

элементов. Второй оператор вводит трехмерный массив, состоящий из 25830 вещественных

элементов. Укажем порядок следования элементов в памяти ПЭВМ для массивов
float c [3][4];
char tx [2][3][4];
c[0]0[], c[0][1], c[0][2], c[0][3],
c[1][0], c[1][1], c[1][2], c[1][3],
c[2][0], c[2][1], c[2][2], c[2][3]
 и
tx[0][0][0], tx[0][0][1], tx[0][0][2], tx[0][0][3],
tx[0][1][0], tx[0][1][1], tx[0][1][2], tx[0][1][3],
tx[0][2][0], tx[0][2][1], tx[0][2][2], tx[0][2][3],
tx[1][0][0], tx[1][0][1], tx[1][0][2], tx[1][0][3],
tx[1][1][0], tx[1][1][1], tx[1][1][2], tx[1][1][3],
tx[1][2][0], tx[1][2][1], tx[1][2][2], tx[1][2][3]
В частности, имя двумерного массива является указателем на первую строку этого массива.
Представим пример программы, иллюстрирующий работу с двумерными массивами посредством технологии, основанной на индексных переменных. Программа решает задачу о вычислении произведения двух прямоугольных матриц по правилу


В первом операторе объявляется целочисленный массив l, содержащий 150 элементов. Второй оператор вводит трехмерный массив, состоящий

Слайд 18 Программа 23:
#include
#define N 5
#define L 4
#define M

3
void main (void)
{
int i, j, k;

float a[N][L], b[L][M], c[N][M], p;
printf ("\n");
for (i=0; i for (j=0; j {
printf ("Введите элемент a[%d][%d] = ", i, j);
scanf ("%f", &p);
a[i][j] = p;
}
printf ("\n");
for (i=0; i for (j=0; j {
printf ("Введите элемент b[%d][%d] = ", i, j);
scanf ("%f", &p);
b[i][j] = p;
Программа 23:#include #define N 5#define L 4#define M 3void main (void) {  int i,

Слайд 19
}
printf ("\n");
/* Вычисляем элементы матрицы c

*/
for (i=0; i

j++)
{
c[i][j] = 0;
for (k=0; k {
c[i][j] = c[i][j] + a[i][k]*b[k][j];
printf ("Элемент матрицы c[%d][%d} = %f\n",I, j, c[i][j]);
}
}
}
В данной программе в теле первых двух вложенных циклов вводятся элементы матрицы a, вторая группа циклов осуществляет ввод элементов матрицы b, а в последней группе трех вложенных циклов насчитываются элементы матрицы c и выводятся на экран монитора.
Операции над ссылками. Обсудим основные операции над указателями, которые определены в языке СИ. Для этого введем переменные s и ps, описанные оператором
int s, *ps;
} printf (

Слайд 20
Здесь s – переменная целого типа, а p – переменная-указатель

на целый тип. Тогда для снятой ссылки *ps допустимы все

операции, что и для переменной типа int, в частности
s = *ps + 3;
*ps = s;
*ps -= 2;
(*ps)++;
Таким образом, там, где по смыслу должна применяться переменная целого типа, пользователь имеет полное право употреблять вместо нее *ps. Данное правило справедливо для указателей с точностью до типа значений, применяемых переменной, на которую он (указатель) ссылается.
Над указателями также могут выполняться операции целочисленной арифметики. Данная особенность, как правило, связана с использованием массивов в программе. Мы уже знаем, что имя массива – указатель первого его элемента (хранит адрес ячейки, занимаемой им). Допустим, что программа работает с массивом
float d[28], *pd, e;
Оператор
pd = &d[0];
заносит на хранение в переменную с именем pd адрес нулевого элемента массива d, а оператор
e = *pd;
переменной e присваивает значение нулевого элемента массива, используя операцию снятия ссылки. Однако подобные операции можно проделать иначе:
Здесь s – переменная целого типа, а p – переменная-указатель на целый тип. Тогда для снятой ссылки

Слайд 21pd = d;
e = *pd;
поскольку переменная pd указывает на нулевой

элемент массива d, то по определению pd+1 будет указывать на

следующий элемент, а pd+j на j-ый после d [0]. Таким образом, pd+j будет являться адресом j-го элемента массива d, а *(pd+j) соответствовать d[j]. Например, оператор
e = *(pd+j);
эквивалентен следующему:
e = d[j];
аналогичным образом можно использовать имя массива, так как d+j является адресом j-го элемента массива d, и для получения его содержимого применить операцию снятия ссылки *(d+j). В силу данного правила операторы
e = *(d+j);
и
e = d[j];
эквивалентны по своему действию. Адреса различных элементов массива будут отличаться на целое число, кратное количеству байт, которые требуются для хранения одного элемента. Вообще для указателей допустимы операции, представленные в следующей таблице:

pd = d;e = *pd;поскольку переменная pd указывает на нулевой элемент массива d, то по определению pd+1

Слайд 22Таблица 1.2.1
Операции над указателями
Таким образом, описанная группа

операций позволяет манипулировать элементами массивов, используя указатели. Для иллюстрации работы

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

Слайд 23 Программа 24:
#include
#define NSIZE 20 /*

Максимальный размер массива */
void main (void)
{
int

i, n;
float s[NSIZE], sum;
printf ("\nвведите число элементов массива n = ");
l1:scanf ("%d:, &n);
if ((n <= 0) || (n > NSIZE))
{
printf ("\n0 <= n <= %d.", NSIZE);
goto l1;
}
sum = 0;
for (i=0; i {
printf ("Введите элемент массива s[%d] = ", i);
scanf ("%f", s+i);
sum += *(s+i);
}
printf ("\nСумма элементов массива sum = %f\n", sum);
}
Программа 24:#include #define NSIZE 20 /*  Максимальный размер массива  */void main (void)

Слайд 24
Для двумерного массива, объявленного оператором
int date0 [10][15], I, j;
имя массива

date0 является указателем на его первую строку. Выражение вида
*(date0+j)
задает указатель

на строку, отстоящую от первой на j строк. Следовательно, выражение
*(*(date0+i)+j)
эквивалентно более привычному для нас способу обращения к элементу, стоящему в (i+1)-ой строке (j+1)-ом месте, а именно
date0[i][j]
С учетом этого представим новую версию программы 23 о вычислении произведения двух прямоугольных матриц.
Программа 25:
#include
#define N 5
#define L 4
#define M 3
void main (void)
{
int i, j, k;
float a[N][L], b[L][M], c[N][M], p;
printf ("\n");
for (i=0; i for (j=0; j
Для двумерного массива, объявленного операторомint date0 [10][15], I, j;имя массива date0 является указателем на его первую строку.

Слайд 25 {
printf ("Введите элемент

a[%d][%d] = ", i, j);
scanf ("%f",

&p);
*(*(a+i)+j) = p;
}
printf ("\n");
for (i=0; i for (j=0; j {
printf ("Введите элемент b[%d][%d] = ", i, j);
scanf ("%f", &p);
*(*(b+i)+j) = p;
}
printf ("\n");
/* Вычисляем элементы матрицы c */
for (i=0; i for (j=0; j {
*(*(c+i)+j) = 0;
for (k=0; k {
*(*(c+i])+j) += *(*(a+i)+k]*(*(*b+k)+j));
{    printf (

Слайд 26
printf ("Элемент матрицы c[%d][%d} =

%f\n",i, j, *(*(c+i)+j));
}
}
}

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

printf (

Слайд 28К О Н Е Ц

К О Н Е Ц

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика