Strange Commands in C++ ???

Started by
9 comments, last by SelethD 19 years, 3 months ago
I have been trying to learn some things about how to program a mud and I have been going through lots of other peoples source code. I have ran across some commands that are totally foreign to me, and I cant seem to find anything that really can help me understand them. I am programming in C++ under Windows Here are the commands I dont understand what the 'register' command means here for( register int i = 0; i < nMax ; i++ ) I dont understand what the 'assert' command means here short nMax = bOnlyOne ? 1 : GetMax(); assert(nMax); I dont understand what the 'try' and 'catch' commands mean try { printf("do somthing"); { catch (...) { printf("do somthing"); } I think thats all of the odd ones I have found. I hope someone with more experience than I might know how to explain some of these to me. Thanks
Advertisement
'register' tells the compiler to try to store that variable in a register instead of memory, since registers are faster. This is only a suggestion to the compiler and it won't necessarily be done. Also, a good compiler will usually optimize something like a loop counter into a register anyway, so in my opinion, it is just a waste of typing. :)

An assert normally only gets executed in a debug build and causes an exception to occur. In the example you gave, an error would occur if nMax was zero. Some people fill their code with asserts to check for things like NULL pointers. Once again, you'd probably be better off doing an actual check, since asserts are normally compiled out in release builds.
The register keyword is a suggestion to the compiler that the variable should be put into a register and not on the stack; it's an optimization hint. Modern optimizing compilers pretty much ignore the register keyword, except to check for syntax.

assert() is a macro defined in the <cassert> header that stops program execution in debug mode if the expression you pass to assert() is false. Basically you're saying that whatever is inside the assert() had better be true, otherwise something hit the fan. In release mode, assert()s are no-ops.

A try/catch construct is used for exception handling. First the program executes the stuff after try. If an exception is thrown, then if you handle that kind of exception, program execution transfers to the appropriate catch block. catch (...) tells the compiler that the catch block handles all exceptions. For more detail you should really consult a C++ reference. It would be difficult to describe the minutia of exception handling in a forum post.
MSVC completely ignores the register command, since the compiler knows best as to what should and shouldn't be put into the register.
_________________Politics is the ability to foretell what is going to happen tomorrow, next week, next month and next year. And to have the ability afterwards to explain why it didn't happen. -- Winston ChurchillGDNet-0.2 - rate users the easy way with this nifty Firefox extension. Updated with new features.
the 'register' keyword I believe just stores the variable in the CPU registers and increases speed of operations on that variable. I don't see it used too often but it is useful in loops.

I'm not sure quite sure about assert(). I have never used it.

the 'try', 'throw' and 'catch' keywords are used in exception handling. You may want to find a tutorial on this but basically it works like this.

try
{
//code here
if(error)
throw "an error occurred";
}
catch(char* error) //catches a value thrown
{
std::cout << error;
}

you can throw different types too. I just used char* as an example.
Wow!

That totally answers all my questions, and fast too!

You guys are great, Thanks!
One more odd command I found that boggles me.


I dont understand the '#pragma hdrstop' what is it used for?

#include "stdinclude.h"
#pragma hdrstop

#define COMMENT_CHARACTER '*'
#define NO_ENTRY_CHARACTER '#'

Thanks again.
#pragma commands are special compiler-specific commands. The standard doesn't specify what the compiler does with them. It depends on an individual compiler as to what pragma commands are available and what they all do. As for what yours might actually do, I have no idea.
My stuff.Shameless promotion: FreePop: The GPL god-sim.
In some compilers (I believe including VC6 and later) the register keyword has one other side-effect (which it should, according to some edition or other of the standard): you cannot take the address (& operator) of a register variable. This is very rarely useful, but it should be kept in mind - register is not a total no-op in all cases. However, this is only an ANSI C behavior and (AFAIK) does not occur in C++.

If you're not confused enough yet, here's MSDN's two cents.

As noted in that article, for optimizing compilers register is wasted unless compiling ANSI C, in which case the address-of restriction applies. In general, if a variable ever has its address taken, either explicitly or implicitly, it will not be kept in a register. To make things even more confusing, a pointer can itself be kept in a register, but not the data it points to.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

#pragma hdrstop

is a command telling the compiler to stop building the precompiled header ... and if you don't know what that is, it is almost completely unimportant.

But just so you believe me that it is unimportant (at least except for the cases where something is configured wrong and it causes an error) I'm going to tell you the basics of what it is.

when you compile multiple files, like:

Main.cpp
GraphicsEngine.cpp
GameLogic.cpp
Timer.cpp
...

each and every .cpp files is compiled seperatly from each other (it's like the compiler is reset between each compile, and the compiling of 1 does not affect the other at all) - each source file generates an output object file (usually .obj on windows), then after all files in a project compile succesfully (assuming there are no errors), the linker comes along and combines them together into a library or executable file (.lib, .dll, .com or .exe on windows).

Well when a source file #includes another file, like:

#include <fstream>
#include <cstdlib>
#include <gl/glut.h>
#include "Utilities.h"

each of those other files are injected into the current files ... (it looks to the compiler just like the lines inside the included file where actually typed at the point at which the insertion happens).

so when you type this inside a file called 'MyClass.cpp'

#include "MyClass.h"

it is putting all the code inside MyClass.h inside the file MyClass.cpp, before it compiles MyClass.cpp.

Now the thing is, some header files get included into most or all of the source files of your project. Files like <vector>, <iostream>, "Utils.h", <windows.h>, <gl/glut.h>, are just a few possible examples of files you might include A WHOLE LOT.

Now this would normally make the compiler load, copy, parse, and compile that code once for every time the file is #included ... which can be a LOT of compiling ...

so someone invented this concept called a precompiled header, which is simply a thing that the compiler partially/mostly compiles and stores, for repeated use.

So if every cpp in your project started with these lines:
#include <gl/glut.h>
#include <cstdlib>
#include <fstream>
#include "Utilities.h"

in that exact same order, before anything else ... a compiler which supports precompiled headers could load all four of those files into a block, compile it, and just reload that same block when starting each new cpp file ...

but the problem is, this only works if 1) the files use the SAME list of #incldue files, and in the same ORDER ... and 2) the compiler is smart enough to notice (or be told) which files are shared amoung the files of your app.

In general there are 3 ways a compiler can do this, it can have a specified set of precompiled files to use, it can have a specified file to look at for guidance, or it can just assume that the first file it compiles is representative of most files in the project ... which is where your #pragma comes in ...

if you did this in one file:

#include "FileA.h"
#include "FileB.h"
#include "FileC.h"

And the compiler puts A, B, and C in the precompiled header

and then in another file did this:

#include "FileA.h"
#include "FileB.h"

the compiler cannot use the precompiled header at all ... because the second file doesn't use C ... so it doesn't match ...

but if you did this:

#include "FileA.h"
#include "FileB.h"
#pragma hdrstop
#include "FileC.h"

then it knows (cause you told it) to only but FileA and FileB in the header ...

and therefore all files which start with A then B (no matter if they use C or not) will get the benifit of using the precompiled header for parts A and B.

This topic is closed to new replies.

Advertisement