Checking for null pointer for structure

G

GrzybSon

Hello,

I have got two nested structures:

struct TopStruct
{
char * ggg;
union
{
NestedStruct nested;
} param;
};

struct NestedStruct
{
InnerStruct inner;
};

struct InnerStruct
{
char * txt;
}

How to check if field nested of type NestedStruct is not null?

Some code given:

TopStruct * top;

while ( (top = GetStructs()) != NULL)
{
// ...
if (top->nested != NULL) // this gives me compiler error c2678 binary
'!=' : no operator found which takes a left hand operand of type
{
// do something
}
}

What is wrong?
 
A

Alf P. Steinbach

* GrzybSon:
Hello,

I have got two nested structures:

struct TopStruct
{
char * ggg;
union
{
NestedStruct nested;
} param;
};

struct NestedStruct
{
InnerStruct inner;
};

struct InnerStruct
{
char * txt;
}

How to check if field nested of type NestedStruct is not null?

Some code given:

TopStruct * top;

while ( (top = GetStructs()) != NULL)
{
// ...
if (top->nested != NULL) // this gives me compiler error c2678 binary
'!=' : no operator found which takes a left hand operand of type
{
// do something
}
}

What is wrong?

The design. Sorry, that's brutal, and even though I'm pretty old I've not yet
learned how to say such things in some acceptable way. So I just go for the
straightforward, hoping people will forgive me since the info is good, yes?

Okay, others will probably comment on your char*'s, recommending instead
std::string, but let's look at the design.

As I understand it you want TopStruct to have an optional NestedStruct.

Some TopStruct-s will have a NestedStruct, some will not.

The question is, will any given TopStruct ever /acquire/ or /lose/ a
NestedStruct, or is a TopStruct created with/without a NestedStruct and staying
that way for its lifetime?

If it stays that way for its lifetime, then a natural solution is to use
inheritance.

It then goes like this:

struct TopStruct
{
virtual ~TopStruct() {} // You need /some/ virtual method.
std::string ggg;
};

struct WithNestedStruct: TopStruct // Inheritance
{
std::string text;
};

...

while( (top = GetStructs()) != 0 )
{
if( WithNestedStruct* p = dynamic_cast<WithNestedStruct*>( top ) )
{
// Do things with p
}
}


There are more advanced techniques to avoid the 'if' or 'case', that is, to
avoid explicit type discrimantion, and generally those techniques are based on
using virtual methods. In short, you let the effect of a call to method depend
on the object at hand. But perhaps first try if you can get the above to work,
assuming of course that the assumption of TopStruct-s staying the way they're
created, holds.

If that assumption does not hold, then use a pointer in TopStruct, and then take
care not to copy those structs, or if you do, decide on what to do with pointer.


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* GrzybSon:

The design. Sorry, that's brutal, and even though I'm pretty old I've
not yet learned how to say such things in some acceptable way. So I just
go for the straightforward, hoping people will forgive me since the info
is good, yes?

Forgot to add, the direct cause of the compilation error is that the code
compares a non-pointer, namely a NestedStruct, to zero.

C++ provides enough magic to make that work, i.e. NestedStruct could /define/ a
meaning for comparision with zero, in various ways.

But that's advanced and not relevant here.

Okay, others will probably comment on your char*'s, recommending instead
std::string, but let's look at the design.

As I understand it you want TopStruct to have an optional NestedStruct.

Some TopStruct-s will have a NestedStruct, some will not.

The question is, will any given TopStruct ever /acquire/ or /lose/ a
NestedStruct, or is a TopStruct created with/without a NestedStruct and
staying that way for its lifetime?

If it stays that way for its lifetime, then a natural solution is to use
inheritance.

It then goes like this:

struct TopStruct
{
virtual ~TopStruct() {} // You need /some/ virtual method.
std::string ggg;
};

struct WithNestedStruct: TopStruct // Inheritance
{
std::string text;
};

...

while( (top = GetStructs()) != 0 )
{
if( WithNestedStruct* p = dynamic_cast<WithNestedStruct*>( top ) )
{
// Do things with p
}
}


