- •Int a; /* целая
- •Int n; // Переменная n целого типа double a; // Переменная a вещественного типа двойной точности
- •Вещественные константы
- •Символьные константы
- •Строковые константы
- •Логические операции
- •Тернарные операции
- •Оператор ветвления switch
- •Параметрический цикл for
- •Тип *имя_объекта;
- •Стандартные функции динамического выделения памяти
- •Динамическое выделение памяти для одномерных массивов
- •Основные функции стандартной библиотеки string.H
- •Массивы структур
- •Идентификатор(аргумент1, ..., агрументn)
- •Функция, позволяющая вывести день недели на русском языке
- •Файловая структура fat32
- •Работа с файлами в языке Си
Тип *имя_объекта;
Тип указателя— это тип переменной, адрес которой он содержит.
Для работы с указателями в Си определены две операции:
операция * (звездочка) — позволяет получить значение объекта по его адресу - определяет значение переменной, которое содержится по адресу, содержащемуся в указателе;
операция & (амперсанд) — позволяет определить адрес переменной.
Например,
сhar c; // переменная char *p; // указатель p = &c; // p = адрес c
Для
указанного примера обращение к одним
и тем же значениям переменной и адреса
представлено в таблице
|
Переменная |
Указатель |
Адрес |
&c |
p |
Значение |
c |
*p |
Пример
#include <stdio.h> #include <stdlib.h> int main() {
int a, *b;
system("chcp 1251");
system("cls");
a=134;
b=&a;
printf("\n Значение переменной a равно %d.", a);
printf("\n Адрес переменной a равен %d.", &a);
printf("\n Данные по адресу указателя b равны %d.",*b);
printf("\n Значение указателя b равно %d.",b);
printf("\n Адрес расположения указателя b равен %d.", &b);
getchar();
return 0; }
Результат
выполнения программы:
Расположение
в памяти переменной a и указателя
b:
Необходимо
помнить, что компиляторы высокого уровня
поддерживают прямой
способ адресации:
младший байт хранится в ячейке, имеющей
младший адрес.
Массивы в языке Си
Главная > Язык Си > Массивы в языке Си
При решении задач с большим количеством данных одинакового типа использование переменных с различными именами, не упорядоченных по адресам памяти, затрудняет программирование. В подобных случаях в языке Си используют объекты, называемые массивами.
Массив - это непрерывный участок памяти, содержащий последовательность объектов одинакового типа, обозначаемый одним именем.
Массив характеризуется следующими основными понятиями:
Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.
Каждый элемент массива характеризуется тремя величинами:
адресом элемента - адресом начальной ячейки памяти, в которой расположен этот элемент;
индексом элемента (порядковым номером элемента в массиве);
значением элемента.
Адрес массива – адрес начального элемента массива. Имя массива – идентификатор, используемый для обращения к элементам массива. Размер массива – количество элементов массива Размер элемента – количество байт, занимаемых одним элементом массива.
Графически
расположение массива в памяти компьютера
можно представить в виде непрерывной
ленты адресов.
Представленный на рисунке массив содержит q элементов с индексами от 0 до q-1. Каждый элемент занимает в памяти компьютера k байт, причем расположение элементов в памяти последовательное.
Адреса i-го элемента массива имеет значение
n+k·i
Адрес массива представляет собой адрес начального (нулевого) элемента массива. Для обращения к элементам массива используется порядковый номер (индекс) элемента, начальное значение которого равно 0. Так, если массив содержит q элементов, то индексы элементов массива меняются в пределах от 0 до q-1.
Длина массива – количество байт, отводимое в памяти для хранения всех элементов массива.
ДлинаМассива = РазмерЭлемента * КоличествоЭлементов
Для определения размера элемента массива может использоваться функция
int sizeof(тип);
Например,
sizeof(char) = 1; sizeof(int) = 4; sizeof(float) = 4; sizeof(double) = 8;
Объявление и инициализация массивов
Для объявления массива в языке Си используется следующий синтаксис:
тип имя[размерность]={инициализация};
Инициализация представляет собой набор начальных значений элементов массива, разделенных запятыми.
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // массив a из 10 целых чисел
int a[10] = {0}; // массив a из 10 элементов, инициализированных 0
Если массив проинициализирован при объявлении, то константные начальные значения его элементов указываются через запятую в фигурных скобках. В этом случае количество элементов в квадратных скобках может быть опущено.
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках [].
Пример
#include <stdio.h> int main() {
int a[]={5, 4, 3, 2, 1}; // массив a содержит 5 элементов
printf("%d %d %d %d %d\n",a[0], a[1], a[2], a[3], a[4]);
getchar();
return 0; }
Результат
выполнения программы:
Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.
int a[10];
Для задания начальных значений элементов массива очень часто используется параметрический цикл:
#include <stdio.h> int main() {
int a[5]; // объявлен массив a из 5 элементов
int i;
// Ввод элементов массива
for(i=0; i<5; i++) {
printf("a[%d] = ", i);
scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива
}
// Вывод элементов массива
for(i=0;i<5;i++) {
printf("%d ",a[i]); // пробел в формате печати обязателен
}
getchar();
getchar();
return 0; }
Результат
выполнения программы
Многомерные массивы
В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном — несколькими. Примером многомерного массива является матрица.
Общая форма объявления многомерного массива
тип имя[размерность1][размерность2]...[размерностьm];
Элементы многомерного массива располагаются в последовательных ячейках оперативной памяти по возрастанию адресов. В памяти компьютера элементы многомерного массива располагаются подряд, например массив, имеющий 2 строки и 3 столбца,
int a[2][3];
будет расположен в памяти следующим образом
Общее
количество элементов в приведенном
двумерном массиве определится
как
КоличествоСтрок
* КоличествоСтолбцов = 2 * 3 = 6.
Количество
байт памяти, требуемых для размещения
массива, определится как
КоличествоЭлементов
* РазмерЭлемента = 6 * 4 = 24 байта.
Инициализация многомерных массивов
Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки {}. Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках [].
Пример
#include <stdio.h> int main() {
int a[2][3]={1, 2, 3, 4, 5, 6};
printf("%d %d %d\n", a[0][0], a[0][1], a[0][2]);
printf("%d %d %d\n", a[1][0], a[1][1], a[1][2]);
getchar();
return 0; }
Результат
выполнения
Однако
чаще требуется вводить значения элементов
многомерного массива в процессе
выполнения программы. С этой целью
удобно использовать вложенный
параметрический
цикл.
Пример
#include <stdio.h> int main() {
int a[2][3]; // массив из 2 строк и 3 столбцов
int i, j;
// Ввод элементов массива
for(i=0; i<2; i++) // цикл по строкам
{
for(j=0; j<3; j++) // цикл по столбцам
{
printf("a[%d][%d] = ", i,j);
scanf("%d", &a[i][j]);
}
}
// Вывод элементов массива
for(i=0; i<2; i++) // цикл по строкам
{
for(j=0; j<3; j++) // цикл по столбцам
{
printf("%d ", a[i][j]);
}
printf("\n"); // перевод на новую строку
}
getchar();
getchar();
return 0; }
Результат
выполнения
Передача массива в функцию
Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать
адрес массива,
размер массива.
Исключение составляют функции обработки строк, в которые достаточно передать только адрес.
При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.
Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.
Пример Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.
#include <stdio.h>
// Функция обмена
void change(int *x, int n) { // x - указатель на массив (адрес массива)
// n - размер массива
int i;
int max, index;
max = x[0];
index = 0;
// Поиск максимального элемента
for(i=1; i<n; i++)
{
if(x[i]>max)
{
max= x[i];
index = i;
}
} // Обмен
x[index] = x[0];
x[0] = max; } int main() {
int a[10];
int i;
for(i=0; i<10; i++)
{
printf("a[%d] = ", i);
scanf("%d", &a[i]);
}
change(a,10); // вызов функции обмена
// Вывод элементов массива
for(i=0; i<10; i++)
{
printf("%d ", a[i]);
}
getchar();
getchar();
return 0; }
Результат
выполнения
Пример
Дан массив размерности n. Вычислить
произведение четных элементов
#include <stdio.h> int func(int *x, int n) { // произведение четных элементов
int p=1; // начальное значение произведения
int i;
for(i=0;i<n; i++) {
if(x[i] % 2==0) // остаток от деления на 2 равен 0?
p = p * x[i];
}
return p; } int main() {
int a[5]; // объявлен массив a из 5 элементов
int i;
int pr;
// Ввод элементов массива
for(i=0; i<5; i++) {
printf("a[%d] = ", i);
scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива
}
pr = func(a, 5); // вычисление произведения
printf("\n pr = %d", pr); // вывод произведения четных элементов
getchar();
getchar();
return 0; }
Результат
выполнения
Динамическое выделение памяти в Си
Главная > Язык Си > Динамическое выделение памяти в Си
Очень часто возникают задачи обработки массивов данных, размерность которых заранее неизвестна. В этом случае возможно использование одного из двух подходов:
выделение памяти под статический массив, содержащий максимально возможное число элементов, однако в этом случае память расходуется не рационально;
динамическое выделение памяти для хранение массива данных.
Для использования функций динамического выделения памяти необходимо описать указатель, представляющий собой начальный адрес хранения элементов массива.
int *p; // указатель на тип int
Начальный адрес статического массива определяется компилятором в момент его объявления и не может быть изменен.
Для динамического массива начальный адрес присваивается объявленному указателю на массив в процессе выполнения программы.
