Quick question: C++ compare to null?

Carlis

Senior member
May 19, 2006
237
0
76
Hi.
I left my c++ book in school. I have a question about comparing to null in c++.

If I have a class called Vcore that is allocated to a variable next;

VCore *next;

Now, I want to be able to know whether the variable next is initiated. In java you would do

if(next==null){
do stuff...
}
else{
...
}

What do you do in c++?
 

Scooby Doo

Golden Member
Sep 1, 2006
1,034
18
81
Originally posted by: Carlis
Hi.
I left my c++ book in school. I have a question about comparing to null in c++.

If I have a class called Vcore that is allocated to a variable next;

VCore *next;

Now, I want to be able to know whether the variable next is initiated. In java you would do

if(next==null){
do stuff...
}
else{
...
}

What do you do in c++?

Pretty much exactly the same as what you've got, with probably one minor difference, personally I would assign null to next when it's created. (Not sure if this is needed anymore with the newer C++)???

VCore *next = NULL ;

...

if(next==NULL)
{
do stuff...
}
else
{
...
}
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
in C++ it's just all caps i.e. "NULL"
you could compare to 0, but really you should use the macro NULL
 

engineereeyore

Platinum Member
Jul 23, 2005
2,070
0
0
Just FYI, instantiating a variable VCore *next doesn't actually initialize anything. All you've done is create a pointer. It doesn't allocate any memory for the actual class itself. I think what you actually need is this:

VCore *next;
next = new VCore;
if (next == NULL)
{
...
}
else
{
....
}

Just declaring a pointer doesn't tell you anything about whether anything was initialized. The pointer is also not likely to be NULL, but rather contain some arbitrary value. You need to allocate the class by setting the pointer with the next = new VCore call. Just don't forget to deallocate the memory when you're done using it. C++ doesn't have a garbage collector, that I know of, like Java does.

Sorry if I misunderstood what you're looking for, but I just wanted to make sure you understood this.
 

Cogman

Lifer
Sep 19, 2000
10,284
138
106
Originally posted by: IHateMyJob2004
Originally posted by: dighn
in C++ it's just all caps i.e. "NULL"
you could compare to 0, but really you should use the macro NULL

:thumbsup:

Ok, here is a dumb question I'm sure. Why do we have to use the NULL macro? Is null going to be defined as some other number other then 0 in the near future? Or is it just one of those "It is somehow easier to understand" sorts of things?
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
Originally posted by: engineereeyore
Just FYI, instantiating a variable VCore *next doesn't actually initialize anything. All you've done is create a pointer. It doesn't allocate any memory for the actual class itself. I think what you actually need is this:

VCore *next;
next = new VCore;
if (next == NULL)
{
...
}
else
{
....
}

Just declaring a pointer doesn't tell you anything about whether anything was initialized. The pointer is also not likely to be NULL, but rather contain some arbitrary value. You need to allocate the class by setting the pointer with the next = new VCore call. Just don't forget to deallocate the memory when you're done using it. C++ doesn't have a garbage collector, that I know of, like Java does.

Sorry if I misunderstood what you're looking for, but I just wanted to make sure you understood this.


On my machine (Windows 7 using Code::Blocks w/ mingw) when I call for example Heap<int> *test; and print out test, I get an address of 0x4f, which obviously isn't NULL/0, so comparisons to them don't work.

Is C++ just not designed to be used in this manor?
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
Originally posted by: Cogman
Originally posted by: IHateMyJob2004
Originally posted by: dighn
in C++ it's just all caps i.e. "NULL"
you could compare to 0, but really you should use the macro NULL

:thumbsup:

Ok, here is a dumb question I'm sure. Why do we have to use the NULL macro? Is null going to be defined as some other number other then 0 in the near future? Or is it just one of those "It is somehow easier to understand" sorts of things?

You don't have to. It's just more "correct". All platforms that I've dealt with has NULL defined as 0, but the C++ standard doesn't specify that as far as I know. So theoretically it's possible for some implementation to define NULL otherwise. As a general rule I think it's better to not assume anything about the implementation unless you really have to.
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
Originally posted by: ObscureCaucasian
Originally posted by: engineereeyore
Just FYI, instantiating a variable VCore *next doesn't actually initialize anything. All you've done is create a pointer. It doesn't allocate any memory for the actual class itself. I think what you actually need is this:

VCore *next;
next = new VCore;
if (next == NULL)
{
...
}
else
{
....
}

Just declaring a pointer doesn't tell you anything about whether anything was initialized. The pointer is also not likely to be NULL, but rather contain some arbitrary value. You need to allocate the class by setting the pointer with the next = new VCore call. Just don't forget to deallocate the memory when you're done using it. C++ doesn't have a garbage collector, that I know of, like Java does.

Sorry if I misunderstood what you're looking for, but I just wanted to make sure you understood this.


On my machine (Windows 7 using Code::Blocks w/ mingw) when I call for example Heap<int> *test; and print out test, I get an address of 0x4f, which obviously isn't NULL/0, so comparisons to them don't work.

Is C++ just not designed to be used in this manor?

