romanbird
romanbird

Reputation: 178

Dealing with nested struct access

What is the best way to avoid writing something like:

someDataStruct.longSubStructName.anotherLongName.theVariable = 
    someStruct.longSubStructName.anotherLongName.theVariable + 10;

Setters and getters would be a work around in oop programs. But what would be the best way to deal with this in for example C without having any objects?

Upvotes: 0

Views: 120

Answers (3)

Sai Karthik K
Sai Karthik K

Reputation: 31

Transfer these operation inside a function with meaning full name and use inline.

inline void someFunctionNameAdd(int val)
{
    someDataStruct.longSubStructName.anotherLongName.theVariable = 
         someStruct.longSubStructName.anotherLongName.theVariable + val;
}

then call function someFunctionName(10);

Other way use define macro:

#define SOME_MEANINGFULLNAME \
          someDataStruct.longSubStructName.anotherLongName.theVariable

then: SOME_MEANINGFULLNAME+=10;

Upvotes: 0

Christian Gibbons
Christian Gibbons

Reputation: 4370

If you can make your inner structs anonymous typedefs, you can use plan9 extensions to access the sub-struct's member directly (assuming there aren't any variable name conflicts). Disclaimer: I do not really recommend this method as I prefer standard-conforming C, but figure I'd lob it out there because it does exist. Here's an example of it:

#include <stdlib.h>
#include <stdio.h>

typedef struct{
   int x;
   int y;
} inner_struct1;

typedef struct{
   int v;
   int w;
} inner_struct2;

struct outer_struct {
   inner_struct1;
   inner_struct2;
   int a;
   int b;
   int c;
};

int main(void)
{
   struct outer_struct os;
   os.x = 1;
   os.y = 2;
   os.v = 3;
   os.w = 4;
   os.a = 5;
   os.b = 6;
   os.c = 7;

   printf("inner_struct1.x: %d, inner_struct1.y: %d, inner_struct2.v: %d,
       inner_struct2.w: %d os.a: %d, os.b: %d, os.c: %d\n",
       os.x, os.y, os.v, os.w, os.a, os.b, os.c);
}

With gcc, you'd have to compile with either -fplan9-extensions or -fms-extensions. clang does not have plan9, so only -fms-extensions will work.

Upvotes: 0

dbush
dbush

Reputation: 223739

Create a pointer to the variables in question:

int *someDataVar1 = &someDataStruct.longSubStructName.anotherLongName.theVariable;
int *someDataVar2 = &someStruct.longSubStructName.anotherLongName.theVariable;

*someDataVar1 = *someDataVar2 + 10;

If you're using a deeply nested field like this many times in a block of code, doing something like this can help to increase readability. If you only need to use it once or twice however you're probably better off leaving it way it is.

Here's an example where such a construct might make sense:

for (clientNum = 0; clientNum < clientCount; clientNum++) {
    printf("name: %s\n", mainStructure.subStructure.clientList[clientNum].name);
    printf("address: %s\n", mainStructure.subStructure.clientList[clientNum].address);
    printf("identifier: %x\n", mainStructure.subStructure.clientList[clientNum].identifier);
    printf("file count: %d\n", mainStructure.subStructure.clientList[clientNum].fileCount);

    for (fileNum = 0; fileNum < mainStructure.subStructure.clientList[clientNum].fileCount; fileNum++) {
        printf("filename: %s\n", mainStructure.subStructure.clientList[clientNum].fileList[fileNum].fileName);
        printf("size: %d\n", mainStructure.subStructure.clientList[clientNum].fileList[fileNum].size);
        printf("checksum: %d\n", mainStructure.subStructure.clientList[clientNum].fileList[fileNum].checksum);
        mainStructure.subStructure.clientList[clientNum].fileList[fileNum].printed++;
    }

    mainStructure.subStructure.clientList[clientNum].printed++;
}

Lots of verbose, repeated information here. So much so it can make it difficult to see what you're actually working with. This can be made more readable as follows:

for (clientNum = 0; clientNum < clientCount; clientNum++) {
    struct client *thisClient = &mainStructure.subStructure.clientList[clientNum];
    printf("name: %s\n", thisClient->name);
    printf("address: %s\n", thisClient->address);
    printf("identifier: %x\n", thisClient->identifier);
    printf("file count: %d\n", thisClient->fileCount);

    for (fileNum = 0; fileNum < thisClient->fileCount; fileNum++) {
        struct file *thisFile = &thisClient.fileList[fileNum];
        printf("filename: %s\n", thisFile->fileName);
        printf("size: %d\n", thisFile->size);
        printf("checksum: %d\n", thisFile->checksum);
        thisFile->printed++;
    }

    thisClient->printed++;
}

Upvotes: 2

Related Questions