Passing pointer as argument c++ 2 compilers different results - c++

I was working with another computer science student today, and he said his class was covering pointers. He was trying to understand pointers by creating an example where he was passing a pointer as an argument to a function, and setting that referenced pointer argument inside the function equal to the hypotenuse of a triangle (two of the other sides of the triangle are also passed into the function as double arguments).
As I explained to him about how pointers worked, I coached him what he should do, and we ended up with something like the example code I have below. His compiler continually failed to compile despite our efforts, but the compiler for VS2013 worked okay.
My question is simply this: Is there anything we're doing wrong with the code I've presented below? I did tell him that you'd probably use dynamic memory allocation instead of setting the pointer equal to the address of another variable we define in the program, but it seems baffling to me why the code won't compile. Same exact code, one compiles, the other doesn't. I just want to be sure the information I'm giving out is correct, of course.
And of course, much thanks to the stackoverflow community.
#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 was edited because we did include the cmath header, I just forgot to write it in this example because VS2013 doesn't require it. My apologies.

Both GCC and Visual C++ are conforming here. If we look to the draft C++ standard, section [res.on.headers]:
A C++ header may include other C++ headers. A C++ header shall provide
the declarations and definitions that appear in its synopsis. A C++
header shown in its synopsis as including other C++ headers shall
provide the declarations and definitions that appear in the synopses
of those other headers.
Somewhere in its standard library, Visual C++ decided to include <cmath>. From now on, follow good practice and always include headers for functions you use.

The code as posted in this question will not compile with gcc as is because it is lacking the include of the math header that defines sqrt. Your compiler error/warnings should clearly show this problem, pay close attention to those messages.
Because sqrt is not part of the c++ language you have to add an include for the cmath header. It is possible that in some iteration of your friends code you had included this header directly or indirectly however without the information about the compiler used there and an exact error message this is purely speculation, you need to include that information in a question like this to get a better answer. When you include the cmath the code will compile and run without issue.

What is the wanted result of your code?
You are calculating a hypotenuse and then
Displaying pointer's address ptr and double c's contents.
Prossible mistakes:
Omitted header for the calculations inside the function
Solution:
add header the line: #include <cmath>

I'm pretty close to closing this question. I don't think I will be able to get the compiler error message, and the question that was really being asked here was if I did anything wrong in the code that I shouldn't do. It seems to me that the answer to the question is, "Well, that depends," and it depends on the compiler; but I would like to write code that is, of course, portable.
Now, I know I've made a few small errors of bad programming practice, such as not passing by reference, forgetting to include the header for cmath, and maybe assigning a pointer to the address of an undefined variable.... and I could have made a return type instead of passing a pointer argument and so on. Although, it doesn't seem that I've done anything that should invoke the compiler error, but hey, who am I and what do I know?
I cannot get the error message from the student who compiled the code, but I believe the IDE he was using was cloud nine, an online IDE that works in browser. I don't know which version of gcc or g++ it's using, and I went to the website, signed up, and was able to compile my code just fine. I can assure you it was the same exact code I used because I took it from my email, the same code he was unable to compile on his own machine or on his own account at cloud 9.
So I think the answer to this question is that I haven't done anything that would violate the language of C++, if I can put it that way.
Anyway, just thought I'd say thanks anyway, and sorry for wasting people's time.

First off initializing a pointer without a value (double* ptr;) is bad practice and could lead to undefined behavior.
Most of the time you should not declare a void _ (T,T*) function and should instead replace the T* with a return value. This allows for return value optimizations to basically inline the functional call. It also is much more readable:
double hyp;
hypotenuse(3, 4, &hyp);
vs
double hyp = hypotnuse(3, 4);
I understand that you were teaching about pointers, but still it is much better to do an example where pointers/references make sense:
int /* error code */
getyx(int* y, int* x);
Then you can use:
int y,x;
if(getyx(&y,&x)) {
/* use value */
} else {
/* error handling */
}

Related

How can I declare variables with illegal names (such as "int double = 0")?

