Svid, попробую вербализовать некоторые аспекты в менее гуманитарной манере

Для начала - думайте об указателях, как об адресах памяти. То есть:
C++ |
1
2
3
4
5
| int var = 18; //допустим, лежит по адресу 0x0022ff74
int * ptr; //указатель
ptr = &var; // ptr = 0x0022ff74
cout << ptr << ": " << *ptr << endl; |
|
Вывод:
Амперсанд (&) - это операция взятия адреса; Вы присваиваете АДРЕС переменной var, а не её значение. Звёздочка перед именем указателя ( *ptr ) - это операция разыменовывания указателя, то есть вы берёте не значение указателя (то есть адрес), а значение, лежащее по этому адресу.
Теперь о практике: представьте себе, что вам нужно написать функцию, которая выводит массив int, но вы заранее не знаете, массив какого размера ей передадут. Это могут быть 2 int'а, а может быть десь-тыщ. В этом случае проще сделать так:
C++ |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| void int_out( int * array, int size )
{
for( int i = 0; i < size; i++ )
cout << array[i] << "; " << endl;
cout << "=============\nTotal " << size << " numbers" << endl;
}
int main()
{
int var = 18;
int test[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
int_out( &var, 1 ); //передаём адрес var
cout << endl;
int_out( test, 15 ); //массивы всегда передаются по указателю; операция взятия адреса не требуется
return 0;
} |
|
Теперь вопрос: вы задумывались, почему в C и C++ нумерация элементов массива идёт с нуля, а не с единицы? Смотрите, вот так выглядит массив в памяти:
00 AF 14 28 A8 76 42 00 00 00 01 00 00 00 02 00 00 04 A1 00 00 A7 70 21 17 86 61 0A
При синтаксисе var[5] берётся
адрес начала массива var и к нему прибавляется ( размер_элемента_массива_var * 5 ). То есть нулевой элемент массива int будет равен ( адрес_начала + (4 * 0) = адрес_начала ), первый - ( адрес_начала + (4 * 1) = адрес_начала + 4 ) и так далее. Вы в любом случае работаете с адресами, указатели просто позволяют это делать более просто.
Теперь на счёт ссылки. По сути, ссылка - это
константный указатель на неконстантные данные, то есть вы можете изменить данные по ссылке, но не можете изменить адрес, на который она указывает.
Теперь на счёт синтаксиса printf():
C++ |
1
2
3
4
5
| int var = 18;
// сначала функции передаётся значение переменной var,
// а затем её адрес
printf( "var = %i\naddress = 0x%x\n", var, &var ); |
|
Всё очень просто, если всё понимать.
Другой пример: вам нужно передать функции структуру, которая занимает в памяти 1 килобайт (ну, жирная такая структура). Вы можете либо это запихать целиком и подавиться, а можете вместо 1 килобайта записать 4 байта адреса этой структуры и на этом успокоиться. Что проще будет?
Если что - спрашивайте.
Добавлено через 1 минуту
Не по теме:
О, пока я писал, тема развилась... Если что - простите за повторения, ещё не ознакомился 