Did you initialize it? Uninitialized pointers are just that, uninitialized and could contain anything. They are known as "dangling pointers".

ALWAYS initialize your pointers or you WILL encounter bugs related to them at some point. e.g. Heap<int> *test = NULL;
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
Originally posted by: dighn

Did you initialize it? Uninitialized pointers are just that, uninitialized and could contain anything. They are known as "dangling pointers".

ALWAYS initialize your pointers or you WILL encounter bugs related to them at some point. e.g. Heap<int> *test = NULL;

Ah, I see. That's something I was never taught before, I'd just assumed an uninitialized pointer defaulted to 0x0.
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
Originally posted by: ObscureCaucasian
Originally posted by: dighn

Did you initialize it? Uninitialized pointers are just that, uninitialized and could contain anything. They are known as "dangling pointers".

ALWAYS initialize your pointers or you WILL encounter bugs related to them at some point. e.g. Heap<int> *test = NULL;

Ah, I see. That's something I was never taught before, I'd just assumed an uninitialized pointer defaulted to 0x0.

I think they are for globally declared ones, but to be sure just initialize them always :)
 

engineereeyore

Platinum Member
Jul 23, 2005
2,070
0
0
Originally posted by: ObscureCaucasian
Originally posted by: engineereeyore
Just FYI, instantiating a variable VCore *next doesn't actually initialize anything. All you've done is create a pointer. It doesn't allocate any memory for the actual class itself. I think what you actually need is this:

VCore *next;
next = new VCore;
if (next == NULL)
{
...
}
else
{
....
}

Just declaring a pointer doesn't tell you anything about whether anything was initialized. The pointer is also not likely to be NULL, but rather contain some arbitrary value. You need to allocate the class by setting the pointer with the next = new VCore call. Just don't forget to deallocate the memory when you're done using it. C++ doesn't have a garbage collector, that I know of, like Java does.

Sorry if I misunderstood what you're looking for, but I just wanted to make sure you understood this.


On my machine (Windows 7 using Code::Blocks w/ mingw) when I call for example Heap<int> *test; and print out test, I get an address of 0x4f, which obviously isn't NULL/0, so comparisons to them don't work.

Is C++ just not designed to be used in this manor?

The reason you are getting a value there is because that's the value that just happens to be residing in the memory area where the variable is stored, which is likely just some spot on the stack. dighn was correct in what he said. The statement VCore *next is merely allocating a pointer (32 or 64 bit value) to a structure, not the structure itself. Now, if you type

VCore next;

that allocates a structure of type VCore right at that location in memory. Here's a breakdown of the difference.

I'll start with your original declaration, VCore *next; Unless this is a global variable, it's simply going to be stored on the stack at some address, let's say 0xabcd. So the value at that memory location is what next will be equal to, in your case, 0x4f. This is a completely arbitrary value and could be anything. What C++ expects is that at some point in time you'll set the pointer equal to the address of an actual structure in memory, hopefully before attempting to use it. So by doing

next = new VCore;

what you're doing is allocating a memory area large enough to store a VCore structure/class and then setting the next variable (memory location 0xabcd) equal to the address that was allocated for the structure/class. If the memory allocated is located at 0xabababab, then the value at 0xabcd would be 0xabababab. So next is simply used to reference that location in memory, which is where the structure is actually located.

In the alternative (VCore next; // no asterik), it would store the structure/class actually at location 0xabcd, rather than storing it elsewhere in memory and then storing an address reference at that location.

As for the automatic zeroing of variables, anything that is global can be automatically initialized to zero via compiler directives (might be linker, but IIRC it's the compiler). Depending on the compiler you use, it might be be done by default of it might not. The best practice is to just set them equal to NULL or some other invalid value (INVALID_HANDLE_VALUE, INVALID_SOCKET, etc.) right when you instantiate them. That way, if you ever do make a mistake and forget to initialize them, you're NULL comparison will work and you won't inadvertently end up hacking your own system. :)

Hope that wasn't too confusing.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: Cogman
Ok, here is a dumb question I'm sure. Why do we have to use the NULL macro? Is null going to be defined as some other number other then 0 in the near future? Or is it just one of those "It is somehow easier to understand" sorts of things?

Off the top of my head:
1) It is more readable -- NULL means 'pointer'.
2) NULL could be defined as something else.
3) NULL is always the same size as a pointer.
4) NULL always has pointer alignment -- so if you're not on x86 and you reference a NULL pointer, you will get a SIGSEGV instead of a SIGBUS.

Originally posted by: JasonCoder
Don't most platforms support smart pointers in some fashion nowadays?

Sure. C++ has auto_ptr for instance: pointers for the pointer-challenged programmer.
http://www.cplusplus.com/reference/std/memory/auto_ptr/

Finally: w00t to engineereeyore for the explanation. One addition:
Variable initialization is done by some compilers automatically, and others let you suffer. Its like IE over-implementing HTML -- its actually a very very bad thing and leads to very very bad habits. Always initialize every variable you ever declare. Use valgrind constantly until your brain hurts.
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
Originally posted by: engineereeyore

