Dunris писал(а): ↑24.08.2009 20:14
То есть char * value - указатель на область памяти типа char, с этим ясно. Но по идее, чтобы присвоить значение этой области, необходимо обратиться к указателю *value. Здесь же присваивают значение как бы указателю, хотя этого сделать, если я не ошибаюсь, нельзя.
Указатель — это та же переменная, просто она содержит число, однозначно отображаемое на адрес памяти. Мы можем как изменять данные в этой области (используя оператор «*»), так и изменять сам этот адрес, после чего указатель будет направлять на другую область памяти.
«char **argv» — здесь argv — это указатель на указатель. Как и сказал
Crazy, для обращения к массиву достаточно знать адрес начала области памяти, где этот массив располагается. С помощью argv можно читать аргументы командной строки, переданные в программу, но что такое эти аргументы? — это строки, то есть массивы символов типа char, и эти массивы сами объединены в массив, то есть получается двумерный массив — матрица. Поэтому и «двойной» указатель.
Указатели на самом деле очень удобны. Они позволяют добиться большей гибкости блокам вашей программы. Кроме очевидных случаев вроде передачи массива с помощью них создаются связанные списки (наверное, вы до этого ещё не дошли, но когда дойдёте, поймёте
) и многое другое. Передать параметр функции и позволить ей его изменять можно только с помощью указателя (явно или неявно). Или, к примеру, у вас есть несколько целочисленных переменных, и в зависимости от значения некоторого параметра вы должны выбрать одну из них и проделать над ней определённые действия (одинаковые для всех этих переменных). С помощью указателей это можно сделать легко и красиво:
Код: Выделить всё
int32_t *some_var_p, var_1, var_2, var_3;
switch (var_index) {
case VAL_1:
some_var_p = &var_1;
break;
case VAL_2:
some_var_p = &var_2;
break;
case VAL_3:
some_var_p = &var_3;
}
— и далее все операции проводить уже по указателю.
Указателями можно пользоваться вообще без наличия обычных переменных. Разумеется, для того, чтобы «направить» указатель на какую-то область памяти, эта область должна прежде существовать. Это автоматически верно для переменной, но можно выделить память и вручную, используя функцию malloc:
— sizeof возвращает размер, в данном случае — 4 (байта). Тем самым будет выделена область размером 4 байта, и возвращён указатель на неё. В дальнейшем с этой областью можно спокойно работать. Когда эта область перестаёт быть нужна (при выходе из функции, например, или по завершении программы), выделенную память
можнонужно освободить:
Создание массива:
Код: Выделить всё
int *int_array = malloc(sizeof(int) * num_elements);
— теперь к элементам массива можно обращаться по индексу, как вы привыкли. «*» в параметрах malloc — это операция умножения
.
Как видите, количество элементов создаваемого массива не задаётся заранее, а может быть вычислено в процессе исполнения программы, что позволяет, во-первых, не гадать, какой же массив нужно делать, чтобы в него гарантированно поместились все передаваемые данные, а во-вторых, экономить память, не выделяя под массив больше памяти, чем нужно в данном конкретном случае.
Не забывайте освобождать память: