将指针作为参数传递给c++ 2编译器会得到不同的结果

Passing pointer as argument c++ 2 compilers different results

本文关键字:结果 编译器 指针 参数传递 c++      更新时间:2023-10-16

我今天和另一个计算机科学专业的学生一起学习,他说他的课是关于指针的。他试图通过创建一个例子来理解指针,在这个例子中,他将一个指针作为参数传递给一个函数,并将函数内部的引用指针参数设置为三角形的斜边(三角形的另外两条边也作为双参数传递给函数)。

当我向他解释指针的工作原理时,我指导他应该怎么做,我们最终得到了类似下面的示例代码。尽管我们努力了,他的编译器还是无法编译,但是VS2013的编译器工作得很好。

我的问题很简单:我下面给出的代码有什么地方做错了吗?我确实告诉他,你可能会使用动态内存分配,而不是将指针设置为我们在程序中定义的另一个变量的地址,但我似乎很困惑为什么代码无法编译。同样的代码,一个可以编译,另一个不能。当然,我只是想确保我所提供的信息是正确的。

当然,非常感谢stackoverflow社区。

#include <iostream>
#include <cmath>
using namespace std;
void hypotenuse(double a, double b, double *ptr);
int main()
{
    //double *ptr = new double;
    double *ptr;
    double c;
    ptr = &c;
    hypotenuse(3, 4, ptr);
    cout << ptr << 'n' << *ptr;
    cin.get();
}
void hypotenuse(double a, double b, double *ptr)
{
    *ptr = sqrt(a*a + b*b);
}

Post被编辑了,因为我们确实包含了cmath头,我只是忘记在这个例子中写它,因为VS2013不需要它。我的歉意。

GCC和Visual c++在这里都是一致的。如果我们看一下c++标准草案,section [res.on.headers]:

一个c++头文件可以包含其他的c++头文件。c++头文件应该提供在概要中出现的声明和定义。一个c++在其概要中显示的包含其他c++头文件的头文件应当提供大纲中出现的声明和定义

在它的标准库中,Visual c++决定包含<cmath>。从现在开始,遵循良好的实践,总是为您使用的函数包含头文件。

这个问题中的代码不能用gcc编译,因为它缺少定义sqrt的math头文件。你的编译器错误/警告应该清楚地显示这个问题,密切关注这些消息。

因为sqrt不是c++语言的一部分,你必须为cmath头添加一个include。可能,在你的朋友代码的一些迭代中,你已经直接或间接地包括了这个头,但是没有关于那里使用的编译器的信息和一个确切的错误消息,这纯粹是猜测,你需要在这样的问题中包括这些信息,以获得更好的答案。当您包含cmath时,代码将编译并运行而不会出现问题。

您的代码想要的结果是什么?

  1. 你正在计算斜边,然后
  2. 显示指针地址ptrdouble c的内容。

Prossible错误:

  1. 省略了函数内部计算的头信息

解决方案:

add header the line: #include <cmath>

我差不多要结束这个问题了。我不认为我将能够得到编译器错误信息,这里真正被问到的问题是,如果我在代码中做错了什么,我不应该做的。在我看来,这个问题的答案是,"嗯,那要看情况",这取决于编译器;但是我想写的代码当然是可移植的。

现在,我知道我犯了一些糟糕的编程实践的小错误,比如没有通过引用传递,忘记包含cmath的头,以及可能将指针分配给未定义变量....的地址我可以创建一个返回类型,而不是传递一个指针参数等等。虽然,我似乎没有做任何应该调用编译器错误的事情,但是,嘿,我是谁,我知道什么?

我无法从编译代码的学生那里得到错误信息,但我相信他使用的IDE是cloud nine,一个在浏览器中工作的在线IDE。我不知道它使用的是gcc还是g++的哪个版本,我去了网站,注册了,并且能够编译我的代码。我可以向你保证,这和我用的代码是一样的,因为我是从我的电子邮件中取的,这段代码他无法在自己的机器上或在cloud 9上自己的帐户上编译。

所以我认为这个问题的答案是,如果我可以这么说的话,我没有做任何会违反c++语言的事情。不管怎样,我还是想说声谢谢,很抱歉浪费了大家的时间。

首先,初始化一个没有值的指针(double* ptr;)是不好的做法,可能导致未定义的行为。

大多数情况下不应该声明void _ (T,T*)函数,而应该用返回值替换T*。这允许返回值优化基本上内联函数调用。它也更可读:

double hyp;
hypotenuse(3, 4, &hyp);

double hyp = hypotnuse(3, 4);

我明白你刚才讲的是指针,但还是做一个指针/引用有意义的例子要好得多:

int /* error code */
getyx(int* y, int* x);

那么你可以使用:

int y,x;
if(getyx(&y,&x)) {
    /* use value */
} else {
    /* error handling */
}