what you're doing is allocating a memory area large enough to store a VCore structure/class and then setting the next variable (memory location 0xabcd) equal to the address that was allocated for the structure/class. If the memory allocated is located at 0xabababab, then the value at 0xabcd would be 0xabababab. So next is simply used to reference that location in memory, which is where the structure is actually located.

Just to clarify, the value where 0xabcd used to be stored will be 0xabababab, but 0xabababab won't be stored in the address 0xabcd correct?

Here's what I interpret what you are trying to get across:

VCore *next;

// This means next = 0xa
// This means &next = 0xb

Now call:
next = new VCore;

// Now next = 0xc <==== the address where the new VCore was created
// Now &next = 0xb <==== the address where the next pointer is stored
 

engineereeyore

Platinum Member
Jul 23, 2005
2,070
0
0
Originally posted by: ObscureCaucasian
Originally posted by: engineereeyore

what you're doing is allocating a memory area large enough to store a VCore structure/class and then setting the next variable (memory location 0xabcd) equal to the address that was allocated for the structure/class. If the memory allocated is located at 0xabababab, then the value at 0xabcd would be 0xabababab. So next is simply used to reference that location in memory, which is where the structure is actually located.

Just to clarify, the value where 0xabcd used to be stored will be 0xabababab, but 0xabababab won't be stored in the address 0xabcd correct?

The value at 0xabcd would always represent the value of next. I'm just picking some arbitrary memory location as the location of the variable next. So from that point on, any time you reference the variable next, it's going to look at memory address 0xabcd for the value of next.

After you perform "next = new VCore", the CPU is going to allocate a block of memory to store an instance of the VCore class, in this example at memory location 0xabababab. So the value at 0xabcd will be 0xabababab.

Anytime you reference some element of the class, for instance next->variable1, what the computer is going to do is say, "Ok, the next variable is at address 0xabcd. Since next is a pointer, what is contained at 0xabcd isn't the instance of the class, but the memory location where the class was allocated. So I'm going to look at the address stored at 0xabcd, which is 0xabababab, for the variable I'm looking for."

If variable1 is the first element of the class, then the computer will look at address 0xabababab + 0 (the offset of variable1 in the class structure) for the value of variable1.

If this still doesn't make sense, or even if it does, here's a good explanation to look at as well: Pointer explanation.

Here's what I interpret what you are trying to get across:

VCore *next;

// This means next = 0xa
// This means &next = 0xb

Now call:
next = new VCore;

// Now next = 0xc <==== the address where the new VCore was created
// Now &next = 0xb <==== the address where the next pointer is stored

Yep, that looks correct. Just remember that originally, where you have "next = 0xa", next could actually be any arbitrary value. But you are correct, the address where next is store should always be 0xb, but the value of next will change when you assign it to the result of "new VCore".

Looks like you got it though! Pointers, and how they work, are one of the biggest stumbling blocks for almost all C and C++ programmers, so don't feel bad.
 

chronodekar

Senior member
Nov 2, 2008
721
1
0
Originally posted by: engineereeyore
Pointers, and how they work, are one of the biggest stumbling blocks for almost all C and C++ programmers

I'll say !!

I hated pointers back when they taught it to me in school. Somehow I managed to worm my way through (as class topper) without using them. ;) My teacher back then, never gave me a satisfactory explanation of why they exist at all.

Then 3 years later, I decided to try out linux kernel programming. ... Long story short, I learned the value of pointers by jumping of a cliff and learning to swim. :)
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Originally posted by: ObscureCaucasian
I think you can do:

if (!next)
{}

My understanding is that this is somewhat dangerous, because the value of NULL need not be 0. Also it makes more sense from a typing point of view... NULL is a pointer; 0 (or any number) is not.

So for maximally portable code, I'd compare (next == NULL) and let the compiler handle it.

-Eric

edit: oops fail, I didn't realize how many replies there'd been already. Looks like degibson gave a much more articulate/detailed response, lol.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
if(!next) is very C-esque. An explicit NULL comparison is better, even more so with NULL on the left.
 

Templeton

Senior member
Oct 9, 1999
467
0
0
Originally posted by: eLiu
Originally posted by: ObscureCaucasian
I think you can do:

if (!next)
{}

My understanding is that this is somewhat dangerous, because the value of NULL need not be 0. Also it makes more sense from a typing point of view... NULL is a pointer; 0 (or any number) is not.

So for maximally portable code, I'd compare (next == NULL) and let the compiler handle it.

-Eric

edit: oops fail, I didn't realize how many replies there'd been already. Looks like degibson gave a much more articulate/detailed response, lol.

In c++, Null is defined to be 0, there is no difference. See Stroustrup
 

Templeton

Senior member
Oct 9, 1999
467
0
0
Originally posted by: degibson

Sure. C++ has auto_ptr for instance: pointers for the pointer-challenged programmer.
http://www.cplusplus.com/reference/std/memory/auto_ptr/

It is near impossible to write exception safe code in c++ without RAII, smart pointers of some type are required to keep from leaking in the face of exceptions without resorting to try/catch at every level. C++0x/tr1 includes support for additional smart pointers based largely on those found in boost.