Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning struct from a function, how can I check that it is initialized?

Tags:

c++

null

I have the following struct in C++:

struct routing_entry {
        unsigned long destSeq;  // 32 bits
        unsigned long nextHop   // 32 bits
        unsigned char hopCount; // 8 bits
}; 

And I have the following function:

routing_entry Cnode_router_aodv::consultTable(unsigned int destinationID ) {    
    routing_entry route;

    if ( routing_table.find(destinationID) != routing_table.end() )
        route = routing_table[destinationID];

    return route; // will be "empty" if not found
}

"routing_table" is a stl::map defined as follows:

map< unsigned long int, routing_entry > routing_table;

My question now is, when using the consultTable function, I want to check that the return value is actually initialized, some how like in Java pseudocode (because I come from the Java camp):

Route consultTable(int id) {
    Route r = table.find(id);
    return r;
}

then checking if r == null

like image 823
sabbour Avatar asked Jun 19 '09 09:06

sabbour


People also ask

How do you check if a struct has been initialized?

The only way you could determine if a struct was initialized would be to check each element within it to see if it matched what you considered an initialized value for that element should be.

How do you return a struct from a function?

Return struct from a function Here, the getInformation() function is called using s = getInformation(); statement. The function returns a structure of type struct student . The returned structure is displayed from the main() function. Notice that, the return type of getInformation() is also struct student .

Are struct fields initialized 0?

To define a new struct type, you list the names and types of each field. The default zero value of a struct has all its fields zeroed.

How do you return a struct array?

You can't return arrays from functions — period. You can return pointers though, provided the storage will continue to exist after the function returns. Or you can pass a pointer to the function pointing to the storage that the function should use. Don't forget to pass the size of the array too.


1 Answers

There are a few problems here. The most urgent may be what happens when the destination ID is not found. Since you have no constructor on the routing_entry and you are not default initialising, it will have undefined values.

// the data inside route is undefined at this point
routing_entry route;

One way to handle this is to default initialise. This works by instructing the compiler to fill the structure with zeros. This is kind of a trick borrowed from C but it works well here.

routing_entry route={0};

You mention you are coming from Java, unlike in Java, structure and class members are not 0 initialised, so you should really handle that somehow. Another way is to define a constructor:

struct routing_entry
{
  routing_entry()
  : destSeq(0)
  , nextHop(0)
  , hopCount(0)
  { }

            unsigned long destSeq;  // 32 bits
            unsigned long nextHop;   // 32 bits
            unsigned char hopCount; // 8 bits
};

Also note that in C++, the size of the integer and char members is not defined in bits. The char type is 1 byte (but a byte is a not defined, but usually 8 bits). The longs are usually 4 bytes these days but can be some other value.

Moving on to your consultTable, with the initialisation fixed:

routing_entry Cnode_router_aodv::consultTable(unsigned int destinationID )
{    
  routing_entry route={0};

  if ( routing_table.find(destinationID) != routing_table.end() )
        route = routing_table[destinationID];

  return route; // will be "empty" if not found
}

One way to tell might be to check if the structure is still zeroed out. I prefer to refactor to have the function return bool to indicate success. Additionally, I always typedef STL structures for simplicity, so I'll do that here:

typedef map< unsigned long int, routing_entry > RoutingTable;
RoutingTable routing_table;

Then we pass in a reference to the routing entry to populate. This can be more efficient for the compiler, but probably that is irrelevant here - anyway this is just one method.

bool Cnode_router_aodv::consultTable(unsigned int destinationID, routing_entry &entry)
{
  RoutingTable::const_iterator iter=routing_table.find(destinationID);
  if (iter==routing_table.end())
    return false;
  entry=iter->second;
  return true;
}

You would call it like this:

routing_entry entry={0};
if (consultTable(id, entry))
{
  // do something with entry
}
like image 65
1800 INFORMATION Avatar answered Sep 21 '22 15:09

1800 INFORMATION