Указатели и массивы
Имя массива является указателем на его первый элемент, поэтому обратиться к первому элементу можно так *mas и эта запись эквивалента mas[0]. Для обращение к элементу с индексом I можно воспользоваться записью *(mas+i) и это будет эквивалентно mas[i].
int mas[] = {10,20,30,40,50};
printf("%9s%9s%9s\n", "Индекс", "Значение", "Адрес");
for (int i=0; i<5; i++) {
printf("%9d%9d%9d\n", i, mas[i], &mas[i]);
}
int mas[] = {10,20,30,40,50};
printf("%9s%9s%9s\n", "Индекс", "Значение", "Адрес");
for (int i=0; i<5; i++) {
printf("%9d%9d%9d\n", i, *(mas+i), mas+i);
}
Передача массивов в качестве аргументов функций
Поскольку элементы массива хранятся в памяти последовательно, что для обращения к массиву достаточно знать указатель на его первый элемент и тип. Таким образом, прототип функции, принимающей массив в качестве аргумента имеет вид:
int getSum(int* numbers, int size) {
int result = 0;
for (int i=0; i<size; i++) {
result += numbers[i];
}
return result;
}
int myNumbers[] = {1,2,3,4,5,6,7,8};
printf("%d\n", getSum(myNumbers, 8));
36.
Поскольку все корректные строки завершаются нуль-символом, то передавать в функцию аргументом размер массива не нужно. Функция, принимающая строку в качестве аргумента, может иметь такой вид:
int vowels(char* word) {
int result = 0;
for (int i=0; i<strlen(word); i++) {
if (isVowel(word[i])) {
result++;
}
}
return result;
}
Динамическое распределение памяти
Массив является статической структурой данных в том смысле, что количество элементов массива можно задать только перед началом работы программы. Другими словами, сколько памяти под массив выделено с тем размером нужно работать. Довыделить или освободить память невозможно.
Данную проблему можно решить путем выделения памяти с запасом. Например, зная, что длина слов, с которыми предстоит работа, не превышает 10, то выделить память нужно под них, а по факту использовать меньше.
int* ptr;
int size;
printf("Введите размер: ");
scanf("%d",&size);
ptr = new int[size];
for (int i=0; i<size; i++) {
*(ptr+i) = rand();
}
for (int i=0; i<size; i++) {
printf("%-7d\n", ptr[i]);
}
Почему в scanf() ставится амперсанд
void set7(int x) {
x=7;
}
int main() {
int x=10;
set7(x);
printf("%d", x);
}
void set7(int* ptr) {
*ptr=7;
}
int main() {
int x=10;
set7(&x);
printf("%d", x);
putchar('\n');
}
Передача аргументов по значению и по ссылке
Представьте себе ситуацию, когда необходимо передать некоторый предмет, скажем, книгу своему коллеге по работе. Сделать это можно двумя способами: либо передать эту книгу лично из рук в руки, либо положить это книгу в ящик стола и сообщить коллеге, что книга находится там. В первом случае книга передается фактически, а во втором вы «передаете» ссылку на книгу вместо самой книги. Результат по большому счету одинаков в обоих случаях: предмет доставлен адресату. Тем не менее, удобство и эффективность этих двух способов существенным образом зависит от того, насколько далеко друг от друга находятся взаимодействующие стороны, насколько велик и тяжел передаваемый предмет и т.д.
В программировании также возможна реализация этих механизмов передачи аргументов функций. Первый способ называется передача аргументов по значению, а второй – передача аргументов по ссылке.
Структуры и указатели
Структура – это тип данных, хотя и составной:
struct worker {
char name[20];
int age;
};
Можно создать массив, элементами которого являются структуры:
worker workers[] = {
{"John", 30},
{"Maria", 33},
{"Jim", 23}
};
Можно также объявить указатель на структуру:
worker* ptr;
и присвоить ему указатель на массив:
ptr = worker;
обратиться к полю структуры
for (int i=0; i<3; i++) {
printf("%s\t%d\n", (*ptr).name, (*ptr).age);
printf("%s\t%d\n\n", ptr->name, ptr->age);
ptr++;
}
}