I started learning c++ about 3 weeks ago after 2 years of java. It seems so different but im getting there. my lecturer is a lovely guy but any time i ask a question as to why something is that way or this way. he just responds "because it is".
Theres lots of comments in the code below with a few random questions, but the main problem is im getting two build errors, one says the arraytotal has not been initialized (even though i found a value for it) and the other says an external reference in main.
would anyone mind reading the code and answering a few comments within, and maybe the overall problem im having?
#include<string>
#include<fstream>
#include<ostream>
using namespace std;
//double decimals[5] ={2,4,6,8,10};
const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
//double decimals[arraySize];
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
// why do you have to write the name of the function up here before you even create it?
double averageN();
int main()
{
averageN();
return 0;
}
// why does the array have to be created here?
double averageN(double decimals[arraySize])
{
double average;
double arrayTotal;
for (int i = 0; i<5;i++)
{
// fills with random numbers from 0 - 10
decimals[i] = (0+(rand()%10));
}
// find the total of all the elements in the array
for (int i = 0; i < arraySize;i++)
{
double currentElement = decimals[i];
arrayTotal = (currentElement+arrayTotal);
//arrayTotal +=decimals[i]) ;
}
// return the average
average = (arrayTotal/arraySize);
return 0.0;
}
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
Yes, it has to be const, moreover, it must be a constant expression, which means its size must be known at compile-time (not at runtime).
If you want to resize arrays, then the best is to use the standard container std::vector. Or use dynamically allocated arrays if you want a fixed-size array, but the size is not known until runtime
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
if you speak about decimals, then no, it is a global variable, you can use it from anywhere.
// why do you have to write the name of the function up here before you even create it?
You must declare any name in C++ prior to its use. Since you call this function in main, it must be at least declared beforehand. You can also provide the definition (body) before main.
// why does the array have to be created here?
Oops, it appears that there's a big mixup in your code. As a matter of fact, you have 2 functions named averageN, one is averageN that takes no parameters, other is AveraeN taking an array of double.You never defined the first one, just declared.
Errors:
doubleTotal is not initialized. Well it is not
double arrayTotal; change to
double arrayTotal = 0.0;
unresolved extenal in main - that's the AverageN function in main you are caling. You never wrote a body for it. You created a function that takes an array, which wasn't useful since your array is global. Just delete the array parameter from AverageN definition.
HTH
P.S. Read S. Lippmann's C++ Primer. It's the best book for beginners ther is for C++. IMO :)
const gives the compiler a clue that the item should not be changed and if the code attempts it then the compiler can flag an error.
the function name is mentioned before the actual declaration the main() function needs to reference it before the compiler has actually come to compile it (as it later on in the code file). You can move the whole function before the main() to avoid this.
double averageN(double decimals[arraySize]) is saying this function takes an array. It doesn't say that it create the array. If you look in the function, it takes the array, and adds calculated values into it (decimals[i] = (0+(rand()%10))). This function also calculates an average over the array and returns that as a double.
So to answer your big question what's wrong - read the last point and look at the call you are making -averageN(); - can you see how this is not the correct call?
OK, here's your only assignment into arrayTotal:
arrayTotal = (currentElement+arrayTotal);
Now, what is the value of arrayTotal after this assignment? Well, it depends on its value before the assignment. What was its value before the very first assignment? You don't know. It could be anything because you never gave it an initial value.
const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
C++ basically supports two kinds of arrays: fixed-size arrays, that are declared as type name[size], and dynamic arrays that are allocated with new[].
For fixed-size array you must provide their size to the compiler so that it can set aside enough memory for the array. As the size must be known to the compiler, you can only specify it with a const variable or a literal.
Although it is possible to create dynamically allocated arrays yourself, by invoking new[], this will give you some headaches getting the memory management right. It is better to use existing classes that do this for you, like std::vector.
//double decimals[arraySize];
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
You can create it up here, but that would give anybody access to the array. For a small program like this that is not a big problem, but consider that there are a dozen other files that can also access the array and change it at unexpected moments.
It is basically the same question as to why you don't make all classes and members public in Java: to limit who has access.
// why do you have to write the name of the function up here before you even create it?
double averageN();
You have to declare the function before you can use it. C++ has the requirement that all names you use must have been declared to the compiler before their first use, and the compiler will read a file in sequential order from the top to the bottom.
Note that this declaration does not match the function definition you give below. As C++ supports function overloading, the two are considered different functions, because they accept different parameters (none versus a pointer)
int main()
{
averageN();
return 0;
}
// why does the array have to be created here?
double averageN(double decimals[arraySize])
{
This does not create an array. Instead it specifies that the function expects to be called with a pointer argument (the arraySize is completely ignored and you can't pass an array to a function in C++, so the parameter is adjusted to read double *decimals).
To get a working program, you need to change the two lines above to
double averageN()
{
double decimals[arraySize];
double average;
double arrayTotal;
Both average and arrayTotal are not initialised. That means they will start with some unknown value.
For average, thatis not a problem, because the first thing you do with it is assign a new value. But for arrayTotal, you are adding values to it, so you must let it start with a known value.
for (int i = 0; i<5;i++)
{
// fills with random numbers from 0 - 10
decimals[i] = (0+(rand()%10));
}
// find the total of all the elements in the array
for (int i = 0; i < arraySize;i++)
{
double currentElement = decimals[i];
arrayTotal = (currentElement+arrayTotal);
//arrayTotal +=decimals[i]) ;
}
// return the average
average = (arrayTotal/arraySize);
return 0.0;
}
My quick answers without double checking (its been awhile since I've developed in C++) are:
arraytotal has not been initialized
I suspect that your compiler flags this as an error to make sure you do it. If you don't, you can't be sure what it will be initialized to. Traditionally for debug builds, C/C++ initialized memory to some debug value to help identify uninitialized variables. Set arrayTotal = 0 when it is initialized and that should go away. (Best practice)
e.g. double arrayTotal = 0;
external reference in main
I suspect this is because your prototype for averageN does not match the method defined later. A prototype needs to include the types of the parameters as well as the return type. Change the prototype from double averageN(); to double averageN(double []); and I believe that will fix that problem.
does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
Since you are using it to define the size of the array passed into averageN, yes. Setting the size of the array like this requires a constant value.
This array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
It is not being created in averageN. It is a formal parameter to averageN. The caller of averageN needs to provide the appropriate variable and pass it in. Then from within the method, you access it through decimals.
why do you have to write the name of the function up here before you even create it?
This is the function prototype. It is necessary if the function is referenced in code before the function is defined. This could be resolved in other ways as well, such as moving the definition of averageN before all uses of it.
Couple of problems:
Your forward declaration of averageN is not correct
Code:
double averageN();
The supplied version below takes a parameter.
Your declaration of averageN does not quite work
Declaring parameters of type array is not intuitively obvious.
Normally people let the array degrade to a pointer to the array and pass a length as a second parameter.
Code:
double averageN(double *decimals, int arraySize)
If you want to only pass arrays of a specific size you need to do so by reference:
double averageN(double (&decimals)[arraySize])
Your call to averageN() in main.
You are passing zero parameters. Now this matches the forward declaration but not the actual definition.
Result I would change the code like this:
extern double averageN(double (&decimals)[arraySize]);
int main()
{
double data[arraySize];
averageN(data);
return 0;
}
// why does the array have to be created here?
double averageN(double (&decimals)[arraySize])
{
In addition to the technical details of the other answers, instead answering the complaint in your first paragraph: one way to get quality answers to "why" C++ questions is to ask in one of the Usenet groups, because, like with StackOverflow there are Real Experts hanging out there, but unlike StackOverflow even a beginner's question is likely to get an answer from a member of the standardization committee, and if you're lucky even from those who have penned the standard (like Andrew Koenig or currently Pete Becker). In earlier times Bjarne was there too. But recent years he hasn't posted much.
Basic novice "why" questions:alt.comp.lang.learn.c-c++. Francis Glassborow hangs out there. He's a committe member and author of several successful C++ introductory books. He also knows a bit of math, and since the posting frequency there is low (what with StackOverflow!), you are almost assured that any halfway interesting question will be answered almost immediately -- and correctly -- by Francis, in a snap. :-)
General questions about the C++ language: comp.lang.c++and/or comp.lang.c++.moderated. The latter group is moderated and has a charter. The moderation reduces noise -- e.g. no spam -- but adds delay. Some committee members prefer to post mostly in the unmoderated group (e.g. James Kanze), some, like Pete Becker and Howard Hinnant, post in both groups, and some well known experts, e.g. Andrei Alexandrescu, now apparently only post in the moderated group.
Questions about what the standard means, reports about errors in the standard and so on (in earlier times this was also where you formally reported defects in the standard): [comp.std.c++]. This is also a moderated group, and unfortunately the mod delay is now almost unbearably long. But as a novice you're probably less interested in the formal details, and more interested in rationales and explanations, for which [comp.lang.c++] and [comp.lang.c++.moderated] are great groups (I think StackOverflow's main advantage is when you're wondering "what's the bug in this code" or questions that in principle can be resolved by just reading the relevant documentation).
Finally, I've linked to Google Groups which provides a web based interface, but you can access these groups more directly from a Usenet client like Thunderbird (or e.g. the Opera browser, which has a built-in client). All you have to do in order to access Usenet via a local client is to configure the client, telling it about a server, like the free EternalSeptember. Or AIOE.
Cheers & hth.,
– Alf
One thing nobody seems to have commented on: your return statement at the end of averageN is wrong. You say you're returning the average, then you calculate the radius, and then return 0.0;. Try return average; or return arrayTotal/arraySize;.
Related
Take for example:
int main(void){
numberComparator comparator1;
comparator1.setA(78.321);
comparator1.showA();
comparator1.setB('c');
comparator1.setB("Yes");
comparator1.setB(124.213);
comparator1.showB();
comparator1.setB(12);
return 0;
}
Instead of saying comparator1 over and over again, can I do something shorter?
I understand that this doesn't really change much about how the program works, but it does make it easier to work around with testing a class I make.
I am doing overloading so that for an assortment of inputs into my comparator, my program can handle them without making the results go crazy. In this case, I want the input to be an int, but what if the input isn't?
The answer could be lying around the internet, but as my title may infer, I do not know how to state the question.
You are looking for something like with keyword which is part of, for example, Pascal language.
Unfortunately, C++ doesn't provide similar feature. Using the references, one can shorten the name of the class and somewhat alleviate the pain, i.e.
Comparator comparator1;
...
{
Comparator& cr = comparator1;
cr.a();
cr.b();
cr.c();
}
It depends. If numberComparator has a "fluent" interface, then each member function will return a reference to *this, and you can write:
comparator1
.setA(78.321)
.showA()
.setB('c')
.setB("Yes")
.setB(124.213)
.showB()
.setB(12);
Note that this is a bitch to debug by step-into (you have to step into every function until you get to the one you are interested in).
The alternative of course is "use a shorter name".
int main(void){
numberComparator c1;
c1.setA(78.321);
c1.showA();
c1.setB('c');
c1.setB("Yes");
c1.setB(124.213);
c1.showB();
c1.setB(12);
return 0;
}
There is really no point in having a particularly long name if it is limited in scope to a few lines. For a local variable, if it isn't limited in scope to a few lines, your function is probably too long.
this is more like an ethical question:
if i have the following code:
void changeInt(int& value)
{
value = 7;
}
and i do:
int number = 3;
changeInt(number);
number will have value 7
I know that when the new stack frame will be created for changeInt function, new variables will be created and &value will point to number.
My concern here is that the caller, if it's not paying attention , can be fooled by thinking that is passing by value which actually, on the function frame , a reference will be created.
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
i think this should be somehow marked and enforced by syntax. Like in C# where you have ref keyword.
What do you guys think ?
This is one of those things where references are less clear than pointers. However, using pointers may lead to something like this:
changeInt(NULL);
when they actually should have done:
changeInt(&number);
which is just as bad. If the function is as clearly named as this, it's hardly a mystery that it actually changes the value passed in.
Another solution is of course to do:
int calculateNewInt(/* may need some input */)
{
return 7;
}
now
int number = 3;
...
number = calculateNewInt();
is quite obviously (potentially) changing number.
But if the name of the function "sounds like it changes the input value", then it's definitely fair to change the value. If in doubt, read the documentatin. If you write code that has local variables that you don't want to alter, make them const.
const int number = 3;
changeInt(number); /* Makes an error */
(Of course, that means the number is not changeable elsewhere either).
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
I think that's perfectly normal and part of the language. Actually, this is one of the bad things of C and C++: you have to check the headers all the time when dealing with an unknown API, since when calling a function you don't pass by reference explicitly.
That's not the case for all system languages though. IIRC Rust makes it obligatory to pass references explicitly.
Reference to the Stackoverflow question title "variable length arrays in C++" we know that following is valid
void foo(int n) {
int values[n]; //Declare a variable length array
}
I have read that there exists a small run time penalty(in variable length arrays) here. Can somebody nicely explain what that is in this context?
I would also try my level best to locate the link where I read it.I apologize i could not mention it here.
IIRC, with GCC, functions with VLA's:
Will not be inlined
Need to use an extra register for the frame pointer (that is, -fomit-frame-pointer works on non-VLA functions), so there is one less register available for the other work the function needs to do.
I was looking over some example functions and methods (I'm currently in a C++ class), and I noticed that there were a few functions that, rather than being void, they were something like
int myFunction() {
// ...;
return 0;
}
Where the ellipses is obviously some other statement. Why are they returning zero? What's the point of returning a specific value every time you run a function?
I understand that main() has to be int (at least according to the standards) because it is related (or is?) the exit code and thus works with the operating system. However, I can't think of a reason a non-main function would do this.
Is there any particular reason why someone might want to do this, as opposed to simply making a void function?
If that's really what they're doing, returning 0 regardless of what the function does, then it's entirely pointless and they shouldn't be doing it.
In the C world, an int return type is a convention so that you can return your own "error code", but not only is this not idiomatic C++ but if, again, your programmer is always returning 0, then it's entirely silly.
Specifically:
I understand that main() has to be int (at least according to the standards) because it is related (or is?) the exit code and thus works with the operating system. However, I can't think of a reason a non-main function would do this.
I agree.
There's a common convention of int functions returning 0 for success and some non-zero error code for failure.
An int function that always returns 0 might as well be a void function if viewed in isolation. But depending on the context, there might be good reasons to make it compatible with other functions that returning meaningful results. It could mean that the function's return type won't have to be changed if it's later modified so it detects errors -- or it might be necessary for its declaration to be compatible with other int-returning functions, if it's used as a callback or template argument.
I suggest examining other similar functions in the library or program.
It's a convention, particularly among C programmers, to return 0 if the function did not experience any errors and return a nonzero value if there was an error.
This has carried over into C++, and although it's less common and less of a convention due to exception handling and other more object-oriented-friendly ways of handling errors, it does come up often enough.
One more issue that was not touched by other answers. Within the ellipses may be another return statement:
int myFunction() {
// ...;
if (error)
return code;
// ...;
return 0;
}
in which case myFunction is not always returning 0, but rather only when no error has occurred. Such return statements are often preferred over more structured but more verbose if/else code blocks, and may often be disguised within long, sloppy code.
Most of the time function like this should be returning void.
Another possibility is that this function is one of a series of closed-related functions that have the same signature. The return int value may signal the status, say returning 0 for success, and a few of these functions always succeed. To change the signature may break the consistency, or would make the function unusable as function objects since the signature does not match.
Is there any particular reason why someone might want to do this, as opposed to simply making a void function?
Why does your mother cut the ends off the roast before putting it in the oven? Answer: Because that's what her grandmother did. However, her grandmother did that for a simple reason: Her roast pan wasn't big enough to hold a full-sized roast.
I work with a simulation tool that in its earliest incarnations required that all functions callable by the simulation engine must return a success status: 0=success, non-zero=failure. Functions that could never fail were coded to always returned zero. The simulation engine has been able to accommodate functions that return void for a long, long, time. That returning an integer success code was the required behavior from some previous millennium hasn't stopped cargo cult programmers from carrying this behavior of writing functions that always returning zero forward to the current day.
In certain programming languages you find procedures and functions. In C, C++ and similar languages you don't. Rather you only have functions.
In practice, a procedure is a part of a program that performs a certain task. A function on the other hand is like a procedure but the function can return an answer back.
Since C++ has only functions, how would you create a procedure? That's when you would either create a void function or return any value you like to show that the task is complete. It doesn't have to be 0. You can even return a character if you like to.
Take for example, the cout statement. It just outputs something but not return anything. This works like a procedure.
Now consider a math function like tan(x). It is meant to use x and return an answer back to the program that called it. In this case, you cannot return just anything. You must return the value of the TAN operation.
So if you need to write your own functions, you must return a value based on what you're doing. If there's nothing to return, you may just write a void function or return a dummy value like 0 or anything else.
In practice though, it's common to find functions returning 0 to indicate that 'all went off well' but this is not necessarily a rule.
here's an example of a function I would write, which returns a value:
float Area ( int radius)
{
float Answer = 3.14159 * radius * radius;
return Answer;
}
This takes the radius as a parameter and returns the calculated answer (area). In this case you cannot just say return 0.
I hope this is clear.
I came across the following weird chunk of code.Imagine you have the following typedef:
typedef int (*MyFunctionPointer)(int param_1, int param_2);
And then , in a function , we are trying to run a function from a DLL in the following way:
LPCWSTR DllFileName; //Path to the dll stored here
LPCSTR _FunctionName; // (mangled) name of the function I want to test
MyFunctionPointer functionPointer;
HINSTANCE hInstLibrary = LoadLibrary( DllFileName );
FARPROC functionAddress = GetProcAddress( hInstLibrary, _FunctionName );
functionPointer = (MyFunctionPointer) functionAddress;
//The values are arbitrary
int a = 5;
int b = 10;
int result = 0;
result = functionPointer( a, b ); //Possible error?
The problem is, that there isn't any way of knowing if the functon whose address we got with LoadLibrary takes two integer arguments.The dll name is provided by the user at runtime, then the names of the exported functions are listed and the user selects the one to test ( again, at runtime :S:S ).
So, by doing the function call in the last line, aren't we opening the door to possible stack corruption? I know that this compiles, but what sort of run-time error is going to occur in the case that we are passing wrong arguments to the function we are pointing to?
There are three errors I can think of if the expected and used number or type of parameters and calling convention differ:
if the calling convention is different, wrong parameter values will be read
if the function actually expects more parameters than given, random values will be used as parameters (I'll let you imagine the consequences if pointers are involved)
in any case, the return address will be complete garbage, so random code with random data will be run as soon as the function returns.
In two words: Undefined behavior
I'm afraid there is no way to know - the programmer is required to know the prototype beforehand when getting the function pointer and using it.
If you don't know the prototype beforehand then I guess you need to implement some sort of protocol with the DLL where you can enumerate any function names and their parameters by calling known functions in the DLL. Of course, the DLL needs to be written to comply with this protocol.
If it's a __stdcall function and they've left the name mangling intact (both big ifs, but certainly possible nonetheless) the name will have #nn at the end, where nn is a number. That number is the number of bytes the function expects as arguments, and will clear off the stack before it returns.
So, if it's a major concern, you can look at the raw name of the function and check that the amount of data you're putting onto the stack matches the amount of data it's going to clear off the stack.
Note that this is still only a protection against Murphy, not Machiavelli. When you're creating a DLL, you can use an export file to change the names of functions. This is frequently used to strip off the name mangling -- but I'm pretty sure it would also let you rename a function from xxx#12 to xxx#16 (or whatever) to mislead the reader about the parameters it expects.
Edit: (primarily in reply to msalters's comment): it's true that you can't apply __stdcall to something like a member function, but you can certainly use it on things like global functions, whether they're written in C or C++.
For things like member functions, the exported name of the function will be mangled. In that case, you can use UndecorateSymbolName to get its full signature. Using that is somewhat nontrivial, but not outrageously complex either.
I do not think so, it is a good question, the only provision is that you MUST know what the parameters are for the function pointer to work, if you don't and blindly stuff the parameters and call it, it will crash or jump off into the woods never to be seen again... It is up to the programmer to convey the message on what the function expects and the type of parameters, luckily you could disassemble it and find out from looking at the stack pointer and expected address by way of the 'stack pointer' (sp) to find out the type of parameters.
Using PE Explorer for instance, you can find out what functions are used and examine the disassembly dump...
Hope this helps,
Best regards,
Tom.
It will either crash in the DLL code (since it got passed corrupt data), or: I think Visual C++ adds code in debug builds to detect this type of problem. It will say something like: "The value of ESP was not saved across a function call", and will point to code near the call. It helps but isn't totally robust - I don't think it'll stop you passing in the wrong but same-sized argument (eg. int instead of a char* parameter on x86). As other answers say, you just have to know, really.
There is no general answer. The Standard mandates that certain exceptions be thrown in certain circumstances, but aside from that describes how a conforming program will be executed, and sometimes says that certain violations must result in a diagnostic. (There may be something more specific here or there, but I certainly don't remember one.)
What the code is doing there isn't according to the Standard, and since there is a cast the compiler is entitled to go ahead and do whatever stupid thing the programmer wants without complaint. This would therefore be an implementation issue.
You could check your implementation documentation, but it's probably not there either. You could experiment, or study how function calls are done on your implementation.
Unfortunately, the answer is very likely to be that it'll screw something up without being immediately obvious.
Generally if you are calling LoadLibrary and GetProcByAddrees you have documentation that tells you the prototype. Even more commonly like with all of the windows.dll you are provided a header file. While this will cause an error if wrong its usually very easy to observe and not the kind of error that will sneak into production.
Most C/C++ compilers have the caller set up the stack before the call, and readjust the stack pointer afterwards. If the called function does not use pointer or reference arguments, there will be no memory corruption, although the results will be worthless. And as rerun says, pointer/reference mistakes almost always show up with a modicum of testing.