I have tried to do this but I'm unable. How can i declare a number of variables with legal and illegal names (such as int double = 0;), so that you can see how the compiler reacts.
The short answer to this is DON'T DO IT.
There are a number of reserved words in the C and C++ standards that should not be used for any purpose other than which they are originally intended. Going out of your way to recycle these for your own perverse purpose is going to create problems for a lot of people. One of those people might be yourself fin the future when you have to fix a bug.
If you want to use double as a variable name, the best method to make this happen is to successfully petition the C++ committee constructing the next standard to allow it. Then you will have a valid program.
If you want to see how the compiler behaves when encountering this problem, create tiny programs that are as small as practical. For example:
// invalid_double.c
int double = 0;
You'll immediately see a syntax error when trying to compile that. Repeat as necessary with other keywords. This is often how things like configure run tests to verify the behaviour and capabilities of the local compiler.
Your compiler will probably halt compilation at the first invalid use of a keyword so you may need to construct one file per experiment. Subsequent errors in the same file may be ignored, such as if you had int class = 0
it is like a Quote from (Programming__Principles_and_Practice_Using C++),I think the auther asks us to try it and see the error no more(just we try it ourselfes).

Why does iostream define an abs function, and how can I stop it?

The following c++ code does not compile:
int main() {
double a = abs(5.1);
return 0;
}
It complains that abs is not defined, of course. But the following does compile:
#include <iostream>
int main() {
std::cout << abs(5.1) << std::endl;
std::cout << abs(-5.1) << std::endl;
return 0;
}
It outputs two 5's (not 5.1's). This is bad for lots of reasons. First, abs is such a natural and common function that I use it all the time, but the int part is almost never what I want returned. Second, it's much too easy for me (or people using my code) to just write abs and not notice that it compiles but does the wrong thing, because I'm (they're) really good at overlooking warnings. Third, I just plain don't understand why iostream bothers defining an abs function anyway. Fourth, I really don't understand why it goes into the global namespace.
Is there any way I can prevent this objectionable abs function from going into my global namespace?
If it matters, I'm using
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.6)
Most likely iostream includes stdlib.h to do some of its work. This is the C version of the header which declares abs for int only in the global namespace (in C you had to use fabs for double values).
I'm not aware of any specific way to keep abs from being included that way but I do know that g++ 4.5 is much better at not having excess stuff brought in by basic includes like iostream and string.
It may also be possible to get a warning that the double is being truncated to int (EDIT: yes, use -Wconversion to warn).
In C, including one standard header was not allowed to act like it included any other standard header. This avoided the problem you're seeing, at considerable expense in difficulty implementation.
C++ allows any standard header to include any other standard header. This makes implementation considerably easier, but can lead to exactly the sort of problem you're seeing, where including a seemingly-unrelated header has made a function visible that you didn't really want to use, instead of getting an error because the function you used isn't declared at all.
Unfortunately, I don't think there's an easy way to deal with this. Although it's pretty easy to imagine <iostream> being independent of <stdlib.h>, it's much easier to see how it might need/want definitions of things like ios_base. It would take quite a bit of extra work to define things to prohibit the former while allowing the latter.
I should mention, however, that over time this situation does seem to be improving quite a bit. Ten years ago, it was fairly common to get virtually all standard headers from including almost any one of them. Although most still include at least a few that aren't strictly required, they're generally much closer to each defining only what it's required to.
If this is an ongoing maintenance problem, why not add a little code at the beginning of the program which specifically checks for the abs() problem?
// test if abs() is defined incorrectly, as would happen if <stdlib.h> were
// included by <iostream>. abs() it should return a float/double, not an int
// (put suggestions here how to fix problem)
if (abs(-5.1) == 5)
{
std::cerr << "Invalid build: abs() defined improperly, ..." << std::endl;
return 2; // exit program by returning from main
}
That will make it a lot harder for warnings to be overlooked.

Using void in functions without parameter?

