Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. C and Macros

C and Macros

Scheduled Pinned Locked Moved C / C++ / MFC
question
12 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Filipe Marques
    wrote on last edited by
    #1

    Hi everyone, Right now, I am creating a project in C and at some point I am accessing, multi times during the source code, to a struct with a lot of nested structs, like this

    struct1->struct2->struct3->struct4->struct5->value1
    struct1->struct2->struct3->struct4->struct6->value2

    What I created was a macro to clear the code:

    #define ACCESS (struct1->struct2->struct3->struct4)

    ACCESS->struct5->value1
    ACCESS->struct6->value2

    My question is: This is a good practice or a very very very bad practice? Best regards, Filipe Marques

    J L L 3 Replies Last reply
    0
    • F Filipe Marques

      Hi everyone, Right now, I am creating a project in C and at some point I am accessing, multi times during the source code, to a struct with a lot of nested structs, like this

      struct1->struct2->struct3->struct4->struct5->value1
      struct1->struct2->struct3->struct4->struct6->value2

      What I created was a macro to clear the code:

      #define ACCESS (struct1->struct2->struct3->struct4)

      ACCESS->struct5->value1
      ACCESS->struct6->value2

      My question is: This is a good practice or a very very very bad practice? Best regards, Filipe Marques

      J Offline
      J Offline
      Jochen Arndt
      wrote on last edited by
      #2

      Bad practice is using such chains of pointers. You should check if that can be avoided. If structure members can share memory locations, you should use unions. I would use a variable instead to make the code more readable and avoid the chain:

      struct4_t *struct4 = struct1->struct2->struct3->struct4;
      s5val = struct4->struct5->value;

      F 1 Reply Last reply
      0
      • F Filipe Marques

        Hi everyone, Right now, I am creating a project in C and at some point I am accessing, multi times during the source code, to a struct with a lot of nested structs, like this

        struct1->struct2->struct3->struct4->struct5->value1
        struct1->struct2->struct3->struct4->struct6->value2

        What I created was a macro to clear the code:

        #define ACCESS (struct1->struct2->struct3->struct4)

        ACCESS->struct5->value1
        ACCESS->struct6->value2

        My question is: This is a good practice or a very very very bad practice? Best regards, Filipe Marques

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #3

        Very bad practice, it makes it difficult to understand or maintain the code; you should look closely at your design. You may also benefit from upgrading to C++ and using classes instead of structs.

        Veni, vidi, abiit domum

        F 1 Reply Last reply
        0
        • J Jochen Arndt

          Bad practice is using such chains of pointers. You should check if that can be avoided. If structure members can share memory locations, you should use unions. I would use a variable instead to make the code more readable and avoid the chain:

          struct4_t *struct4 = struct1->struct2->struct3->struct4;
          s5val = struct4->struct5->value;

          F Offline
          F Offline
          Filipe Marques
          wrote on last edited by
          #4

          Thanks for your answer Jochen. I have been thinking better and maybe I will accept the Richard suggestion because the real situation is something worst

          struct1->struct2->struct3->struct4[struct5->struct6->struct7]

          Not pretty ah?. :laugh: Best regards Filipe Marques

          1 Reply Last reply
          0
          • L Lost User

            Very bad practice, it makes it difficult to understand or maintain the code; you should look closely at your design. You may also benefit from upgrading to C++ and using classes instead of structs.

            Veni, vidi, abiit domum

            F Offline
            F Offline
            Filipe Marques
            wrote on last edited by
            #5

            Hi Richar, thanks for your answer. Yeah, the code is getting realy hard to maintain and each little change I do, it is a nightmare. :( Best regards Filipe Marques

            S 1 Reply Last reply
            0
            • F Filipe Marques

              Hi Richar, thanks for your answer. Yeah, the code is getting realy hard to maintain and each little change I do, it is a nightmare. :( Best regards Filipe Marques

              S Offline
              S Offline
              Stefan_Lang
              wrote on last edited by
              #6

              Not sure if some C-Compilers accept functions within a struct like in C++ Classes, but if not, you could just define a global function instead of a member function. You could then also integrate some sanity checks to make your code safer, e. g.:

              // helper function
              Struct4* haul(Struct1* s1) {
              if (s1 && s1->struct2 && s1->struct2->struct3 && s1->struct2->struct3->struct4)
              return s1->struct2->struct3->struct4;
              else
              return 0;
              }

              ...
              // using it
              Struct4* s4 = haul(struct1);
              if (s4) {
              s4->struct5->struct6;
              ...
              }

              Of course the question is why you need so many levels of indirection :wtf:

              GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

              J F 2 Replies Last reply
              0
              • S Stefan_Lang

                Not sure if some C-Compilers accept functions within a struct like in C++ Classes, but if not, you could just define a global function instead of a member function. You could then also integrate some sanity checks to make your code safer, e. g.:

                // helper function
                Struct4* haul(Struct1* s1) {
                if (s1 && s1->struct2 && s1->struct2->struct3 && s1->struct2->struct3->struct4)
                return s1->struct2->struct3->struct4;
                else
                return 0;
                }

                ...
                // using it
                Struct4* s4 = haul(struct1);
                if (s4) {
                s4->struct5->struct6;
                ...
                }

                Of course the question is why you need so many levels of indirection :wtf:

                GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                J Offline
                J Offline
                jschell
                wrote on last edited by
                #7

                That would be my choice.

                1 Reply Last reply
                0
                • S Stefan_Lang

                  Not sure if some C-Compilers accept functions within a struct like in C++ Classes, but if not, you could just define a global function instead of a member function. You could then also integrate some sanity checks to make your code safer, e. g.:

                  // helper function
                  Struct4* haul(Struct1* s1) {
                  if (s1 && s1->struct2 && s1->struct2->struct3 && s1->struct2->struct3->struct4)
                  return s1->struct2->struct3->struct4;
                  else
                  return 0;
                  }

                  ...
                  // using it
                  Struct4* s4 = haul(struct1);
                  if (s4) {
                  s4->struct5->struct6;
                  ...
                  }

                  Of course the question is why you need so many levels of indirection :wtf:

                  GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                  F Offline
                  F Offline
                  Filipe Marques
                  wrote on last edited by
                  #8

                  Hi Stefan. Thanks for your answer. It is very smart way to contour the problem. I think I would never figure out a solution like that :) . The reason of so many levels is because the s1 is an identity with a lot of different information and I must have access to them in every function (I thought this was the best way) but I will take a chance in C++. I think in my situation will help me a lot. Best regards Filipe Marques

                  S 1 Reply Last reply
                  0
                  • F Filipe Marques

                    Hi Stefan. Thanks for your answer. It is very smart way to contour the problem. I think I would never figure out a solution like that :) . The reason of so many levels is because the s1 is an identity with a lot of different information and I must have access to them in every function (I thought this was the best way) but I will take a chance in C++. I think in my situation will help me a lot. Best regards Filipe Marques

                    S Offline
                    S Offline
                    Stefan_Lang
                    wrote on last edited by
                    #9

                    You appear to be facing a problem that is not related to the programming language or it's (lack of) features: when your function needs to parse a data structure of such complexity, the question arises why it needs to know about the entirety of this structure? Wouldn't it be sufficient if e. g. the caller passed struct1->struct2->struct3 to the function as an argument, so it wouldn't need to dig through the top layers to start with? If this is true, then you need to redesign the function signature so it requests only pointer(s) those parts of the data structures that it needs to access. Or, if your function really needs to know about all parts of that data structure, then it might be doing too much in just one function, and you should consider splitting it up into multiple parts. Or, if your function is small, and really can't be split up any further in a sensible way, then the question arises why are these data values spread so far out over different parts of the data structure? Maybe it is the data structures after all , that need to be redesigned, so that related values are stored within the same (sub-)structure! All of this is based on the principals of "locality of concern" or "information hiding". You can google on those expressions for more information.

                    GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                    F 1 Reply Last reply
                    0
                    • S Stefan_Lang

                      You appear to be facing a problem that is not related to the programming language or it's (lack of) features: when your function needs to parse a data structure of such complexity, the question arises why it needs to know about the entirety of this structure? Wouldn't it be sufficient if e. g. the caller passed struct1->struct2->struct3 to the function as an argument, so it wouldn't need to dig through the top layers to start with? If this is true, then you need to redesign the function signature so it requests only pointer(s) those parts of the data structures that it needs to access. Or, if your function really needs to know about all parts of that data structure, then it might be doing too much in just one function, and you should consider splitting it up into multiple parts. Or, if your function is small, and really can't be split up any further in a sensible way, then the question arises why are these data values spread so far out over different parts of the data structure? Maybe it is the data structures after all , that need to be redesigned, so that related values are stored within the same (sub-)structure! All of this is based on the principals of "locality of concern" or "information hiding". You can google on those expressions for more information.

                      GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                      F Offline
                      F Offline
                      Filipe Marques
                      wrote on last edited by
                      #10

                      Thank you Stefan, I didn't know about "locality of concern" or "information hiding". In these couple of days I have been review the code and yes, I am passing information that I am not really using in my functions and I am making all of them available to the user, unnecessarily. Right now I am redrawing the code ... again :laugh: Best regards Filipe Marques

                      1 Reply Last reply
                      0
                      • F Filipe Marques

                        Hi everyone, Right now, I am creating a project in C and at some point I am accessing, multi times during the source code, to a struct with a lot of nested structs, like this

                        struct1->struct2->struct3->struct4->struct5->value1
                        struct1->struct2->struct3->struct4->struct6->value2

                        What I created was a macro to clear the code:

                        #define ACCESS (struct1->struct2->struct3->struct4)

                        ACCESS->struct5->value1
                        ACCESS->struct6->value2

                        My question is: This is a good practice or a very very very bad practice? Best regards, Filipe Marques

                        L Offline
                        L Offline
                        leon de boer
                        wrote on last edited by
                        #11

                        It becomes a "depends" question and by that I mean it depends on why such deep nesting is required. To me your code looks like it either needed a variant record or simple database functions put over the top of it. To give you the idea lets look at a simple example that would nest something like what you have. Lets say we have database of books that were linked in memory. Done in your sort of nested format to access a given line would be like this section struct->book struct->page struct-> Line struct->actual text on that line So you could imagine an example something like Fiction->War and Peace->page 200->line 20->text That structure points to the text on the 200th page, line 20 of the fictional book called "war and peace" There is nothing wrong with that but from a programming sense it would have been much more desirable to setup a basic interface. Define your structures Section, Book, Page, Line as per normal but make functions to do the work book* SelectBook (book* Booklist, section, title); page* MoveToPage (book* SelectedBook, int PageNum); line* MoveToLine (page* SelectedPage, int LineNum); So your code would now become something like

                        book* MyCurrentBook;
                        page* CurrentPage;
                        line* CurrentLine;

                        MyCurrentBook = SelectBook(BookList, Fiction, "War and peace"); // Select our book
                        Currentpage = MoveToPage(MyCurrentBook, 200); // select page 200
                        CurrentLine = MoveToLine(Currentpage, 20); // select line 20

                        What you get for the cost of building the functions is code clarity as well as being able to contain error checks inside the functions. You can take the idea even further if you like and start writing object like code in C. So my ultimate view of your macro depends on what your nested structure list is for and could it have been done a better way. If it couldn't then using the MACRO is perfectly fine.

                        F 1 Reply Last reply
                        0
                        • L leon de boer

                          It becomes a "depends" question and by that I mean it depends on why such deep nesting is required. To me your code looks like it either needed a variant record or simple database functions put over the top of it. To give you the idea lets look at a simple example that would nest something like what you have. Lets say we have database of books that were linked in memory. Done in your sort of nested format to access a given line would be like this section struct->book struct->page struct-> Line struct->actual text on that line So you could imagine an example something like Fiction->War and Peace->page 200->line 20->text That structure points to the text on the 200th page, line 20 of the fictional book called "war and peace" There is nothing wrong with that but from a programming sense it would have been much more desirable to setup a basic interface. Define your structures Section, Book, Page, Line as per normal but make functions to do the work book* SelectBook (book* Booklist, section, title); page* MoveToPage (book* SelectedBook, int PageNum); line* MoveToLine (page* SelectedPage, int LineNum); So your code would now become something like

                          book* MyCurrentBook;
                          page* CurrentPage;
                          line* CurrentLine;

                          MyCurrentBook = SelectBook(BookList, Fiction, "War and peace"); // Select our book
                          Currentpage = MoveToPage(MyCurrentBook, 200); // select page 200
                          CurrentLine = MoveToLine(Currentpage, 20); // select line 20

                          What you get for the cost of building the functions is code clarity as well as being able to contain error checks inside the functions. You can take the idea even further if you like and start writing object like code in C. So my ultimate view of your macro depends on what your nested structure list is for and could it have been done a better way. If it couldn't then using the MACRO is perfectly fine.

                          F Offline
                          F Offline
                          Filipe Marques
                          wrote on last edited by
                          #12

                          Hi Leon, thanks for your answer. What you described here is exactly my problem. The problem is that I always program in C++ and the few C programs were really small ones. The way to think is a little different and I always think in an object way. I decided to migrate to C++. The code became cleaned and easy to read. One more time, thanks for your answer and I am sorry to take so long to answer :) Best regards Filipe Marques

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups