What is the difference between these two structure declarations?
Asked Answered
E

7

32

I am confused about these two structures from different tutorials:

typedef struct complex {
    float real;
    float imag;
} COMPLEX;

typedef struct {
    float real;
    float imag;
} COMPLEX;

COMPLEX c1;

Are they both correct? Why? and is it necessary to add the lowercase of complex before struct? What is general situation?

Efferent answered 13/9, 2021 at 9:0 Comment(4)
Those look like they are from a C tutorial, in C++ you don't need to typedefAngelia
Even the COMPLEX bit is not needed! en.cppreference.com/w/c/language/struct, If you just started learning "C++" try to get information from sources that teach C++11 or later.Vainglorious
You used both the [c] and [c++] tags, but the answers are very different for the two languages. Please remove one so you're asking about just the language you're studying.Accentuation
@aschepler: To be fair, they both work in both languages due to only using the typedeffed name, not the struct tag. godbolt.org/z/16Mcde99T. Still generally agreed, though, that this question probably shouldn't have both tags unless it's asking about the difference between languages.Curtsey
K
31

With the first you can use either the type-alias COMPLEX or struct complex.

With the second you have an anonymous structure which can only be used with the type-alias COMPLEX.

With that said, in C++ any structure name is also a type-name and can be used as a type directly:

struct complex { ... };
complex c1;
Korea answered 13/9, 2021 at 9:3 Comment(1)
A struct-tag is only looked for in C++ if it cannot be otherwise resolved. So, a struct-tag is not quite a type-name there.Nevis
W
18
typedef struct complex{
    float  real;
    float imag;
}COMPLEX;

This is a struct complex which has been typedef'ed to COMPLEX. You can now use both struct complex c1; and COMPLEX c1;. As you tagged this question C++, you can also use complex c1; as the struct (and thus, the typedef to avoid it) is not necessary in C++.

typedef struct {
    float  real;
    float imag;
}COMPLEX;

This is an unnamed struct, typedef'ed to COMPLEX. You can now use COMPLEX c1;.

So far for the difference between these two (C) constructs.

As you tagged this question C++, the correct thing to do would be to use the features of the C++ header <complex>:

std::complex< float > c1;
Wichern answered 13/9, 2021 at 9:4 Comment(0)
G
10

For starters there is no anonymous structure as others have written in their answers to your question. There is an unnamed structure (a structure without a tag name) that has the alias name COMPLEX

typedef struct {
    float real;
    float imag;
} COMPLEX;

In C++ the term unnamed class/structure is documented like (the C++ 14 Standard, 9 Classes)

A class-specifier whose class-head omits the class-head-name defines an unnamed class.

As for the notion anonymous structure then it is defined in C the following way (6.7.2.1 Structure and union specifiers, p.#1)

13 An unnamed member of structure type with no tag is called an anonymous structure; an unnamed member of union type with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.

Here is an example of an anonymous structure

struct A
{
    struct { int x; int y; };  // <== anonymous structure
    int z;
};

Bear in mind that in C++ opposite to C there is no such a notion as anonymous structure. In C++ there is only the notion of anonymous union.

As for your question

Are they both correct? Why? and is it necessary to add the lowercase of complex before struct? What is general situation?

then the both typedef declarations are correct. And there is no need to use exactly lower-case name complex as the structure tag. You may use also upper-case name COMPLEX as the structure tag.

typedef struct COMPLEX {
    float real;
    float imag;
} COMPLEX;

In this structure declaration

typedef struct {
    float  real;
    float imag;
}COMPLEX;

there is declared a structure without a tag name. So you can refer it only by means of its alias name COMPLEX.

In C structure tag names have their own name space that do not conflict with identifier names in other name spaces.

From the C Standard (6.2.3 Name spaces of identifiers)

1 If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:

— the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);

For example consider the following program.

#include <stdio.h>

typedef struct {
    float  real;
    float imag;
} COMPLEX;

int main(void) 
{
    int COMPLEX;
    COMPLEX c = { 0.0f, 0.0f };
    
    return 0;
}

The compiler will issue an error because the declaration of the local variable COMPLEX hides the alias name of the unnamed structure declared in the file scope.

However if you will write

#include <stdio.h>

typedef struct COMPLEX {
    float  real;
    float imag;
} COMPLEX;

int main(void) 
{
    int COMPLEX;
    struct  COMPLEX c = { 0.0f, 0.0f };
    
    return 0;
}

