Wskaźniki funkcji i adres funkcji

Więc pomyślałem, że podczas tworzenia wskaźników funkcji, nie potrzebujesz operator &, aby uzyskać adres początkowej funkcji:

#include <stdio.h>

double foo (double x){
    return x*x;
}

int main () {

    double (*fun1)(double) = &foo;
    double (*fun2)(double) =  foo;

    printf("%f\n",fun1(10));
    printf("%f\n",fun2(10));

    printf("fun1 = %p \t &foo = %p\n",fun1, &foo);
    printf("fun2 = %p \t  foo = %p\n",fun2,  foo);       

    int a[10];

    printf("  a = %p \n &a = %p  \n",a,&a);

    return 0;
}

Wyjście:

>./a.out 
100.000000
100.000000
fun1 = 0x4004f4      &foo = 0x4004f4
fun2 = 0x4004f4       foo = 0x4004f4
  a = 0x7fff26804470 
 &a = 0x7fff26804470 

Wtedy zdałem sobie sprawę, że jest to również prawda dla tablic, co oznacza, że jeśli masz int a[10] zarówno a, jak i &a wskazują na to samo miejsce. Dlaczego tak jest z tablicami i funkcjami? Czy adres jest zapisany w miejscu pamięci, które ma ten sam adres, Co zapisywana w nim wartość (adres)?

Author: skrtbhtngr, 2012-03-04

5 answers

Podane int a[10], zarówno a, jak i &a dają ten sam adres, tak, ale ich typy są różne.

a jest typu int[10]. Gdy jest ona domyślnie przekonwertowana na typ wskaźnika, Wskaźnik jest typu int* i wskazuje na początkowy element tablicy. &a jest typu int (*)[10] (czyli wskaźnik do tablicy dziesięciu liczb całkowitych). Ponieważ w tablicy nie może być padding, oba dają wskaźniki o tej samej wartości , ale wskaźniki mają inną wartość typy .

Funkcje są podobne do tablic, ale nie do końca takie same. Twoja funkcja {[8] } jest Typu double(double). Gdy foo jest używane w wyrażeniu i nie jest operandem operatora unary &, jest on niejawnie konwertowany na wskaźnik do siebie samego, który jest typu double(*)(double).

Więc, dla wszystkich praktycznych celów, nazwa funkcji i wskaźnik do tej samej funkcji są wymienne. Są pewne subtelności, o których wszystkie omawiam w odpowiedzi na "dlaczego wszystkie te szalone definicje wskaźników funkcyjnych działają? Co tak naprawdę się dzieje?" (to pytanie zostało zadane o C++, ale zasady dla funkcji pozamember w C++ są takie same jak dla funkcji w C)

 72
Author: James McNellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:52

Nie, Nie ma dodatkowej pamięci przeznaczonej do wskazywania funkcji / tablicy.

Dla większości zmiennych variable_name ma znaczenie inne niż uzyskanie adresu tej zmiennej, więc musisz użyć &variable, aby uzyskać adres.

Z funkcją lub tablicą, function_name (sama w sobie, bez nawiasów) nie ma żadnego innego znaczenia, więc nie było problemu z interpretacją jej jako adresu funkcji.

Podobnie w odwrotnej kolejności: normalny wskaźnik musi być nie jest to jednoznaczne, ale wskaźnik do funkcji nie (znowu, ponieważ nie ma innej rozsądnej interpretacji), więc biorąc wskaźnik do funkcji takiej jak:

int (*func)(param_list);

Poniższe są sobie równoważne -- oba wywołują dowolną funkcję func wskazującą na:

(*func)(params);

func(params);
 9
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-04 05:52:13

fun i {[1] } są dokładnie takie same (tyle że rozmiar(f) jest nielegalny). a i &a są takie same do arytmetyki wskaźnika: a + 10 == &a + 1, Ponieważ 10*sizeof(*a) == sizeof(a) (Gdzie sizeof(*a) == sizeof(int)).

 1
Author: Loic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 22:25:44

Zasadniczo, ponieważ nazwa funkcji jest" znana " jako funkcja, & nie jest bezwzględnie konieczne. To zachowanie jest takie samo dla tablic. Przypomnijmy, że sama funkcja nie jest zmienną, więc zachowuje się trochę inaczej, niż można się czasem spodziewać. Jeśli masz drugie wydanie K & r, możesz sprawdzić sekcję 5.11 na wskaźnikach do funkcji, lub instrukcję referencyjną na końcu,

Sekcja A7.1 generowanie wskaźnika: jeśli typ wyrażenia lub podekspresja to " tablica T" dla pewnego typu T, wtedy wartość wyrażenie jest wskaźnikiem do pierwszego obiektu w tablicy, A Typ wyrażenia jest zmieniana na "wskaźnik na T". ta konwersja nie zachodzi wyrażenie jest operandą unary & operator, ... Podobnie wyrażenie typu " funkcja zwracająca T," z wyjątkiem, gdy jest używany jako operand operatora&, jest konwertowany na "wskaźnik do funkcji zwracającej T."

Sekcja A7. 4. 2 Operator adresu: unary & operator przyjmuje adres jego operand.... Wynikiem jest wskaźnik do obiektu lub funkcji / align = "left"/ Jeśli typem operandu jest T, to typ wynik jest "wskaźnik do T."

Z tego co wiem to tak samo jest z C99.

 1
Author: Cameron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Printf ("fun1 = % p \t & foo = % p \ n", fun1, foo);

Tutaj wywołujesz foo przekazując Wskaźnik funkcji z pass by value oraz

Printf ("fun2 = %P \T foo = %P\n", fun2, &foo)

Tutaj wywołujesz &foo przekazując wskaźnik funkcji z pass by reference

W obu przypadkach wywołujesz {[4] } tylko ze wskaźnikiem funkcji.

Remember foo itself is function pointer value and ' not a variable.

To samo dzieje się z array. int arr[10] przekłada się na get ciągły blok 10 liczb całkowitych i adres pierwszego elementu jest zapisywany w arr. tak więc arr jest również wskaźnikiem.

 0
Author: rahul maindargi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 07:44:26