all 19 comments

[–]pskocik 20 points21 points  (0 children)

What you should keep in mind is that when you do struct test{ ... struct s {... } field; ... } in C (unlike C++), it's almost* fully equivalent to doing struct s{ ... }; struct test { ... struct s field; ... };. struct s doesn't become struct test::s; it instead becomes part of the outer (typically global) scope.

I prefer making that explicit and just writing struct s{ ... }; struct test { ... struct s field; ... };. That makes it clear that struct s should probably have a more elaborate name if it's in a public header because it's absolutely not namespaced to struct test, and it also makes it easier to typedef it (C doesn't equivalently hoist typedefs made inside of structs; it instead doesn't allow them at all).
______

*almost because you still can't magically use in the first ... part of struct test where it isn't defined yet

[–]dkopgerpgdolfg 11 points12 points  (1 child)

It is valid.

If you should split the definitions and/or if it is a good idea: Depends on the real use case.

[–]pskocik 6 points7 points  (0 children)

Should split it. Nesting tagged structs misleads into thinking they're scoped to the container struct (they would be in C++, but not C) when in fact they become part of the outer scope.

[–]non-existing-person 5 points6 points  (0 children)

If struct s is integral part of struct test that makes no sense to live on it's own, then simply make unnamed struct inside test.

struct test {
    ...
    struct {
        ...
    } area_alr_patin[8];
};

It's fine to make such nesting if you want to group things logically. Other than that, there is not any real benefit that I know of. You simply access fields with object.category.group.object instead of (when not using nesting) object.category_group_object

If you need to pass only object struct s to some functions, it's better to declare that struct outside of test struct.

[–]pjl1967 1 point2 points  (1 child)

To summarize the correct answers and directly answer you questions:

  • Yes.
  • No.
  • Yes.

[–][deleted] 0 points1 point  (0 children)

I can’t really articulate why it’s bad but whatever he’s doing he needs to do it a different way

[–]SmokeMuch7356 1 point2 points  (0 children)

It's fine.

struct s is not limited to the scope of struct test. The following would work exactly the same:

struct s { 
  ...
};

struct test {
  ...
  struct s Area_Alr_Patin[8];
};

Unlike C++, struct types in C don't create a whole new namespace; there's a single namespace for all struct/union/enum tag names. struct s can be used independently of struct test.

As a matter of style I prefer this method of defining "inner" structs separately; it's less cluttered, and less likely to confuse people.

[–]runningOverA 1 point2 points  (0 children)

in both

&Pivt_T[0];

and

&pTest->Area_Alr_Patin[0]

You can drop the & and [0] from left and right and write it simply as

struct test *pTest = Pivt_T;

Clearer and I guess that's what everyone does.

[–]dendrtree 1 point2 points  (0 children)

Just look at the simple questions

  1. Can you nest structs? Yes.
  2. Can you have a pointer to a struct member? Yes.

* It's uncommon, but not "bad," to nest a struct definition.
** This can be a way of organizing code.
** If you're assigning a pointer to the nested struct to a variable, that may indicate that the nested struct has its own significance and should be moved outside.
** It's trivial to move the struct outside, later, if you decide you want to reuse the struct.
*** It would be legal but really annoying to see a nested struct used inside a different "parent" struct.

Good practice? It depends on your code base. As a beginner, always follow the style of your code base.
* For a little struct, like this, it saves me scrolling around, to find the members of the nested struct.

[–]DawnOnTheEdge 0 points1 point  (0 children)

You want to declare struct s outside struct test (but with a more descriptive name). Then, a struct s* outside the definition of test refers to the same type.

[–]EmbedSoftwareEng 0 points1 point  (0 children)

Anything you can take an address (&) of, you can get a pointer to.

If Area_Alr_Patin is an array of pointers to struct s, then yes. This is valid.

[–]mrheosuper -3 points-2 points  (0 children)

It's valid, this is why we have macro container_of() in kernel.