then the name COMPLEX of the local variable will not conflict with the tag name COMPLEX of the structure. The C compiler can only issue a message that declared variables are not used.

Another important difference is that sometimes you need to refer to the declared structure specifier within the structure definition itself.

For example if you want to declare a singly-linked list in C you need to write

typedef struct Node
{
    int data,
    struct Node *next;
} Node;

Without the tag name like

typedef struct 
{
    int data,
    struct Node *next;
} Node;

the compiler considers this structure definition as declarations of two different type specifiers: unnamed structure with the alias name Node and another structure with the tag name Node. These types are not compatible.

As for C++ then you may use the name of a structure tag without specifying the keyword struct

For example

struct complex{
    float  real;
    float imag;
};

struct complex c1;
complex c2;

Also you can refer the structure specifier within its definition without using the keyword struct because (the C++ 15 Standard, 9 Classes)

2 A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.

For example

struct Node
{
    int data,
    Node *next;
};

But again a declaration of a variable or a function can hide a declaration of a structure. In this case you need to use the keyword struct. Such using of a name with the keyword struct is called in C++ as elaborated type specifier.

For example

struct complex{
    float  real;
    float imag;
};

int complex;
struct complex c;

Without specifying the keyword struct the compiler will issue an error because the declaration of the integer variable hides the declaration of the structure.

Pay attention to that many programmers do not even know that the typedef in C and C++ can be also rewritten like

struct COMPLEX {
    float  real;
    float imag;
} typedef COMPLEX;
Gitagitel answered 13/9, 2021 at 10:26 Comment(2)
Very good answer... no anonymous structure indeed, but I'm afraid typedef struct { float real; float imag; } COMPLEX; does not meet the definition of an unnamed structure either. tagless or untagged seem more precise but these terms are not used in the C Standard either.Centering
@Centering In fact we may call a structure without a tag name as an unnamed structure. That is the type specifier of a structure type does not have a name.Gitagitel
B
4

This is really because the type system changed subtly between C and C++. User defined structures (and enums) in C had "tags", which were treated as different from types.

struct Tag {/*some members*/};
typedef struct Tag Type; /* Tag and Type can be the same name */

This way of working is still supported as your example shows, but C++ added a new rule, that says that structure tags are always types as well. Thus, viewed from a C view-point it's as if the C++ compiler adds the typedef for you. Thus in C++ you no longer need to say "struct" before declaring variable of your structure type.

So yes, both ways are "correct", one is the old C way, and will work in both C and C++, the other is the native C++ way, and will not compile in C. It's possible your example needed C compatibility for some of the code but not all.

If you need C-compatibility you should use the pattern above, but it is not common practice to use it for native C++ code.

Blastosphere answered 13/9, 2021 at 9:38 Comment(0)
S
2

struct definition is as below:

struct type_name {
       member_type1 member_name1;
       member_type2 member_name2;
       .
       .
                } object_names;

you use one name for struct name and object name. you can use object in side of structure definition without declare a name for struct

Saxophone answered 13/9, 2021 at 11:38 Comment(0)
L
0

There is nothing like C/C++ language.

In C.

   typedef struct complex {
        float real;
        float imag;
    } COMPLEX;

    COMPLEX c1;
    struct complex c2;

Aliases struct complex to type COMPLEX

   typedef struct{
        float real;
        float imag;
    } COMPLEX;

    COMPLEX c1;

Aliases tagless structure to type COMPLEX

What is the practical difference?

As you see using the first one you can define new objects using the new type COMPLEX and struct complex.

The secon type decvlaration allows only definitions using COMPLEX type.

Lobell answered 13/9, 2021 at 14:42 Comment(0)
E
0

Think of "namespaces" here: struct names live in their own namespace.

struct complex {
    float real;
    float imag;
};

struct complex myvar; // in C and C++
complex myvar // only in C++!

C++ also resolves struct-tags (if not otherwise possible), where C does not. typedef defines an alias for a typename, i.e.

typedef struct complex COMPLEX;

will define a new name COMPLEX which is a stand-in for struct complex.

This declaration

typedef struct complex {
    float real;
    float imag;
} COMPLEX;

is shorthand for

struct complex {
    float real;
    float imag;
};
typedef struct complex COMPLEX;

You can also omit the struct-tag altogether

typedef struct {
    float real;
    float imag;
} COMPLEX;

just as in

struct {
    float real;
    float imag;
} myvar;

which defines a variable myvar with an unnamed struct type.

Extemporary answered 18/9, 2021 at 9:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.