In C++ using void in a function with no parameter, for example:
class WinMessage
{
public:
BOOL Translate(void);
};
is redundant, you might as well just write Translate();.
I, myself generally include it since it's a bit helpful when code-completion supporting IDEs display a void, since it ensures me that the function takes definitely no parameter.
My question is, Is adding void to parameter-less functions a good practice? Should it be encouraged in modern code?
In C++
void f(void);
is identical to:
void f();
The fact that the first style can still be legally written can be attributed to C.
n3290 ยง C.1.7 (C++ and ISO C compatibility) states:
Change: In C++, a function declared with an empty parameter list takes
no arguments.
In C, an empty parameter list means that the number and
type of the function arguments are unknown.
Example:
int f(); // means int f(void) in C++
// int f( unknown ) in C
In C, it makes sense to avoid that undesirable "unknown" meaning. In C++, it's superfluous.
Short answer: in C++ it's a hangover from too much C programming. That puts it in the "don't do it unless you really have to" bracket for C++ in my view.
I see absolutely no reason for this. IDEs will just complete the function call with an empty argument list, and 4 characters less.
Personally I believe this is making the already verbose C++ even more verbose. There's no version of the language I'm aware of that requires the use of void here.
I think it will only help in backward compatibility with older C code, otherwise it is redundant.
I feel like no. Reasons:
A lot more code out there has the BOOL Translate() form, so others reading your code will be more comfortable and productive with it.
Having less on the screen (especially something redundant like this) means less thinking for somebody reading your code.
Sometimes people, who didn't program in C in 1988, ask "What does foo(void) mean?"
Just as a side note. Another reason for not including the void is that software, like starUML, that can read code and generate class diagrams, read the void as a parameter. Even though this may be a flaw in the UML generating software, it is still annoying to have to go back and remove the "void"s if you want to have clean diagrams

VC++ compiler and type conversion?

When I moved a program from a Mac to this Windows PC, the VC++ 2008 compiler is giving me errors for passing unsigned ints to the cmath pow() function. As I understand, this function is not overloaded to accept anything but floating-point numbers.
Is there some compiler flag/setting that will ignore these errors? Also does anyone know how to find the documentation on the VC++ compiler?
Edit
This isn't a warning, it's an error. However, for me it's not an issue since my program is only dealing with numbers that come out as integers, so I don't care that they aren't floats. If it was just warnings I would move on with my life, but it's not letting me compile. Can I suppress errors somehow? Like I said, the errors aren't coming up on my Mac and the program is fine.
Regarding other answers here, it is not a good idea to tell the question author to turn off this warning. His code is broken - he's passing an unsigned int instead of a float. You should be telling him to fix his code!
This isn't a warning, it's an error. However, for me it's not an issue since my
program is only dealing with numbers that come out as integers, so I don't care that
they aren't floats. If it was just warnings I would move on with my life, but it's not
letting me compile. Can I suppress errors somehow? Like I said, the errors aren't
coming up on my Mac and the program is fine.
Integers and floats use different representations internally. If you have the same number in an int and a float, the bit pattern inside the storage for them is completely different. You cannot under any circumstances whatsoever expect your code to work if you are passing an integer when you should be passing a float.
Furthermore, I assert your Mac code either is silently using an overloaded version of that function (e.g. you are on that platform compiling with C++) or you believe it works when in fact it is working by chance or is not actually working.
Addendum
No compilers ever written has the ability to turn off errors.
A warning means the compiler thinks you're making a mistake.
An error means the compiler doesn't know what to do.
There are a couple of options:
In C, the solution is simply to cast the ints to doubles:
pow((double)i, (double)j)
In C++, you can do the same, although you should use a C++-style cast:
pow(static_cast<double>(i), static_cast<double>(j))
But a better idea is to use the overload C++ provides:
std::pow(static_cast<double>(i), j);
The base still has to be a floating-point value, but the exponent can be an int at least
The std:: prefix probably isn't necessary (most compilers make the function available in the global namespace as well).
Of course, to access the C++ versions of the function, you have to include the C++ version of the header.
So instead of #include <math.h> you need to #include <cmath>
C++ provides C++ versions of every C header, using this naming convention. If the C header is called foo.h, the C++ version will be cfoo. When you're writing in C++, you should always prefer these versions.
I don't know of a flag, but getting rid of the warnings was easy enough for me. Just double click on each of the warnings in the "Task List" and add the appropriate casting, whether you prefer
(double) my_variable
or
static_cast<double>(my_variable)
I'm guessing if you're getting the ambiguous warning, there are multiple pow functions defined somewhere. It's better to be explicit in my opinion anyway. For what it's worth, my vote goes with the static_cast option.
As Mehrdad mentioned, use the #pragma warning syntax to disable a warning. Documentation is here - http://msdn.microsoft.com/en-us/library/2c8f766e.aspx
I would be inclined to fix the warnings rather than hide them though!
C++ has overloads for pow/powf for int exponents. Heed the warning.
Don't ignore this or any warnings. Fix them. The compiler is your friend, trying to get you to write good code. It's a friend that believes in tough love, but it is your friend.
If you have an unsigned int and need a float, convert your unsigned in to a float.
And the MSDN Library is the documentation for both the VC++ implementation of the language and the IDE itself.