There are more advanced techniques to avoid the 'if' or 'case', that is,
to avoid explicit type discrimantion, and generally those techniques are
based on using virtual methods. In short, you let the effect of a call
to method depend on the object at hand. But perhaps first try if you can
get the above to work, assuming of course that the assumption of
TopStruct-s staying the way they're created, holds.

If that assumption does not hold, then use a pointer in TopStruct, and
then take care not to copy those structs, or if you do, decide on what
to do with pointer.

Cheers,

- Alf
 
G

GrzybSon

The design. Sorry, that's brutal, and even though I'm pretty old I've not
yet learned how to say such things in some acceptable way. So I just go
for the straightforward, hoping people will forgive me since the info is
good, yes?

Ok, i'll explain some things.
i'm not c++ developer, but C#.
I'm writing managed wrapper (in VC++ 2005 for OpenH323 library which i have
in DLL form).
Also i have header file (opal.h) which contains many structures in unmanaged
C++.
I' ve created managed structures for every unmanaged structure from header
file.
Now i want to make a conversion from unmanaged struct -> managed struct and
back.

So this is why i have to check for null values i unmanaged structures: to
instantiate equivalent managed structure (or not if null value is present).
 
N

Nick Keighley

* GrzybSon:















The design. Sorry, that's brutal, and even though I'm pretty old I've not yet
learned how to say such things in some acceptable way. So I just go for the
straightforward, hoping people will forgive me since the info is good, yes?

Okay, others will probably comment on your char*'s, recommending instead
std::string, but let's look at the design.

As I understand it you want TopStruct to have an optional NestedStruct.

Some TopStruct-s will have a NestedStruct, some will not.

The question is, will any given TopStruct ever /acquire/ or /lose/ a
NestedStruct, or is a TopStruct created with/without a NestedStruct and staying
that way for its lifetime?

If it stays that way for its lifetime, then a natural solution is to use
inheritance.

It then goes like this:

   struct TopStruct
   {
       virtual ~TopStruct() {}       // You need /some/ virtual method.
       std::string ggg;
   };

   struct WithNestedStruct: TopStruct    // Inheritance
   {
       std::string text;
   };

   ...

   while( (top = GetStructs()) != 0 )
   {
       if( WithNestedStruct* p = dynamic_cast<WithNestedStruct*>( top ) )
       {
           // Do things with p
       }
   }

There are more advanced techniques to avoid the 'if' or 'case', that is, to
avoid explicit type discrimantion, and generally those techniques are based on
using virtual methods. In short, you let the effect of a call to method depend
on the object at hand. But perhaps first try if you can get the above to work,
assuming of course that the assumption of TopStruct-s staying the way they're
created, holds.

If that assumption does not hold, then use a pointer in TopStruct, and then take
care not to copy those structs, or if you do, decide on what to do with pointer.

looks rather heavy machinary for a simple job...
inheritance for a simple optional sub-field?

but then we don't know why this nested structure is sometimes here
sometimes not.
 
N

Nick Keighley

Ok, i'll explain some things.
i'm not c++ developer, but C#.
I'm writing managed wrapper (in VC++ 2005 for OpenH323 library which i have
in DLL form).
Also i have header file (opal.h) which contains many structures in unmanaged
C++.
I' ve created managed structures for every unmanaged structure from header
file.
Now i want to make a conversion from unmanaged struct -> managed struct and
back.

So this is why i have to check for null values i unmanaged structures: to
instantiate equivalent managed structure (or not if null value is present).

but the way you have coded it the nested structure can never be null.
You may want to ask on a .Net group or something for all this managed/
unmanaged stuff
 
G

GrzybSon

Uzytkownik "Nick Keighley" <[email protected]> napisal w
wiadomosci
this is odd. A union is usually used to allow two or more disimilar
types to share the same memory. Your union only has one type in it. I
also have a nasty feeking your union is inaccessible outside your
struct. (I don't use unions so I'd have to go and check a reference).

This is only sample code, but real struct has many nested structs in union.
it can't be null. nested isn't a pointer but a nested sub-structure
(union in this case).


I'm surprised it didn't complain about the arrow operator.



