在"理解C中的指针"一书中,在解释了一个参数之后,存在一些已解决的问题.第22页,问题N.5我将附上代码和解释.在那之后,我会有问题.
#include <stdio.h>
int main()
{
int *c;
c = check(10, 20);
printf("c = %p\n",c);
return 0;
}
int * check(int i, int j)
{
int *p, *q;
p = &i;
q = &j;
if(i >= 45)
{
return p;
}
else
{
return q;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:错误消息:主要中的非可移植指针分配
说明错误的原因很简单.传递给check()的整数在i和j中收集,然后将它们的地址分配给p和q.然后在下一个语句中,i的值针对45进行测试,并返回存储在p中的地址或存储在q中的地址.看来这个地址将在main()中的c中收集,然后打印出来.而且存在错误.函数check()不能返回整数指针.它可以返回的只是一个普通的整数.因此,仅将c声明为整数指针是不够的.我们必须在程序中进行以下修改才能使其正常工作
#include <stdio.h>
int * check(int, int);
int main()
{
int *c;
c = check(10, 20);
printf("c = %p\n",c);
return 0;
}
int *check(int i, int j)
{
......
......
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这没有意义.作者为了在第一段代码上故意发出错误,试图在main中使用一个指向未分配的内存区域的指针.但他"试图"解决问题的方式根本不正确,他没有改变任何东西!相反,他应该在check()函数中使用malloc一些内存区域.我对么?
这实际上是关于尚未声明的函数的默认返回值.在您的第一个示例中,当编译器看到该行时,c = check(10, 20);它还不知道该函数将返回什么.标准说编译器应该假设返回是一个int.这就是这就是:a的大小int可能与a int *(指针)的大小不同.为了使编译器始终为此发出正确的机器代码,它必须知道check返回一个指针,这就是它需要声明的原因.这就是第二个例子的作用:它告诉编译器"会有一个名为'check'的函数,它看起来像这样".
除此之外,这个例子非常糟糕.将参数check推送到堆栈然后函数返回指向这些堆栈位置的指针.但是在功能退出后,不能保证这些堆栈位置再次有效.这是未定义的行为,这意味着允许编译器做任何它喜欢的事情,甚至让你的计算机爆炸.这个具体的例子实际上应该工作,因为它只打印指针(即它指向的地址),但它实际上并没有解除引用它(这是从指针指向的地址读取).在大多数机器/编译器上,即使解除引用也应该"正确"工作,但您可能不会依赖它.