How can I trust the behavior of C++ functions that declare const?

This is a C++ disaster, check out this code sample:
#include <iostream>
void func(const int* shouldnotChange)
{
int* canChange = (int*) shouldnotChange;
*canChange += 2;
return;
}
int main() {
int i = 5;
func(&i);
std::cout << i;
return 0;
}
The output was 7!
So, how can we make sure of the behavior of C++ functions, if it was able to change a supposed-to-be-constant parameter!?
EDIT: I am not asking how can I make sure that my code is working as expected, rather I am wondering how to believe that someone else's function (for instance some function in some dll library) isn't going to change a parameter or posses some behavior...
Based on your edit, your question is "how can I trust 3rd party code not to be stupid?"
The short answer is "you can't." If you don't have access to the source, or don't have time to inspect it, you can only trust the author to have written sane code. In your example, the author of the function declaration specifically claims that the code will not change the contents of the pointer by using the const keyword. You can either trust that claim, or not. There are ways of testing this, as suggested by others, but if you need to test large amounts of code, it will be very labour intensive. Perhaps moreso than reading the code.
If you are working on a team and you have a team member writing stuff like this, then you can talk to them about it and explain why it is bad.
By writing sane code.
If you write code you can't trust, then obviously your code won't be trustworthy.
Similar stupid tricks are possible in pretty much any language. In C#, you can modify the code at runtime through reflection. You can inspect and change private class members. How do you protect against that? You don't, you just have to write code that behaves as you expect.
Apart from that, write a unittest testing that the function does not change its parameter.
The general rule in C++ is that the language is designed to protect you from Murphy, not Machiavelli. In other words, its meant to keep a maintainance programmer from accidentally changing a variable marked as const, not to keep someone from deliberatly changing it, which can be done in many ways.
A C-style cast means all bets are off. It's sort of like telling the compiler "Trust me, I know this looks bad, but I need to do this, so don't tell me I'm wrong." Also, what you've done is actually undefined. Casting off const-ness and then modifying the value means the compiler/runtime can do anything, including e.g. crash your program.
The only thing I can suggest is to allocate the variable shouldNotChange from a memory page that is marked as read-only. This will force the OS/CPU to raise an error if the application attempts to write to that memory. I don't really recommend this as a general method of validating functions just as an idea you may find useful.
The simplest way to enforce this would be to just not pass a pointer:
void func(int shouldnotChange);
Now a copy will be made of the argument. The function can change the value all it likes, but the original value will not be modified.
If you can't change the function's interface then you could make a copy of the value before calling the function:
int i = 5;
int copy = i
func(&copy);
Don't use C style casts in C++.
We have 4 cast operators in C++ (listed here in order of danger)
static_cast<> Safe (When used to 'convert numeric data types').
dynamic_cast<> Safe (but throws exceptions/returns NULL)
const_cast<> Dangerous (when removing const).
static_cast<> Very Dangerous (When used to cast pointer types. Not a very good idea!!!!!)
reinterpret_cast<> Very Dangerous. Use this only if you understand the consequences.
You can always tell the compiler that you know better than it does and the compiler will accept you at face value (the reason being that you don't want the compiler getting in the way when you actually do know better).
Power over the compiler is a two edged sword. If you know what you are doing it is a powerful tool the will help, but if you get things wrong it will blow up in your face.
Unfortunately, the compiler has reasons for most things so if you over-ride its default behavior then you better know what you are doing. Cast is one the things. A lot of the time it is fine. But if you start casting away const(ness) then you better know what you are doing.
(int*) is the casting syntax from C. C++ supports it fully, but it is not recommended.
In C++ the equivalent cast should've been written like this:
int* canChange = static_cast<int*>(shouldnotChange);
And indeed, if you wrote that, the compiler would NOT have allowed such a cast.
What you're doing is writing C code and expecting the C++ compiler to catch your mistake, which is sort of unfair if you think about it.