Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Указатели в Си, функции

#c #массивы #указатели #char


Добрый день господа, собственно вопрос. Вижу периодически, что в некоторых функциях
указатели вставляют то таким образом: function(&name), то таким: function(name).

Может кто нибудь объяснить, что да как с этим делом? Я понимаю, как работают указатели,
но чёт догнать не могу, почему в функции стоит входной параметр char, а отправляют
получается адрес указателя. И если можно, пример для использования возможных вариантов.
Заранее спасибо!
    


Ответы

Ответ 1



В выражениях массивы за редким исключением неявно преобразуются в указатель на свой первый элемент. Поэтому когда вы передаете массив в функцию, как в нижеприведенном примере void f( int *a, size_t n ) { for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] ); printf( "\n" ); } int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; f( a, 10 ); то не надо указывать перед именем массива оператор &. Массив уже преобразован в указатель типа int *. Однако если вы имеете дело со скалярными объектами, как, например, выражение a[0], которое представляет собой первый элемент массива, то есть скалярный объект со значением 0, как следует из определения массива в примере выше, то если вы хотите передать его адрес в вышеуказанную функцию , то вам надо будет записать f( &a[0], 10 ); Фактически, данные два вызова f( a, 10 ); и f( &a[0], 10 ); эквивалентны, так как в обоих случаях передается адрес на первый элемент массива. В виду этого данные объявления функции эквивалентны и объявляют одну и ту же функцию void f( int a[10], size_t n ) void f( int a[20], size_t n ) void f( int a[], size_t n ) void f( int *a, size_t n ) Вы все эти объявления можете одновременно включить в программу, и программа будет успешно компилироваться. То же самое справедливо и для символьных массивов. Имейте в виду, что строковые литералы также имеют тип массивов. И если имеется вызов вида h( "Hello" ); где h - это некоторая функция, то в функцию передается адрес первого символа литерала, так как, как описано выше, данный литерал, который представляет из себя символьный массив, неявно преобразуется в указатель на свой первый символ. В заключение приведу демонстрационную программу, в которую также включен пример, показывающий, что строковые литералы - это массивы. #include void f( int a[10], size_t n ); void f( int a[20], size_t n ); void f( int a[], size_t n ); void f( int *a, size_t n ); void f( int *a, size_t n ) { for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] ); printf( "\n" ); } void h( char c ) { printf( "%c\n", c ); } int main(void) { int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; f( a, 10 ); f( &a[0], 10 ); h( "Hello"[0] ); return 0; } Вывод программы на консоль 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 H

Ответ 2



char *name = "Я уже указатель :)"; function(name); function(name+3); // Я указатель на 3 символа дальше, чем name function(&name[3]); // А я не был, я был третьим символом строки, пока не взяли адрес char name='q'; // Я символ, а не указатель function(&name);

Комментариев нет:

Отправить комментарий