【问题标题】:the multiplication result is always zero because of pointers?由于指针,乘法结果总是为零?
【发布时间】:2021-04-06 20:47:45
【问题描述】:

我正在尝试编写一个程序,该程序从用户那里获取两个整数并将它们分配给指针,然后将这些指针传递给函数以将它们相乘并打印结果。但是输出始终为 0。我是初学者,我无法理解我做错了什么。帮助表示赞赏。这是我的代码:

#include <stdio.h>

int x, y, m;

void point(int *xPtr, int *yPtr);

int main()
{
    int *xPtr, *yPtr;
    
    printf("Enter two integers: \n");
    scanf("%d %d", &x, &y);

    point(&x, &y);

    m = (*xPtr)*(*yPtr);

    xPtr = &m;

    printf("The result is %d", *xPtr);

    return 0;
}

void point(int *xPtr, int *yPtr)
{
    xPtr = &x;
    yPtr = &y;
}

【问题讨论】:

  • 请参考books 以更好地理解该语言。

标签: c function pointers recursion multiplication


【解决方案1】:

main 中,变量 xPtryPtr 永远不会被初始化

point 中的赋值是局部的,如果要修改 main 中具有相同名称的变量,则不会影响 point你可以这样做:

void point(int **xPtr, int **yPtr)
{
    *xPtr = &x;
    *yPtr = &y;
}

当然也改变point的声明,把main中的调用改为:

point(&xPtr, &yPtr);

... 但是输出始终为 0

我认为你给出的程序没有任何输出,因为你很可能无法到达打印,你尊重未初始化的指针,行为未定义并且通常像分段错误一样是灾难性的


修改你的程序:

#include <stdio.h>

int x, y, m;

void point(int **xPtr, int **yPtr);

int main()
{
    int *xPtr, *yPtr;
    
    printf("Enter two integers: \n");
    scanf("%d %d", &x, &y);

    point(&xPtr, &yPtr);

    m = (*xPtr)*(*yPtr);

    xPtr = &m;

    printf("The result is %d", *xPtr);

    return 0;
}

void point(int **xPtr, int **yPtr)
{
    *xPtr = &x;
    *yPtr = &y;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
Enter two integers: 
2 3
The result is 6pi@raspberrypi:/tmp $ 
pi@raspberrypi:/tmp $ 
pi@raspberrypi:/tmp $ valgrind ./a.out
==5992== Memcheck, a memory error detector
==5992== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5992== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5992== Command: ./a.out
==5992== 
Enter two integers: 
2 3
The result is 6==5992== 
==5992== HEAP SUMMARY:
==5992==     in use at exit: 0 bytes in 0 blocks
==5992==   total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==5992== 
==5992== All heap blocks were freed -- no leaks are possible
==5992== 
==5992== For lists of detected and suppressed errors, rerun with: -s
==5992== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
pi@raspberrypi:/tmp $ 

这样更好:

  • 检查 scanf 返回 2 以了解输入是否有效,
  • 打印最终的\n,因为您可以在上面执行结果在终端中执行您的程序是不可读的,
  • 以高警告级别编译并考虑生成警告

关于最后一句话和使用你的代码版本:

 pi@raspberrypi:/tmp $ gcc -g -Wall cc.c
 cc.c: In function ‘main’:
 cc.c:16:10: warning: ‘xPtr’ is used uninitialized in this function [-Wuninitialized]
      m = (*xPtr)*(*yPtr);
          ~^~~~~~
 cc.c:16:18: warning: ‘yPtr’ is used uninitialized in this function [-Wuninitialized]
      m = (*xPtr)*(*yPtr);
                 ~^~~~~~

如果我在 valgrind 下执行它:

pi@raspberrypi:/tmp $ valgrind ./a.out
==7143== Memcheck, a memory error detector
==7143== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7143== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==7143== Command: ./a.out
==7143== 
1 2Enter two integers: 

==7143== Use of uninitialised value of size 4
==7143==    at 0x104BC: main (cc.c:16)
==7143== 
==7143== Invalid read of size 4
==7143==    at 0x104BC: main (cc.c:16)
==7143==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7143== 
==7143== 
==7143== Process terminating with default action of signal 11 (SIGSEGV)
==7143==  Access not within mapped region at address 0x0
==7143==    at 0x104BC: main (cc.c:16)
==7143==  If you believe this happened as a result of a stack
==7143==  overflow in your program's main thread (unlikely but
==7143==  possible), you can try to increase the size of the
==7143==  main thread stack using the --main-stacksize= flag.
==7143==  The main thread stack size used in this run was 8388608.
==7143== 
==7143== HEAP SUMMARY:
==7143==     in use at exit: 0 bytes in 0 blocks
==7143==   total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==7143== 
==7143== All heap blocks were freed -- no leaks are possible
==7143== 
==7143== Use --track-origins=yes to see where uninitialised values come from
==7143== For lists of detected and suppressed errors, rerun with: -s
==7143== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Erreur de segmentation
pi@raspberrypi:/tmp $ 

【讨论】:

  • 不错的答案!如果我们从不在堆上分配任何内存,我可以知道我们是否需要在程序中使用 valgrind?
  • @jarvis 在没有任何动态分配等的情况下取消引用可能是非法的;-) 在答案中使用它是一种警告 OP 其存在的方式
  • 对不起,我是这个网站的新手,不知道它
  • @uwuuwu 没问题,新年快乐 ;-)
【解决方案2】:

由于您正在修改指针本身,因此您需要将指针传递给这些指针(并在调用函数时传递指针的地址):

point(&xPtr, &yPtr);

这样定义你的函数:

void point(int **xPtr, int **yPtr) {
    *xPtr = &x;
    *yPtr = &y;
}

别忘了修改声明

void point(int **xPtr, int **yPtr);

【讨论】:

    猜你喜欢
    • 2017-12-07
    • 2020-09-10
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2011-02-15
    • 1970-01-01
    • 2015-05-19
    相关资源
    最近更新 更多