#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
};
struct address a1;
};
}
This code shows a warning:-
warning : declaration does not declare anything (enabled by default)
Where as the following code shows no warning
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
}a1;
};
}
Why 'warning' is displayed in the first code only?
The reason why the compiler is showing the warning is because it doesn't see a name for the variable of type address you defined for the emp struct, even though you do declare something using address on the next line, but I guess the compiler is not smart enough to figure that out.
As you showed, this produces a warning:
struct emp {
struct address {}; // This statement doesn't declare any variable for the emp struct.
struct address a1;
};
But not this:
struct emp {
struct address {} a1; // This statement defines the address struct and the a1 variable.
};
Or this:
struct address {};
struct emp {
struct address a1; //the only statement declare a variable of type struct address
};
The struct emp {} doesn't show any warnings since this statement is not inside a struct defintion block. If you did put it inside one of those then the compiler will show a warning for that as well. The following will show two warnings:
struct emp {
struct phone {};
struct name {};
};
The reason the warning is displayed is that the first excerpt is not proper C - it has a constraint violation that a standards-compliant C compiler must produce a diagnostisc message for. It violates the C11 6.7.2.1p2:
Constraints
A struct-declaration that does not declare an anonymous structure or anonymous union shall contain a struct-declarator-list.
Meaning that it is OK to write
struct foo {
struct {
int a;
};
};
since the inner struct declares an anonymous structure, i.e. it is not named.
But in your example the struct address has a name - address - and therefore it must have a declarator list after the closing brace - declarator list being for example a1 as in your example, or more complex foo, *bar, **baz[23][45].
The syntax of a structure definition is:
struct identifier {
type member_name;
// ...
};
If you add an identifier just after the closing curly brace, you're declaring a variable with that defined struct.
In your first example the compiler consider the address struct as member type. it's like if you writes:
struct identifier {
type ; // No member name is specified
type a1;
// ...
}
But in the second example you specified the member name:
struct identifier {
type a1; // Member name specified
// ...
}
And here is an example of the warning: http://ideone.com/KrnYiE.
Going to also throw this out there that this error may also show up if you don't properly forward declare types found in other namespaces.
https://stackoverflow.com/a/19001722/1330381
Example
namespace A {
// forward declarations
namespace X {
namespace Y {
class MyType;
}
}
namespace B {
class Foo() {
void methodBar(const X::Y::MyType& mt);
}
}
In my case, i had the same warning because the structure name was previously used and changing the structure name solved the problem.
Related
#include <stdio.h>
typedef struct test {
enum en {
zero, one
} en;
} test;
int main(){
test t;
// t.en = test::one; <-- How can I accomplish this?
return 0;
}
test::one is a C++ syntax and won't compile in C.
Is it possible to access en from outside the struct in C?
I know I can use integers here like t.en = 1; but I'm trying to use enum values.
In C, a struct does not create a new namespace for types - the fact that you defined enum en within the body of the struct definition makes no difference, that tag name is visible to the remainder of the code in the program. It's not "local" to the struct definition. Same with a nested struct type - if declared with a tag, such as
struct foo {
struct bar { ... };
...
};
struct bar is available for use outside of struct foo.
C defines four types of namespaces - one for all labels (disambiguated by the presence of a goto or :), one for all tag names (disambiguated by the presence of the struct, union, or enum keywords), one for struct and union member names (per struct or union definition - disambiguated by their presence in a struct or union type definition, or by the presence of a . or -> member selection operator), and one for all other identifiers (variable names, external (function) names, typedef names, function parameter names, etc.).
Yes, by simply writing the name defined.
#include <stdio.h>
typedef struct test {
enum en{
zero, one
} en;
} test;
int main(){
test t;
t.en = one;
return 0;
}
Structure do not introduce a separate scope in C.
Note also that using en as both the enum tag and variable name is perfectly fine in C, but somewhat confusing in C++.
Here is a modified version that should compile as C and C++:
#include <stdio.h>
#ifdef __cplusplus
#define SCOPED_ENUM(s,e) s::e
#else
#define SCOPED_ENUM(s,e) e
#endif
typedef struct test {
enum en {
zero, one
} en;
} test;
int main() {
test t;
t.en = SCOPED_ENUM(test, one);
return 0;
}
My problem is that car_name_str could not be resolved. Why is it not callable and I want to keep the code structure?
I want to keep the structure as struct with union and enum (different datatypes).
Template: How can mixed data types (int, float, char, etc) be stored in an array?
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
//fill_car.c
#include "car_union.h"
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value->car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value->car_cost= 45000;
Just remove the [30][3] from the type def, like this
#include <stdio.h>
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
extern Car_data_ex *Car_data[30][3];
int main() {
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value.car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value.car_cost= 45000;
}
Regardless of what's in your struct, when you do
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
(I've tagged the struct so it can be referred to by struct Car_dataStructTag),
then Car_data_ex is a type alias resolving to struct Car_dataStructTag [30][3]
which means
extern Car_data_ex *Car_data[30][3];
is fully equivalent to
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
which means Car_data[x][y] is a pointer to a two-dimensional array of struct Car_dataStructTag,
which is definitely not something you can apply -> to.
Try:
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
in a compiler -- it gets accepted, confirming the declaration equivalence.
Running into situations such as this one is why it's generally considered ill-advisable to typedef arrays or pointers.
You have over complexified everything.
A typedef is just to give an alias to a (complex) type. Here the type is a struct containing an enum and an union. So it should be:
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
Next, using an array of pointers can make sense, but provided each pointer in the array does point to a true object. Here you only want a plain (2D) array:
Car_data_ex Car_data[30][3];
Once this has been done, you can write with no error or warning:
Car_data[0][0].type = car_name_str;
Car_data[0][0].value.car_name= "land rover";
Car_data[0][1].type = car_cost_float;
Car_data[0][1].value.car_cost= 45000;
And you should avoid extern Car_data_ex Car_data[30][3];. It declares a global array, that will have to be defined in one single compilation unit (.c file). Here again, it can make sense, but IMHO it is a rather advanced feature that can be hard to correctly use. And nothing in the shown code lets think that is is required...
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
example:
struct foo {
int x;
};
typedef struct foo struct bar;
int main(void) {
struct bar bar;
bar.x = 10;
return 0;
}
but this doesn't work obviously.
Here are the errors if anyone is curious:
main.c:5:20: error: two or more data types in declaration specifiers
typedef struct foo struct bar;
^
main.c:5:27: warning: useless storage class specifier in empty declaration
typedef struct foo struct bar;
^
main.c: In function 'main':
main.c:9:13: error: storage size of 'bar' isn't known
struct bar bar;
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
So, it seems that you want to define a structure alias for another structure type.
This is not possible with typedef as it creates a single word alias. The new alias can't be consisted of multiple white space separated words.
But you can use a single name like struct_bar with struct implemented inside of the name to show that bar is a structure.
#include <stdio.h>
struct foo {
int x;
};
typedef struct foo struct_bar;
int main(void) {
struct_bar bar;
bar.x = 10;
return 0;
}
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?.
You cannot. A namespace is a declarative region that provides a scope to the identifiers (names of the types, function, variables etc) inside it. The concept of Namespace as it is defined within C++, is not inherent in C.
So, if you are okay with minor changes in your requirements, instead of doing something unnatural, use a simple typedef:
Instead of this:
struct foo {
int x;
};
do this:
typedef struct {
int x;
}foo;
Then this will work:
typedef foo bar;
int main(void )
{
bar b;
b.x = 10;
return 0;
}
Note: Although namespaces are not inherent in in C, as they are in C++, there are some interpretations eg: as discussed here, that argue the point.
C doesn't have any type of support for namespaces (at least not in the sense that C++ does).
When you create a typedef, the new type name is a single identifier, not multiple words. So struct bar can't be an alias for another type. You would have to call it bar or some other one-word name.
You can't. This isn't how it works.
You cannot "create" a type whose name is more than one word, nor can you refer to a type alias using the keyword struct.
The purpose of writing struct, in this context, is to refer to a struct type by a name that wasn't introduced as an alias. The keyword is there to say that that's what you want to do. But it's not part of the name; it cannot be part of the name.
Fortunately, there's no reason to need or even want this.
I found a solution that works for cygwin:
struct foo {
int x;
};
struct bar {
struct foo;
};
struct one
{
int member;
};
struct two
{
int member;
} structure;
If I want to call the above structures in the main() function then in the first case do I need to name the struct one to any random name of my choice and then and then call its member like this:
int main() {
struct one random_name;
random_name.member = 1;
}
and in the second case I have already named the structure so it's just that I can directly call the member with the name structure like this:
int main() {
structure.member = 1;
}
Is the version below valid or do I have to put typedef in front of the struct?
struct {
int member;
} structure;
Using int as the type of the structure members throughout, then:
struct one
{
int member;
};
This is a perfectly fine definition of the type struct one. It defines no variables of type struct one; it is simply a type that can be used later in the translation unit.
struct two
{
int member;
} structure;
This is a perfectly fine definition of the type struct two and is also the definition of a variable structure of type struct two.
If I want to call the above structures in the main() function then in the first case do I need to name the struct one to any random name of my choice and then and then call its member like this:
int main(void)
{
struct one random_name;
random_name.member = 1;
}
If you want to use a variable of type struct one, you will have to define it, and the way you've done so is fine. You don't 'call' members of structures. You use them.
and in the second case I have already named the structure so it's just that I can directly call the member with the name structure like this:
int main(void)
{
structure.member = 1;
}
This is also valid because you defined the variable structure at the same time as you defined the type struct two.
Is the below version valid or do I have to put typedef in front of the struct:
struct
{
int member;
} structure;
This is also legitimate code. It defines an anonymous structure type and defines a single variable of that type. It is the only variable of that type that can exist, but occasionally it is useful to use this.
Note that if the last structure was followed by:
struct
{
int member;
} form;
the types of the variables form and structure are different; you cannot legitimately assign one to the other, for example, or pass either of them to another function, etc.
More typically, you either give the structure type a tag (struct three) or use a typedef (typedef struct { int member; } four;) or both (typedef struct five { int member; } five;, where it is legitimate to use the same name for the tag and the type name as I showed, though there is also an extensive tradition of using different names for the type and the tag).
So with typedef struct { int member; } structure;, in main() creating one or more variables of type structure is possible, like this?
structure first_var;
structure second_var;
This is entirely legitimate. You could instead write:
structure first_var, second_var;
though many people prefer one variable per declaration.
Whereas if we don't use typedef and just do struct { int member; }structure; then I have just got one variable with name structure and can use that only in main(), such as structure.member = 1; and can't create more.
More or less. You can write:
struct { int member; } var1, var2, … varN;
and now you have multiple variables all of the same type. However, although you can write:
struct { int member; } var1;
struct { int member; } var2;
the two variables var1 and var2 are not officially of the same type. There are complicated bits of wording in the standard in section 6.2.7 Compatible types and composite types which might let you off the hook, but GCC 4.9.1 set fussy says:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c tagless.c
tagless.c: In function ‘main’:
tagless.c:13:10: error: incompatible types when assigning to type ‘struct <anonymous>’ from type ‘struct <anonymous>’
var1 = var2;
^
$
tagless.c
struct
{
int member;
} var1;
struct
{
int member;
} var2;
int main(void)
{
var1.member = 1;
var2.member = 2;
var1 = var2;
return 0;
}
two more doubts:::::::
Whereas if we don't use typedef and just do struct{int member;}structure;
then i just got one variable with name structure and can use that only in
main structure.member=1; and can't create more –
Ans : You can always create more than just one variable once you have declared the structure, so its not that if you dont use typedef you can have only one variable for your structure. For eg:
struct structure
{
int number;
};
int main()
{
structure var1, var2, var3; //...any number of variables can be declared here.
var1.number = 30;
var2.number = 45;
var3.number = 90;
printf("\nvar1 = %d, var2 = %d, var3 = %d\n", var1.number, var2.number, var3.number);
return 0;
}
For a better understanding of typedef,
Consider this example :
1.
struct structure
{
int number;
};
typedef struct structure structure;
2.
typedef struct structure
{
int number;
}structure;
---------------------
Both of the above declarations are equivalent.
typedef is used to define a new name for a variable or a keyword.
Suppose in case if your structure declaration is something like this :
struct this_is_my_structure
{
int number;
};
then every time you declare an instance of this structure you will have to use this long name in front of your instance, like:
int main()
{
struct this_is_my_structure var1; // you dont want to write such long types for variables
var1.number = 23;
return 0;
};
You will find typedef helpful here :
typedef struct this_is_my_structure structure;
Now every time you want to declare an instance of type "this_is_my_structure" all you have to do is the following :
int main()
{
structure var1;
var1.number = 23;
return 0;
}
I want to access members of a structure from void pointer inside a structure, I have tried the following code but it is giving error as "expected identifier before ‘(’ token". what should I change in printf statement? Thanks in advance.
#include "stdio.h"
struct
{
int date;
char *name;
}test;
struct
{
void *check;
}massage;
main()
{
test.date=21;
test.name="Nilesh";
massage.check =&test;
printf("date - %d , name - %s\n",massage.((struct test *)check)->date,massage.((struct test *)check)->name);
}
struct // anonymous struct type
{
int date;
char *name;
} test;
The above statement defines an anonymous struct type and creates a variable test of this struct type which has no name. Similarly, the below statement defines an anonymous struct type and creates a variable massage of this type -
struct // anonymous struct type
{
void *check;
} massage;
The typecast operator must have a type in the parentheses (type), not a variable name. Therefore, you must give the first struct a name (tag) so as to use the typecast operator. Also, the result of a typecast operator is an r-value and therefore it cannot be used with member selection .(dot) operator (it should be the name of the member). Therefore, the typecast operator should be applied after the value is fetched from the structure. Therefore, the following expression is wrong -
massage.((struct foo *)check)->date
// |____________________|
// |
// this should be the member name but it
// evaluates to a r-value - the result of
// the typecast operator assuming struct tag
// is foo
// it should instead be
((struct foo *)massage.check)->date
// dot operator has higher precedence than typecast
// so the struct member check is fetched first and
// it is typecast to type (struct foo *)
I suggest the following changes -
// standard headers should be
// enclosed in angle < > brackets
#include <stdio.h>
// give the structure a name so it can be
// used in typecasting
struct foo {
int date;
char *name;
} test;
// anonymous struct type
struct {
void *check;
} massage;
// return type of main should be int and
// parameter list should contain void
int main(void) {
test.date = 21;
test.name = "Nilesh";
massage.check = &test;
// fetch the struct member check and then
// apply typecast operator
printf("date - %d , name - %s\n", ((struct foo *)massage.check)->date,
((struct foo *)massage.check)->name);
return 0;
}
In your expression:
massage.((struct test *)check)->date
// ^^^ is variable not a data-type
there are two mistakes:
You can't type case into a variable, in your code test is a variable not a type so (struct test *) is wrong expression. You should name the user-defined type (as I have suggested below).
You are applying typecasting without accessing massage's pointer member. So in expression (struct test *)check, actually "check" is unknown variable. compiler will error you "check" is undeclared variable (thought test is not a datatype but the order of applying type casting is conceptually wrong).
I am suggesting a couple of correction try with it:
Name the stuct e.g. newtype
struct newtype // notice I given name to user defined datatype
{
int date;
char *name;
}test;
Then correct second and third argument in printf function as below
((struct newtype *)massage.check)->date
// ^^^^^^^^^^^^^^ notice
Similarly third argument in printf. First access member then type cast to correct type.
For full code refer Ajay's answer.
The struct definition is not want you want -- it defines an object test of an unnamed struct type. Try
struct testType
{
int date;
char *name;
} test;
and then cast to (testType *).