函数中生成的指针变量不能在函数指针的参数中传递

Pointer variables generated in functions cannot be passed in parameters of function pointers

提问人:Drox 提问时间:10/9/2023 更新时间:10/9/2023 访问量:53

问:

主题: 给定一个不超过 5 位数字的正整数,需要:

  1. 找出它有多少位数字;
  2. 分别输出每个数字;
  3. 以相反的顺序输出每个数字。例如,如果原始数字为 321,则应输出 123。

当我使用函数指针调用以下程序时,我发现参数“number”和“digit”无法传递给每个函数。

#include <stdio.h>
#include <stdlib.h>

void inputNumber(int *number){
    printf("Enter number: ");
    scanf_s("%d", number);
    while(*number <= 0 || *number > 9999){
        if(*number <= 0){
            printf("The number is not positive integer! Retry!\nEnter number: ");
        }
        if(*number > 9999){
            printf("The number is more than 5 digits! Retry!\nEnter number: ");
        }
        scanf_s("%d", number);
    }
}

void outputDigit(int *number, int *digit){
    int i;
    for(i = 0; *number != 0; i++){
        *number /= 10;
    }
    *digit = i;
    //printf("%d\n", *number);    Test Output
    printf("The number is %d digits!\n", i);
}

void outputNumber(int *number, int *digit){
    int base = 10;
    int temp = *number;
    for(int i = 1; i < *digit - 1; i++){
        base *= 10;
    }
    //printf("%d %d\n", *number, temp);    Test Output
    for(int i = 0; i < *digit; i++){
        printf("%d ", temp / base);
        temp -= temp / base * base;
        base /= 10;
    }
    printf("\n");
}

void outputReverseNumber(int *number, int *digit){
    int temp = *number;
    for(int i = 0; i < *digit; i++){
        printf("%d ", temp % 10);
        temp = (temp - temp % 10) / 10;
    }
    printf("\n");
}

void function(int *number, int *digit, void (*fun[])(int*, int*)){
    for(int i = 0; i < 3; i++){
        fun[i](number, digit);
    }
}

int main(){
    int *number = (int*)malloc(sizeof(int));
    int *digit = (int*)malloc(sizeof(int));
    void (*fun[3])(int*, int*) = {outputDigit, outputNumber, outputReverseNumber};
    inputNumber(number);
    function(number, digit, fun);
    free(number);
    free(digit);
    system("pause");
    return 0;
}

我希望函数指针中的参数由其他函数生成的指针变量传递。

C 参数传递 函数指针

评论

0赞 Some programmer dude 10/9/2023
有几件事:首先不要投射 malloc 的结果;其次,不要动态分配单个整数值。改用指针运算符获取指向变量的指针。喜欢&int number = 0; inputNumber(&number);
0赞 Some programmer dude 10/9/2023
你的实际问题是什么?当你说你不能传递和传递给函数时,到底发生了什么?是否收到生成错误或警告?然后将完整且完整的构建日志复制粘贴到您的问题中(连同用于构建的命令和选项)。如果你得到意想不到的结果,那么你给你的程序输入什么?预期实际产出是多少?如果遇到崩溃,调试器会说会发生什么?numberdigt
0赞 Some programmer dude 10/9/2023
请花一些时间刷新帮助页面,参加 SO 导览,并阅读如何提问。另外,请阅读有关如何编写“完美”问题的信息,尤其是其清单。然后编辑您的问题以改进它。
0赞 Some programmer dude 10/9/2023
作为一个有根据的猜测:你没有得到你期望的结果。这是因为修改了值。始终处理副本,不要在计算中直接使用指向的值。除非这个练习是关于指针的,否则你为什么要一开始就使用指针呢?你的实际任务是什么?它的实际要求和局限性是什么?outputDigit

答:

0赞 0___________ 10/9/2023 #1

当您用零覆盖每个函数时,下一个调用将使用该修改后的值。你已经陷入了副作用的陷阱。number

您需要在每次调用之前恢复它:

void function(int *number, int *digit, void (*fun[])(int*, int*))
{
    int savedNumber = *number;

    for(int i = 0; i < 3; i++)
    {
        fun[i](number, digit);
        *number = savedNumber;
    }
}

https://godbolt.org/z/6GWKqbfMq

1赞 Lundin 10/9/2023 #2

参数传递没有问题。问题在于,您一直在内部除以数字,从而确保在离开函数时原始数字为零。这可以通过改用临时变量来解决:outputDigit

void outputDigit(int *number, int *digit){
    int i;
    int tmp = *number;
    for(i = 0; tmp != 0; i++){
        tmp /= 10;
    }
    *digit = i;
    printf("The number is %d digits!\n", i);
}

另一个错误是检查数字是否大于位数,而不是五位数。应该是 。*number > 999999999

一般代码审查:

  • 避免,因为它的标准化程度很差。如果您检查结果,原始实际上支持读取固定数量的字符。但是,在这种特定情况下,将输入读取为字符串会方便得多,因为以 10 为基数的十进制数字是一种繁琐的格式,迫使您一遍又一遍地使用除法。scanf_sscanffgets

  • 在这里使用函数指针完全没有意义。数组中的各种函数执行不相关的任务,因此使用抽象层进行泛型编程只会使程序难以阅读,而不会获得任何好处。我认为您只是将它们用于学习目的。

  • 如果您使用 const 正确性,则可以避免此处的大错误,这意味着不应修改的指针参数应标记为只读。那是:

    void outputDigit(const int *number, int *digit);
    void outputNumber(const int *number, const int *digit);
    void outputReverseNumber(const int *number, const int *digit)
    

    尽管现在函数具有不同的类型,因此也无法再使用函数指针数组。

  • 通常,不要将算法(计算位数)与用户 I/O(打印或输入)混淆。程序员不期望一个名为的函数来计算一个数字,他们希望它打印一个数字。outputDigit

  • 对单个使用动态分配是没有意义的。同样,投射的结果是没有意义的。intmalloc

  • 在处理函数指针时,请始终使用 typedef,以提高可读性。在这种情况下,您可以执行以下操作:

    typedef void func_t (int*, int*);
    ...
    func_t* fun[3] = {outputDigit, outputNumber, outputReverseNumber};
    ...
    void function(int *number, int *digit, func_t* fun[3])