【问题标题】:Function pointer code not executing properly函数指针代码未正确执行
【发布时间】:2021-09-24 00:21:37
【问题描述】:

我正在尝试学习函数指针,我只想制作 3 个函数,这些函数具有指向它们的指针,这些函数用于我通过函数指针数组调用的其他 2 个函数。该代码没有给出任何错误,但我收到的是地址而不是值。我尝试了取消引用等,但没有任何改变。我确信我忽略了一些简单的事情,但我不确定该怎么做,或者我的错误在哪里。

显式转换在那里,因为我只是在玩它,没有什么特别的原因。

#include <stdio.h>

#include <stdlib.h>

unsigned int par1(void)
{
    return 5;
}

unsigned int par2(void)
{
    return 6;
}

unsigned int par3(void)
{
    return 7;
}

const unsigned int x = 10;


typedef unsigned int (*parPtr)(void);
parPtr parP1 = &par1;
parPtr parP2 = &par2;
parPtr parP3 = &par3;

/** typedef for sum() and scad() */
typedef int (*sumscadPtr)(parPtr, parPtr);

sumscadPtr sumscadPtrArr[2];

int sum(parPtr, parPtr);

int scad(parPtr, const unsigned int);


void allocate_array_of_pointers(void)
{

    sumscadPtrArr[0] = &sum;
    sumscadPtrArr[1] = &scad;


}


// should return 11
int sum(parPtr parA, parPtr parB)
{
    unsigned int value1 = *parA;
    printf("\n%d\n", value1);
    unsigned int value2 = *parB;
    printf("\n%d\n", value2);

    return (int)value1 + (int)value2;
}


// should return 3
int scad(parPtr parA, unsigned const int b)
{
    unsigned int value1 = parA;

    // This is just a simple check in case i might change the const value in the future
    if((int)value1 > (int)b)
        return (int)value1 - (int)b;
    else
        return (int)b - (int)value1;
}




int main()
{
    allocate_array_of_pointers();

    int sumVal = sumscadPtrArr[0](&par1, &par2);
    int scadVal = sumscadPtrArr[1](&par3, x);

    printf("\nsumVal is :%d\n", sumVal);
    printf("\nscadVal is :%d\n", scadVal);

    int a = *parP1;
    printf("\n%d\n", a);


    return 0;
}

【问题讨论】:

  • 你没有从这段代码中得到任何警告吗? sumscad 不是同一个签名,因此您不能将它们放在 sumscadPtr 的数组中。如果你有一个函数指针,你需要调用它,而不是取消引用它。 unsigned int value1 = *parA; -> unsigned int value1 = parA();
  • 正如@RetiredNinja 所说,使用unsigned int value1 = *parA;parA 指向的函数的指针(地址)分配给value1,如果你的编译器没有对那个分配强烈抱怨,你需要一个更好的编译器。函数指针很奇怪。你不需要在函数名前面加上&amp;来获取它的地址;您也可以相当随意地使用* 并最终得到相同的结果。使用 unsigned int value1 = parA(); 可以正常工作,unsigned value1 = (*parA)(); 也可以正常工作(这是我学习 C 时唯一有效的符号——替代方法来自 C90)。
  • 您好!非常感谢您的回复,以及您的洞察力,这对我帮助很大!我从一个朋友那里收到了这个小练习,根据我从你的 cmets 那里学到的东西,它可能有缺陷。不过,关于如何访问函数指针,你们俩帮了我很多!

标签: c function pointers function-pointers


【解决方案1】:

您的代码 failed 编译时出现这些错误:

main.cpp:42:24: error: invalid conversion from 'int (*)(parPtr, unsigned int)' {aka 'int (*)(unsigned int (*)(), unsigned int)'} to 'sumscadPtr' {aka 'int (*)(unsigned int (*)(), unsigned int (*)())'} [-fpermissive]
   42 |     sumscadPtrArr[1] = &scad;

这很明显,因为您将指向具有不同函数签名的函数的指针存储在 sumscadPtrArr[1] 中,而不是 parPtr

然后:

error: invalid conversion from 'parPtr' {aka 'unsigned int (*)()'} to 'unsigned int' [-fpermissive]
   51 |     unsigned int value1 = *parA;

所有此类将* 应用于parPtr 的调用以及用于将parPtr 分配给unsigned int 的类似错误。正确的方法是

unsigned int value1 = parA();

函数指针可以通过多种方式取消引用:

  1. (*fnPtr)()
  2. fnPtr()

您尝试使用sumscadPtrArr 创建的函数指针* 数组/表理想情况下应该包含相同类型的函数,或者您可以创建一个类似以下内容的结构:

struct fPtrTablle {
    int (*sumFn)(parPtr, parPtr);
    int (*scadFn)(parPtr, const unsigned int);
};

struct fPtrTablle FnTable = { sum, scad};

void initFnTable(void)
{
    FnTable.sumFn =  &sum;
    FnTable.scadFn = &scad;
}

然后从main() 调用它为:

initFnTable();

int sumVal = FnTable.sumFn(&par1, &par2);
int scadVal = FnTable.scadFn(&par3, x);

完整的可编译程序here

【讨论】:

  • 谢谢@Zoso,这很有启发性,我没有想到结构解决方案!我的代码在代码块上编译,但我想这是编译器的事情。无论如何,我知道我的代码有缺陷。再次感谢您指出我的弱点!