我对读取函数指针变量的值有些困惑。
#include <stdio.h>
char* cat_sound()
{
return "meow";
}
char* dog_sound()
{
return "hav";
}
typedef char* (*fptr_sound)(void);
typedef struct
{
int age;
fptr_sound sound;
}creature_t;
int main()
{
creature_t cat, dog;
cat.sound = cat_sound;
dog.sound = dog_sound;
printf("cat.sound()= %s, dog.sound()= %s\n", cat.sound(), dog.sound());
printf("cat.sound= %s, dog.sound= %s\n", cat.sound, dog.sound);
printf("*cat.sound= %s, *dog.sound= %s\n", *cat.sound, *dog.sound);
printf("*cat.sound()= %c, *dog.sound()= %c\n", *cat.sound(), *dog.sound());
printf("value of cat.sound= %x, dog.sound= %x\n", cat.sound, dog.sound);
printf("value of *cat.sound= %x, *dog.sound= %x\n", *cat.sound, *dog.sound);
printf("value of cat.sound()= %x, dog.sound()= %x\n", cat.sound(), dog.sound());
printf("value of *cat.sound()= %x, *dog.sound()= %x\n", *cat.sound(), *dog.sound());
return 0;
}
cat.sound()= meow, dog.sound()= hav
cat.sound= U▒▒]▒U▒▒]▒U▒▒S▒▒▒▒ ▒D$▒D$&▒D$▒ЉËD$▒Љ\▒D$▒$▒▒▒▒▒T$▒D$▒T▒D$▒$▒x▒▒▒▒T$▒D$▒T▒D$▒$<▒\▒▒▒▒D$▒▒▒, dog.sound= U▒▒]▒U▒▒S▒▒▒▒ ▒D$▒D$&▒D$▒ЉËD$▒Љ\▒D$▒$▒▒▒▒▒T$▒D$▒T▒D$▒$▒x▒▒▒▒T$▒D$▒T▒D$▒$<▒\▒▒▒▒D$▒▒▒
*cat.sound= U▒▒]▒U▒▒]▒U▒▒S▒▒▒▒ ▒D$▒D$&▒D$▒ЉËD$▒Љ\▒D$▒$▒▒▒▒▒T$▒D$▒T▒D$▒$▒x▒▒▒▒T$▒D$▒T▒D$▒$<▒\▒▒▒▒D$▒▒▒, *dog.sound= U▒▒]▒U▒▒S▒▒▒▒ ▒D$▒D$&▒D$▒ЉËD$▒Љ\▒D$▒$▒▒▒▒▒T$▒D$▒T▒D$▒$▒x▒▒▒▒T$▒D$▒T▒D$▒$<▒\▒▒▒▒D$▒▒▒
*cat.sound()= m, *dog.sound()= h
value of cat.sound= 804841c, dog.sound= 8048426
value of *cat.sound= 804841c, *dog.sound= 8048426
value of cat.sound()= 80485f0, dog.sound()= 80485f5
value of *cat.sound()= 6d, *dog.sound()= 68如下所示,cat.sound保存cat_sound函数的地址。那么为什么*cat.sound会返回相同的值呢?(如果与指向整数的指针进行比较,则取消引用将返回它所指向的值,而不是值本身。)
为什么cat.sound()指向函数返回的值,而不是函数地址本身?
08048430 <main>:
8048430: 55 push ebp
8048431: 89 e5 mov ebp,esp
8048433: 53 push ebx
8048434: 83 e4 f0 and esp,0xfffffff0
8048437: 83 ec 20 sub esp,0x20
804843a: c7 44 24 1c 1c 84 04 mov DWORD PTR [esp+0x1c],0x804841c
0804841c <cat_sound>:
804841c: 55 push ebp
804841d: 89 e5 mov ebp,esp
804841f: b8 f0 85 04 08 mov eax,0x80485f0
8048424: 5d pop ebp
8048425: c3 ret
08048426 <dog_sound>:
8048426: 55 push ebp
8048427: 89 e5 mov ebp,esp
8048429: b8 f5 85 04 08 mov eax,0x80485f5
804842e: 5d pop ebp
804842f: c3 ret发布于 2019-08-28 21:03:19
cat.sound()调用cat.sound指向的函数并返回其返回值,返回值是一个指向字符串文字"meow"开头的char*指针。使用%s打印它很好,并且会得到预期的结果meow。使用%x打印它提供了文字或未定义行为的地址的实现定义的表示形式。最好使用%p,这将消除未定义行为的可能性。
*cat.sound()解除对字符串文字"meow"的第一个字符的引用,因此给出了字符'm',%c将直接打印该字符,而%x将格式化为其十六进制(ascii)表示形式并打印它。
cat.sound是指向函数的指针,使用%s打印它是未定义的行为。实际上,正如您的输出所表明的那样,编译器选择打印位于指针地址的函数的目标代码,直到它遇到空字节。
*cat.sound与cat.sound相同。应用于函数指针的*实际上不会做任何事情。它产生一个函数指示符,然后你使用它的方式再次衰减为一个函数指针。这是与非函数指针不同的行为。同样,使用%s打印它也是未定义的行为。
使用%x打印函数指针也是未定义的行为,有关如何合法打印函数指针的信息,请参阅this question。
发布于 2019-08-28 21:00:23
与数组类似,函数指示器会自动转换为指向其函数的指针。C 2018 6.3.2.1 4表示:
函数指示符是具有函数类型的表达式。除非是
sizeof运算符的操作数,或者是一元&运算符,否则类型为“函数返回类型”的函数指示符将被转换为类型为“指向函数返回类型的指针”的表达式。
因此,编译器会自动将cat_sound (作为函数名指定函数)转换为&cat_sound。
此外,由于cat.sound是指向函数的指针,因此*cat.sound指定该函数。但是,因为它是一个函数指示符,所以它会自动转换为指向函数的指针,生成与cat.sound相同的&*cat.sound,它只是函数的地址。
cat.sound()是指向函数返回的数据的指针,因为圆括号()会导致调用函数,而结果是函数返回的指针。
https://stackoverflow.com/questions/57692656
复制相似问题