Допустимо бесконечно большое число различных типов указателей и
char *p;
Переменная р является указателем на символ, т.е. этой переменной должен присваиваться адрес символа.
char **t;
Переменная t -
int a[50];
Переменная а -
char m[7][50];
Переменная m -
char *r[7];
r состоит из указателей на символы.
int (*f)();
f -
Тип данных x[n1][n2]...[nk]
Где x - идентификатор, определяемый в качестве имени ni - x называется i -го измерения имеют индексы от 0 до ni-1. Тип элемента (pointer), типом структуры ( struct ) или типом объединения ( union ). Хотя элементы
int page[10]; /* одномерный массив из 10 элементов, перенумерованный с 0 до 9 */ char line[81]; float big[10][10], sales[10][5][8]; /*двумерный массив и трехмерный массив*/
Ссылки на элемент x делаются с помощью следующего обозначения:
x[i1][i2]...[ik]
где ij - целое выражение, при этом 0<=ij<=nj-1, а nj - максимальное значение j -го индекса x. Например:
page[5] line[i+j-1] big[i][j]
Указывая только первые p индексов, можно ссылаться на k-p -мерный подмассив (p<=k), например,
sales[i] /* ссылка на двумерный подмассив массива sales */ sales[i][j] /* ссылка на одномерный подмассив */ sales[i][j][k] /* ссылка на элемент массива*/
Указателем называется компонент заданного типа, являющийся ссылкой на некоторую область памяти. Определение указателя имеет следующий вид:
тип-данных *id1, *id2, *_, *idn
Тип переменных id1, id2, _, определяется как тип указателей на тип-данных. Эти переменные служат ссылками на объекты типа тип-данных. Этот тип называется
int *pi, *qi;/* указатели на целые объекты */ char *c; /* указатель на символьный объект */
Указатели используются при создании и обработке malloc и calloc. В отличие от заранее определенных объектов, число
Значение 0 может быть присвоено указателям любого типа. Это значение показывает, что данный указатель не содержит ссылки на какой-либо объект. Попытка использовать это значение для обращения к объекту может привести к ошибке, но только в операционных системах с защитой памяти. По соглашению, для обозначения константы с нулевым значением используется идентификатор NULL, описание которого находится в библиотеке stddef.h и является системозависимым.
По стандарту аргументы функций malloc, calloc имеют тип возвращаемого объекта void*.
char *s = (char*)malloc(size); unsigned size; /* объем памяти, который необходимо выделить */ char *s = (char *)calloc(nelem,elsize); unsigned nelem; /* число элементов, для которых нужно выделить память */ unsigned elsize; /* объем памяти, который необходимо выделить для каждого элемента */ /* либо просто заменив char* на void* */ void* calloc(nelem, elsize); unsigned nelem; unsigned elsize;
Обе функции возвращают указатель на выделенную память. Для определения необходимого объема памяти можно использовать оператор sizeof:
sizeof (выражение)
Объем памяти, необходимый для хранения выражения:
sizeof(T)
Объем памяти, необходимый для хранения значений типа T.
Функции malloc и calloc возвращают указатель на созданный
pi = (int *) malloc(sizeof(int));
выделяется память для одного целого значения. Адрес этой области памяти присваивается переменной pi после его преобразования из типа char * (указатель на знак), с которым он возвращается функцией malloc, к типу int * (указатель на целое), т.е. типу переменной pi.
Присваивание значения объекту, ссылка на который задана указателем pi, выполняется с помощью имени указателя *pi, например:
*pi = 55;
Одно и то же значение может быть присвоено более чем одной переменной-указателю. Таким образом, можно ссылаться на alias ). Например, в результате присваивания
qi = pi;
и qi, и pi указывают на один и тот же объект, т.е. они являются
Память, занимаемая free, которая имеет следующую спецификацию:
free(ptr) char *ptr;
Необходимо предпринимать меры предосторожности для избежания ошибок, связанных со ссылками на объект, память для которого уже освобождена -
Если реализация языка обеспечивает
Указание на заранее определенные объекты. Указатели могут обеспечивать ссылку на заранее определенные объекты. Адрес такого объекта может быть определен использованием оператора адресации ( address of operator ). Например, рассмотрим переменные i и pi, определенные как
int i, *pi;
Присваивание
pi = i;
pi позволяет ссылаться на объект с именем i также с помощью указателя pi, используя обозначение *pi. Имена i и *pi - является также стандартным средством моделирования
Указание на произвольную ячейку памяти. С помощью явных преобразований можно получить указатель на произвольную ячейку памяти. Например, предположим, что pt является указателем типа T*. Тогда указатель на ячейку памяти 0777000 можно получить с помощью следующей записи:
pt = (T*)0777000;
Обращение к конкретным ячейкам памяти часто бывает необходимо в программах, взаимодействующих с оборудованием, например в драйверах устройств, когда для управления устройствами нужно иметь доступ к таким ячейкам памяти, как регистры состояния или ячейки буфера устройства. Хотя такие возможности полезны и даже необходимы для некоторых приложений, пользоваться ими следует с осторожностью.
В языке Си a[i] есть элемент a+i, т.е. *(a+i), где значение а является адресом первого элемента а, а именно a[0]. Выражение a+i является примером арифметических действий с указателями - целое значение i складывается со значением указателя, адресом первого элемента а. Значение этого выражения есть а плюс объем памяти, занимаемый i элементами a. Предположим, что x - x[i] является ссылкой на i-ю x. x[i] дает адрес первого элемента этой *(x+i). Элементы каждой
Аналогично, ссылка на y[i], где y - n>1 ) n-1 )-мерный подмассив с элементами y[i, j2,j3,_jn], где значения jk соответствуют определению y. y[i] дает адрес первого элемента этого подмассива, т.е. *(y+i). Все элементы этого ( n-1 )-мерного подмассива занимают непрерывную область памяти.
\0. Поскольку имя string могут также рассматриваться, как имеющие тип char *. Например, вторая переменная string_array в определении
char *string_pointer, string_array[81];
может рассматриваться также как знаковый указатель. Для string_pointer, память должна быть выделена явно. С другой стороны, для string_array память является указателем на нее. Заметим, что память должна быть также выделена или зарезервирована для признака конца \0.
| ! | Нет ничего необычного не только в string, т.е. |
Мы знаем, что скалярные переменные можно инициализировать в описании типа при помощи таких выражений, как например:
int fix = 1; float flax = PI*2;
при этом предполагается, что PI - ранее введенное макроопределение. Можно ли инициализировать
Внешние, статические и автоматические массивы можно инициализировать! Регистровые массивы инициализировать нельзя!
Если ничего не засылать в '\0' (null) для символьных типов, а регистровые
/* дни месяца */
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
main( )
{
int index;
extern int days[];/*необязательное описание */
for(index = 0; index<12; index++)
printf("Месяц %d имеет %d дней.\n", index+1,
days[index]);
}
Результат:
Месяц 1 имеет 31 дней. Месяц 2 имеет 28 дней. Месяц 3 имеет 31 дней. Месяц 4 имеет 30 дней. Месяц 5 имеет 31 дней. Месяц 6 имеет 30 дней. Месяц 7 имеет 31 дней. Месяц 8 имеет 31 дней. Месяц 9 имеет 30 дней. Месяц 10 имеет 31 дней. Месяц 11 имеет 30 дней. Месяц 12 имеет 31 дней.
Количество элементов в списке инициализации должно соответствовать размеру
Предыдущую программу лучше переписать так:
int days[ ] = {31,28,31,30,31,30,31,31,30,31,30,31};
main( )
{
int index;
extern int days[ ];/* необязательное описание */
for(index=0;index<sizeof(days)/(sizeof(int));
index++)
printf("Месяц %d имеет %d дней.\n",index +1,
days[index]);
}
К этой программе следует сделать два существенных замечания.
Первое: если мы используем пустые скобки для инициализации
Второе: оно касается добавления, сделанного в управляющем операторе for. Не полагаясь на свои вычислительные способности, мы возложили задачу подсчета размера sizeof определяет размер в байтах объекта или типа, следующего за ним. Предположим в нашей вычислительной системе размер каждого элемента типа int равен двум байтам, поэтому для получения количества элементов 2. Однако в других системах элемент типа int может иметь иной размер. Поэтому в общем случае выполняется деление на значение переменной sizeof для элемента типа int.
В результате работы этой программы мы получаем точно 12 значений. Наш метод, позволяющий программе самой находить размер
/* массив-аргумент */
main( )
{
int ages[50]; /* массив из 50 элементов */
convert(ages);
_
}
convert(years);
int years[ ];/* каков размер массива? */
{
_
}
Очевидно, что ages состоит из 50 элементов. А что можно сказать о years? Оказывается в программе нет такого
int years[ ];
создает не
convert(ages);
ages - аргумент функции convert. Имя ages является указателем на первый элемент convert( ). Это значит, что аргумент функции является указателем, и мы можем написать функцию convert( ) следующим образом:
convert(years);
int *years;
{
_
}
Действительно, операторы
int years[ ]; int *years;
- синонимы. Оба они объявляют переменную years указателем years ссылается на
Как теперь связать его с ages? При использовании указателя в качестве аргумента, функция взаимодействует с соответствующей переменной в вызывающей программе, т.е. операторы, использующие указатель years в функции convert( ), фактически работают с ages, находящимся в теле функции main( ). Короче говоря, когда имя
.* выдает значение, хранящееся в указанной ячейке. сообщает нам, где находится сам указатель.Допустимо бесконечно большое число различных типов указателей и
char *p;
Переменная р является указателем на символ, т.е. этой переменной должен присваиваться адрес символа.
char **t;
Переменная t -
int a[50];
Переменная а -
char m[7][50];
Переменная m -
char *r[7];
r состоит из указателей на символы.
int (*f)();
f -
Тип данных x[n1][n2]...[nk]
Где x - идентификатор, определяемый в качестве имени ni - x называется i -го измерения имеют индексы от 0 до ni-1. Тип элемента (pointer), типом структуры ( struct ) или типом объединения ( union ). Хотя элементы
int page[10]; /* одномерный массив из 10 элементов, перенумерованный с 0 до 9 */ char line[81]; float big[10][10], sales[10][5][8]; /*двумерный массив и трехмерный массив*/
Ссылки на элемент x делаются с помощью следующего обозначения:
x[i1][i2]...[ik]
где ij - целое выражение, при этом 0<=ij<=nj-1, а nj - максимальное значение j -го индекса x. Например:
page[5] line[i+j-1] big[i][j]
Указывая только первые p индексов, можно ссылаться на k-p -мерный подмассив (p<=k), например,
sales[i] /* ссылка на двумерный подмассив массива sales */ sales[i][j] /* ссылка на одномерный подмассив */ sales[i][j][k] /* ссылка на элемент массива*/
Указателем называется компонент заданного типа, являющийся ссылкой на некоторую область памяти. Определение указателя имеет следующий вид:
тип-данных *id1, *id2, *_, *idn
Тип переменных id1, id2, _, определяется как тип указателей на тип-данных. Эти переменные служат ссылками на объекты типа тип-данных. Этот тип называется
int *pi, *qi;/* указатели на целые объекты */ char *c; /* указатель на символьный объект */
Указатели используются при создании и обработке malloc и calloc. В отличие от заранее определенных объектов, число
Значение 0 может быть присвоено указателям любого типа. Это значение показывает, что данный указатель не содержит ссылки на какой-либо объект. Попытка использовать это значение для обращения к объекту может привести к ошибке, но только в операционных системах с защитой памяти. По соглашению, для обозначения константы с нулевым значением используется идентификатор NULL, описание которого находится в библиотеке stddef.h и является системозависимым.
По стандарту аргументы функций malloc, calloc имеют тип возвращаемого объекта void*.
char *s = (char*)malloc(size); unsigned size; /* объем памяти, который необходимо выделить */ char *s = (char *)calloc(nelem,elsize); unsigned nelem; /* число элементов, для которых нужно выделить память */ unsigned elsize; /* объем памяти, который необходимо выделить для каждого элемента */ /* либо просто заменив char* на void* */ void* calloc(nelem, elsize); unsigned nelem; unsigned elsize;
Обе функции возвращают указатель на выделенную память. Для определения необходимого объема памяти можно использовать оператор sizeof:
sizeof (выражение)
Объем памяти, необходимый для хранения выражения:
sizeof(T)
Объем памяти, необходимый для хранения значений типа T.
Функции malloc и calloc возвращают указатель на созданный
pi = (int *) malloc(sizeof(int));
выделяется память для одного целого значения. Адрес этой области памяти присваивается переменной pi после его преобразования из типа char * (указатель на знак), с которым он возвращается функцией malloc, к типу int * (указатель на целое), т.е. типу переменной pi.
Присваивание значения объекту, ссылка на который задана указателем pi, выполняется с помощью имени указателя *pi, например:
*pi = 55;
Одно и то же значение может быть присвоено более чем одной переменной-указателю. Таким образом, можно ссылаться на alias ). Например, в результате присваивания
qi = pi;
и qi, и pi указывают на один и тот же объект, т.е. они являются
Память, занимаемая free, которая имеет следующую спецификацию:
free(ptr) char *ptr;
Необходимо предпринимать меры предосторожности для избежания ошибок, связанных со ссылками на объект, память для которого уже освобождена -
Если реализация языка обеспечивает
Указание на заранее определенные объекты. Указатели могут обеспечивать ссылку на заранее определенные объекты. Адрес такого объекта может быть определен использованием оператора адресации ( address of operator ). Например, рассмотрим переменные i и pi, определенные как
int i, *pi;
Присваивание
pi = i;
pi позволяет ссылаться на объект с именем i также с помощью указателя pi, используя обозначение *pi. Имена i и *pi - является также стандартным средством моделирования
Указание на произвольную ячейку памяти. С помощью явных преобразований можно получить указатель на произвольную ячейку памяти. Например, предположим, что pt является указателем типа T*. Тогда указатель на ячейку памяти 0777000 можно получить с помощью следующей записи:
pt = (T*)0777000;
Обращение к конкретным ячейкам памяти часто бывает необходимо в программах, взаимодействующих с оборудованием, например в драйверах устройств, когда для управления устройствами нужно иметь доступ к таким ячейкам памяти, как регистры состояния или ячейки буфера устройства. Хотя такие возможности полезны и даже необходимы для некоторых приложений, пользоваться ими следует с осторожностью.
В языке Си a[i] есть элемент a+i, т.е. *(a+i), где значение а является адресом первого элемента а, а именно a[0]. Выражение a+i является примером арифметических действий с указателями - целое значение i складывается со значением указателя, адресом первого элемента а. Значение этого выражения есть а плюс объем памяти, занимаемый i элементами a. Предположим, что x - x[i] является ссылкой на i-ю x. x[i] дает адрес первого элемента этой *(x+i). Элементы каждой
Аналогично, ссылка на y[i], где y - n>1 ) n-1 )-мерный подмассив с элементами y[i, j2,j3,_jn], где значения jk соответствуют определению y. y[i] дает адрес первого элемента этого подмассива, т.е. *(y+i). Все элементы этого ( n-1 )-мерного подмассива занимают непрерывную область памяти.
\0. Поскольку имя string могут также рассматриваться, как имеющие тип char *. Например, вторая переменная string_array в определении
char *string_pointer, string_array[81];
может рассматриваться также как знаковый указатель. Для string_pointer, память должна быть выделена явно. С другой стороны, для string_array память является указателем на нее. Заметим, что память должна быть также выделена или зарезервирована для признака конца \0.
| ! | Нет ничего необычного не только в string, т.е. |
Мы знаем, что скалярные переменные можно инициализировать в описании типа при помощи таких выражений, как например:
int fix = 1; float flax = PI*2;
при этом предполагается, что PI - ранее введенное макроопределение. Можно ли инициализировать
Внешние, статические и автоматические массивы можно инициализировать! Регистровые массивы инициализировать нельзя!
Если ничего не засылать в '\0' (null) для символьных типов, а регистровые
/* дни месяца */
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
main( )
{
int index;
extern int days[];/*необязательное описание */
for(index = 0; index<12; index++)
printf("Месяц %d имеет %d дней.\n", index+1,
days[index]);
}
Результат:
Месяц 1 имеет 31 дней. Месяц 2 имеет 28 дней. Месяц 3 имеет 31 дней. Месяц 4 имеет 30 дней. Месяц 5 имеет 31 дней. Месяц 6 имеет 30 дней. Месяц 7 имеет 31 дней. Месяц 8 имеет 31 дней. Месяц 9 имеет 30 дней. Месяц 10 имеет 31 дней. Месяц 11 имеет 30 дней. Месяц 12 имеет 31 дней.
Количество элементов в списке инициализации должно соответствовать размеру
Предыдущую программу лучше переписать так:
int days[ ] = {31,28,31,30,31,30,31,31,30,31,30,31};
main( )
{
int index;
extern int days[ ];/* необязательное описание */
for(index=0;index<sizeof(days)/(sizeof(int));
index++)
printf("Месяц %d имеет %d дней.\n",index +1,
days[index]);
}
К этой программе следует сделать два существенных замечания.
Первое: если мы используем пустые скобки для инициализации
Второе: оно касается добавления, сделанного в управляющем операторе for. Не полагаясь на свои вычислительные способности, мы возложили задачу подсчета размера sizeof определяет размер в байтах объекта или типа, следующего за ним. Предположим в нашей вычислительной системе размер каждого элемента типа int равен двум байтам, поэтому для получения количества элементов 2. Однако в других системах элемент типа int может иметь иной размер. Поэтому в общем случае выполняется деление на значение переменной sizeof для элемента типа int.
В результате работы этой программы мы получаем точно 12 значений. Наш метод, позволяющий программе самой находить размер
/* массив-аргумент */
main( )
{
int ages[50]; /* массив из 50 элементов */
convert(ages);
_
}
convert(years);
int years[ ];/* каков размер массива? */
{
_
}
Очевидно, что ages состоит из 50 элементов. А что можно сказать о years? Оказывается в программе нет такого
int years[ ];
создает не
convert(ages);
ages - аргумент функции convert. Имя ages является указателем на первый элемент convert( ). Это значит, что аргумент функции является указателем, и мы можем написать функцию convert( ) следующим образом:
convert(years);
int *years;
{
_
}
Действительно, операторы
int years[ ]; int *years;
- синонимы. Оба они объявляют переменную years указателем years ссылается на
Как теперь связать его с ages? При использовании указателя в качестве аргумента, функция взаимодействует с соответствующей переменной в вызывающей программе, т.е. операторы, использующие указатель years в функции convert( ), фактически работают с ages, находящимся в теле функции main( ). Короче говоря, когда имя
.* выдает значение, хранящееся в указанной ячейке. сообщает нам, где находится сам указатель.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.