its borhken

I've no idea how to fix it as you gave no idea what you were really
trying to do. Anbd the names you choose were without semantic content.

Is this any help?

struct InnerStruct
{
char * txt;
}

struct NestedStruct
{
InnerStruct inner;
};

struct TopStruct
{
char * ggg;
NestedStruct * nested; /* <-- pointer */
};

struct InnerStruct
{
char * txt;
}

TopStruct * top;

while ((top = GetStructs()) != NULL)
{
if (top->nested != NULL)
{
// do something
}
}



untested, uncompiled

Ok, i've figured this out:

while ((top = GetStructs()) != NULL)
{
if (&top->nested != NULL)
{
// do something
}
}
 
A

Alf P. Steinbach

* Nick Keighley:
looks rather heavy machinary for a simple job...
inheritance for a simple optional sub-field?

Even for a simple optional sub-field it's less to write both for definitions and
usage, and it's more safe, than an embedded pointer.

So it's not exactly heavy machinery; at the source code level it's rather the
opposite, the simplest solution, if the assumptions on which it's based hold.

And on top of that, that even for the simplest case it's simplest, I think one
can be sure that the OP's case is not a simple optional sub-field, and also that
the OP will benefit from learning some OO techniques, using C++ as C++ instead
of as C -- much of the point of C++ is that it has safe & simple direct
language support for many of the patterns that are re-implemented time and time
again in C, so, let the language do its job...


but then we don't know why this nested structure is sometimes here
sometimes not.

Cheers,

- Alf
 
G

Gert-Jan de Vos

Uzytkownik "Nick Keighley" <[email protected]> napisal w
wiadomosci




This is only sample code, but real struct has many nested structs in union.


















Ok, i've figured this out:

while ((top = GetStructs()) != NULL)
 {
    if (&top->nested != NULL)
{
            // do something
    }
 }

This will compile but it is meaningless. It checks that the
address of top->nested is non-NULL which is always true.
 
L

Leclerc

i'm not c++ developer, but C#.
I'm writing managed wrapper (in VC++ 2005 for OpenH323 library which i have
in DLL form).


I suppose taht you want to use some nonmanaged c++ library in c# code.

If that's correct, why don't you expose it's interface as a COM(+)
object, instead writing managed wrappers?
 
G

GrzybSon

Because i don't know why.

--
Pozdro,
Maæko
U¿ytkownik "Leclerc said:
I suppose taht you want to use some nonmanaged c++ library in c# code.

If that's correct, why don't you expose it's interface as a COM(+) object,
instead writing managed wrappers?
 
G

GrzybSon

Uzytkownik "Gert-Jan de Vos" <[email protected]> napisal w
wiadomosci
Uzytkownik "Nick Keighley" <[email protected]> napisal w
wiadomosci




This is only sample code, but real struct has many nested structs in
union.


















Ok, i've figured this out:

while ((top = GetStructs()) != NULL)
{
if (&top->nested != NULL)
{
// do something
}
}
This will compile but it is meaningless. It checks that the
address of top->nested is non-NULL which is always true.

Yes, you are right.
So what's the solution?
 
T

Thomas J. Gritzan

Am 17.02.2010 15:55, schrieb GrzybSon:
Yes, you are right.
So what's the solution?

That really depends on the underlying problem. You haven't specified
what you are trying to do.

Maybe you want to check which one of the inner structs in the union is
active?
 
G

Gert-Jan de Vos

Uzytkownik "Gert-Jan de Vos" <[email protected]> napisal w
wiadomosci




Yes, you are right.
So what's the solution?

Alf hinted at a possible solution. It's hard to give a detailed
solution with the little information we have about your goals. OK
we know you need a C# API for a C OpenH323 library. That's the
problem: we are neither C# experts, nor OpenH323 experts. You are
apparently not a C++ expert. You will need all three expertises
in your project to make it work.

Try to first design a C# API for your library. Then translate it
to C++/CLI classes. Then try to implement these with the C API.
 
T

tonydee

