1)Указатели. Использование указателей при работе с массивами, при передаче параметров функциям.
Указатели - это переменные, показывающие место или адрес памяти, где расположены другие объекты (переменные, функции и др.). Так как указатель содержит адрес некоторого объекта, то через него можно обращаться к этому объекту.
Унарная операция & дает адрес объекта, поэтому оператор у = &х; присваивает адрес переменной х переменной у. Операцию & нельзя применять к константам и выражениям; конструкции вида &(х+7) или &28 недопустимы.
Унарная операция * воспринимает свой операнд как адрес некоторого объекта и использует этот адрес для выборки содержимого, поэтому оператор z = *y; присваивает z значение переменной, записанной по адресу у. Если
y = &x;;
z = *у;
то z = x.
Объекты, состоящие из знака * и адреса (например, *а), необходимо определить. Делается это, например, так:
int *а, *b, *с;
char *d;
Определение вида char *d говорит о том, что значение, записанное по адресу d, имеет тип char.
Указатели могут встречаться и в выражениях. Если у - указатель на целое, т.е. имело место объявление int *у, то *у может появиться там же, где и любая другая переменная, не являющаяся указателем. Таким образом, следующие выражения вполне допустимы:
*у = 7; заносит число 7 в ячейку памяти по адресу у
*x *=5; увеличивает значение по адресу х в пять раз
(*z)++; добавляет единицу к содержимому ячейки памяти с адресом z
Указатели можно использовать как операнды в арифметических операциях. Если у - указатель, то унарная операция y++ увеличивает его значение; теперь оно является адресом следующего элемента. Указатели и целые числа можно складывать. Конструкция у + n (у - указатель, n - целое число) задает адрес n-гo объекта, на который указывает у. Это справедливо для любых объектов (int, char, float и др.); транслятор будет масштабировать приращение адреса в соответствии с типом, указанным в определении объекта.
Любой адрес можно проверить на равенство (= =) или неравенство (!=) со специальным значением NULL, которое позволяет определить ничего не адресующий указатель.
Указатели и массивы
В языке "C" существует сильная взаимосвязь между указателями и массивами, настолько сильная, что указатели и массивы действительно следует рассматривать одновременно. Любую операцию, которую можно выполнить с помощью индексов массива, можно сделать и с помощью указателей. Вариант с указателями обычно оказывается более быстрым, но и несколько более трудным для непосредственного понимания, по крайней мере, для начинающего. Описание int a[10] определяет массив размера 10, т.е. набор из 10 последовательных объектов, называемых a[0], a[1], ..., a[9]. Запись a[i] соответствует элементу массива через i позиций от начала. Если pa – указатель целого, описанный как int *pa, то присваивание pa = &a[0] приводит к тому, что pa указывает на нулевой элемент массива a; это означает, что pa содержит адрес элемента a[0]. Теперь присваивание x = *pa будет копировать содержимое a[0] в x.
Если ра указывает на некоторый определенный элемент массива a, то по определению pa+1 указывает на следующий элемент, и вообще pa-i указывает на элемент, стоящий на i позиций до элемента, указываемого pa,а pa+i на элемент, стоящий на i позиций после. Таким образом, если pa указывает на a[0], то *(pa+1) ссылается на содержимое a[1], pa+i - адрес a[i], а *(pa+i) – содержимое a[i].
2) Оператор goto. Рекомендации по его использованию и примеры.
Действие передачи управления оператору указано меткой. Метки образуются по правилам, что и идентификаторы и отделяются от оператора «:».
Рекомендации: пользуйтесь goto как можно реже, он затрудняет компилятору оптимизацию кода, а также усложняет чтение и сопровождение программы.
Ограничения по использованию goto:
1) Избегайте входа внутрь блока из вне. Язык это разрешает, но если выше точки входа находились объявления переменных с инициализацией, то значения этих переменных будут мусором.
goto inblock;
…
{ int a=1;
int b=2;
inblock: …
}
2) Не входить внутрь оператора if-else и switch из вне (язык это запрещает).
3) Не входить внутрь циклов из вне.
Пригождение goto:
1) При выходе из глубокой вложенности цикла
В двумерном массиве найти первый отрицательный элемент:
for (i=0; i<m; i++)
for (j=0; j<n; j++)
if (a[i][j]<0)
{index i=-i;
index j=-j;
goto label;
}
label; …
2) Уменьшение вложенности
If (усл)
{код
}
3) Если ошибки могут возникать в нескольких местах, а ветвь обработки ошибок значительна.
4) Полезно также использовать goto при переводе программы с неструктурированных языков (basic и др.)
3. Напишите функцию поиска самой длинной цепочки из подряд идущих одинаковых элементов в массиве.
# include <stdio.h>
# include <stdlib.h>
const n=10;
int s[n];
int x[n],maxk=1,j;
void poisk(int a[])
{
for (int i=0;i<n;i++)
{
int k=1;
if (a[i]==a[i+1])
{ j=i;
while (a[j]==a[j+1]) { j++; k++;}
}
if (k>maxk)
{ maxk=k;
for (k=0;i<=j;i++,k++)
x[k]=a[i];
}
}
}
и мой собственный вариант=Ю
#include<stdio.h>
#include<conio.h>
int arr[]={'1','2','4','4','4','4','w','w','32','s','2','3','2','1','2'};
int i,j,k,m,record,recordabs,end;
int n=sizeof(arr)/sizeof(int);
int main()
{
clrscr();
m=0;
recordabs = 0;
for (i=0, j=i+1; j < n; )
{
if (arr[i] == arr[j])
{
record = j-i+1;
if (recordabs < record) {recordabs = record; k = i;}
j++;
}
else {i++;j=i+1;}
}
end = recordabs + k;
printf ("Position = %d; Lenth = %d;\n The string: ",k,recordabs);
for (i=k;i<end;i++)
printf(" %c ",arr[i]);
getch();
}
4. Напишите функцию, выдающую на экран битовое представление заданного вещественного числа.
#include<conio.h>
#include<stdio.h>
void preds(unsigned char*b)
{
for(int i=7;i>=0;i--)
printf("%d",(*b >> i) & 1);
printf(" ");
}
void main()
{
int i;
float ch=-123.5123421;
unsigned char*b;
clrscr();
b = (unsigned char*) & ch;
for(i=0; i<sizeof(float); i++)
preds(b++);
getch();
}