struct TopStruct
{
    char * ggg;
    union
    {
        NestedStruct nested;
    } param;
};
...
TopStruct * top;
...
    if (top->nested != NULL)  // this gives me compiler error c2678 binary
'!=' : no operator found which takes a left hand operand of type

As others have said, the code - overall - is a complete mess. That
said, the immediate problem is that you need to refer to top-
param.nested, not top->nested directly.

Cheers,
Tony
 
G

GrzybSon

Alf hinted at a possible solution. It's hard to give a detailed
solution with the little information we have about your goals. OK
we know you need a C# API for a C OpenH323 library. That's the
problem: we are neither C# experts, nor OpenH323 experts. You are
apparently not a C++ expert. You will need all three expertises
in your project to make it work.
Try to first design a C# API for your library. Then translate it
to C++/CLI classes. Then try to implement these with the C API.

OK. I'll tell you what i've done so far.
I've write managed equivalent of every non-managed C++ struct that comes
from header file opal.h.
Also i have created conversion between structs: managed -> unmanaged and
unmanaged -> managed.

This conversion is required if i want to use openH323 DLL in .NET project.
That's why i needed to check null values of nested structs in umanaged C++
(.NET threats different nested structs).
The answer of my question is a part of algorithm that makes conversion
between managed and unmanaged C++ classes/structs.

I've found solution to my question so now I can use this wrapper in any .NET
project.
 
G

GrzybSon

Uzytkownik "tonydee" <[email protected]> napisal w wiadomosci
struct TopStruct
{
char * ggg;
union
{
NestedStruct nested;
} param;
};
...
TopStruct * top;
...
if (top->nested != NULL) // this gives me compiler error c2678 binary
'!=' : no operator found which takes a left hand operand of type

As others have said, the code - overall - is a complete mess. That
said, the immediate problem is that you need to refer to top-
param.nested, not top->nested directly.

Yes, your right.
I haven't copy-pasted it from IDE so it has mistakes.

Cheers,
Tony
 
N

Noah Roberts

As I understand it you want TopStruct to have an optional NestedStruct.

Some TopStruct-s will have a NestedStruct, some will not.

The question is, will any given TopStruct ever /acquire/ or /lose/ a
NestedStruct, or is a TopStruct created with/without a NestedStruct and staying
that way for its lifetime?

If it stays that way for its lifetime, then a natural solution is to use
inheritance.

I wouldn't agree. There are several things I see with this solution
that make me question it.

1 - Although the OP used "NestedStruct" as his name, he didn't actually
nest it. There's nothing here that tells us that there's no use for
"NestedStruct" outside of "TopStruct".

2 - We don't know that even if #1 is as we are assuming (only used
within the context of TopStruct) that it will continue to be so.

3 - TopStruct cannot be used as a value type except when it doesn't have
the "NestedStruct". It must always use pointer semantics.

The first and second problem are not inherent problems, at least not in
this very specific case (could be in other cases), but it does force all
clients of "NestedStruct" to also hold uninteresting information
inherited from "TopStruct".

The third issue may or may not come up, but there's no reason to force
pointer semantics on something that doesn't necessarily need it.

You may buy some pointer safety with this design but there's a better
option that will provide that same safety without the inheritance,
dynamic_cast, and will give the OP what we should always prefer over
inheritance: composition. That better method is boost::eek:ptional.

struct NestedStruct { std::string x; };
struct TopStruct
{
std::string ggg;
boost::eek:ptional<NestedStruct> nested;
};

while ( top = GetStructs() )
{
if (top->nested)
do_things_with_nested(*top->nested);
}

The boost::eek:ptional template will return false for its bool operator
when it hasn't been assigned a value. Of course, if the OP needs to
make sure that TopStruct either has/nothas a nested for its lifetime
they need to make it a private member and only provide an accessor.

The reason we prefer composition over inheritance includes the three
problems I stated above and can be read about in "C++ Coding Policies"
as I recall. If the OP is not allowed to use boost, the optional
template should be easy enough to replicate.

Of course, there could be other governing forces that would lead one to
chose your method instead of mine. I can't know for sure that they
don't apply in this case but, based on the OP's code, I'm tending to
assume they do not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top