How does scope affect global and local structures of the same name? - c

I have declared two different structures with same name foo, as one of them is declared as globally, and can be easily accessible by any function in program. But I have this second struct in main, which is locally declared.
Worst comes worst I need to access both of them in main? I did it by declaring struct variable with different names. But now the problem is I need to check size of structures... How should I get the size of local struct not a global one?
#include <stdio.h>
#include <stdlib.h>
struct foo {
char arr1[200];
int x_val;
int y_val;
float result;
};
struct foo globe_foo;
int main()
{
struct foo {
char c;
char arr[20];
int x;
};
struct foo my_foo;
globe_foo.x_val = 20;
printf("Globe foo x_val: %d\n",globe_foo.x_val);
printf("Size of struct foo is: %d\n",sizeof(struct foo));
//how to check size of global decleared stuct foo?
printf("Size of struct foo is: %d\n",sizeof(struct foo));
system("pause");
return 0;
}

Variables within block scope whose name is same as the global scope hides the global identifier
ISO C9899 in 6.2.1 says:
If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will be a strict subset of the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
So here the global struct foo is hidden totally(as if its not there) if you just refer to the typename inside the main().
Suggestions : use different names or use variables with different names for these types or typedef the struct types.
Your printf("Size of struct foo is: %d\n",sizeof(struct foo)); will give the size of only local struct foo(28 or 25 depends).

Standard C does not provide any way to refer to an identifier (either object name or type name) that is hidden by a local declaration.
In this case, you can see the size of the global struct foo by using the size of the object, sizeof globe_foo.
GCC (and compilers supporting its extensions) provides a way to refer to the type of an object, __typeof__. So, in GCC, you can refer to the type of globe_foo with __typeof__(struct globe_foo).
Another option is to give the global type an alias, with typedef. If, at file scope, you declare typedef struct foo foo_t;, then the type foo_t will be visible inside a function even when struct foo is hidden.
When printing sizes (values of type size_t), you should use a %zu specification with printf, not %d.

Related

why is not possible to have static members in struct?

First, from this:
static struct foo1 { //private struct, just for this file
int a;
};
int main (void) {
struct foo1 a = {10};
return 0;
}
question number 1
I will get warning:
warning: useless storage class specifier in empty declaration
};
What does it mean? Why is static "useless storage class specifier"? In other context (static local var in function, or global static, which I wanted to apply for the struct foo1, it would work).
question number 2
#include <stdbool.h>
static struct s_t{ //private struct (for this file only)
static bool is_there = false; // defaul (pre-defined) value for all instances
int value;
};
int main (void) {}
Why is not possible to have static, predefined value for all vars of type struct s_t in c? I just wanted to simulate the same functionality as is in function static local var -> preserve value across multiple calls, in that sense, I wanted have one member (bool is_there in this case) that preserve value across each var of type struct foo1 (instance of it). So why it is not possible?
question number 3
Also, can someone explain the error (in more general sense) from it:
error: expected specifier-qualifier-list before ‘static’
EDIT:
from comments, I do not really understand the concept of storage class, I know only from asm, there is data/text/bss segments, so does it mean static var has address in read-only part of memory? Or what is the concept of storage class in c related to asm?
Because static struct foo1 { ... is just a struct definition, not a variable. You should add static when you declare the instance of the struct. I prefer this style:
typedef struct {
int a;
}foo_t;
static foo_t a = {10};
Because C simply doesn't have static member variables like C++ does. In C, it's pretty useless to add storage- or type specifiers to a single struct member. Put it on the allocated variables instead.
TL;DR it's just not making any sense of your syntax since you can't have static there. Unless you are terribly interested about language grammar, there's nothing else to it.
static is a storage-class specifier and const etc are type qualifiers and int etc is a type specifier. The term specifier-qualifier list comes from formal C grammar of structs, which isn't terribly interesting to read unless you are making a compiler. When declaring a struct member you have two options (C17 6.7.2.1):
specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
static doesn't fit the bill of either, being a storage-class specifier, so the compiler is saying "what! this is not a specifier-qualifier list where I expected to find one, where is it?"
(And yeah it's recursive, so you can have multiple of type-specifier or type-qualifier such as const long const const int value;. Because C stands for Crazy.)
because struct is like a type or an object, when you declare a static member in C, it would be like:
static int a = 0;
In this case "int" is like the struct type you declared, so if you want to create a struct static member just do like this:
static s_t a;
static struct foo1 { //private struct, just for this file
int a;
};
The static declaration specifier only applies to object or function declarations, not type definitions. All you're doing in that statement is creating the struct foo1 type. Had you written something like
static struct foo1 {
int a;
} foo;
Then the object foo would be declared static.
If you declare the type within the .c file, it will only be visible within that .c file. The only way to make the type visible to multiple .c files is to declare it in a header and #include that header in each file that needs it.
Why is not possible to have static, predefined value for all vars of type struct s_t in c?
Because C struct types are simply not that sophisticated - they're just a way to define a data item with multiple attributes. The language doesn't provide any way to have members that are common across all instances of the type.
Remember that C is a product of the early 1970s and was originally developed to implement the Unix operating system - it was designed to be small, portable, and fast. A lot's been added to it over the last 40-some-odd years, but nothing that really changes the core philosophy of the language.
Well, its quite evident that you will get the warning. The reason is simple! You are trying to assign a Storage Class to the struct definition.
However, storage classes are applicable to variable declarations. Therefore, you are getting the prompt.
If you still wish to employ the static storage class, then you can do so with any variable, preferably, any instance of the structure.

Passing a struct by reference errors( incomplete struct and redeclaration)

I'm trying to pass a struct by reference but no matter what I do I'm running into errors. I think I have the prototyping and declaration and the pointers all screwed up.
This is for an Arduino project of mine. The code works fine on the Arduino compiler but doesn't compile on Pelles C compiler.
#include <stdio.h>
#include <string.h>
#include <stdint.h>
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct Fault_Flag_Struct *Fault_Flag);
struct Fault_Flag_Struct {
char Fault_Name[30];
uint8_t Fault_State;
};
struct Fault_Flag_Struct Fault_Flag [7];
int main(void) {
uint8_t Master_Fault_Byte = 181;
strcpy(Fault_Flag[0].Fault_Name, "fault 0");
Fault_Flag[0].Fault_State = 1;
strcpy(Fault_Flag[1]....
strcpy(Fault_Flag[2]....
strcpy(Fault_Flag[3]....
strcpy(Fault_Flag[4]....
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
return 0;
}
//Puts 8 bits from single byte into 8 separate bytes (flags)//
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct Fault_Flag_Struct *Fault_Flag) {
for ( int i = 0; i < 8; i++ )
{
Fault_Flag[i].Fault_State = (Master_Fault_Byte >> i) & 1;
}
}
error #2140: Type error in argument 2 to 'Fault_Bits_To_Flags';
expected '(incomplete) struct Fault_Flag_Struct *' but found 'struct
Fault_Flag_Struct'.
error #2120: Redeclaration of 'Fault_Bits_To_Flags', previously
declared at Reference.c(4); expected 'void function(unsigned char,
(incomplete) struct Fault_Flag_Struct *)' but found 'void
function(unsigned char, struct Fault_Flag_Struct )'.
Error code: 1 *
The scope of a parameter declaration in the list of parameters of a function prototype terminates at the end of the function declarator. Opposite to C++ there is no such a notion as the elaborated type specifier in C.
From the C Standard (6.2.1 Scopes of identifiers)
... If the declarator or type specifier that declares the identifier appears
within the list of parameter declarations in a
function prototype (not part of a function definition), the identifier
has function prototype scope, which terminates at the end of the
function declarator
So the type specifier struct Fault_Flag_Struct used in the function prototype
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct
Fault_Flag_Struct *Fault_Flag);
denotes a different entity compared with the declaration that follows the function prototype
struct Fault_Flag_Struct {
char Fault_Name[30];
uint8_t Fault_State;
};
So you have to exchange the placements of the declarations.
Also this call
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
is invalid because the type of the expression *Fault_Flag is struct Fault_Flag_Struct while the function expects the type struct Fault_Flag_Struct *. That is instead of a pointer to an object of the type struct Fault_Flag_Struct you are passing the object itself.
Scope and Structure Types
There are two problems in the code shown.
The first is because C has some odd rules about structure definitions. One rule, in C 2018 6.7.2.3 4, is that structure declarations with the same tag (the name after struct) declare the same type (a structure type with that name) only if they have the same scope:
All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type.…
When you declare a structure inside a function declaration, like this:
void foo(struct X *p);
Then the scope of X is function prototype scope. Per 6.2.1 4, this scope ends at the end of the function declaration. Then, when you later define the structure, as with:
struct X { int q; }
it is in a different scope, and, per the rule above, the struct X in the function declaration is not the same type as the struct X in the later definition. One way to fix this is to move the structure definition prior to the function declaration. It also suffices merely to declare the structure tag prior to the function declaration, as with:
struct X;
void foo(struct X *p);
To fully understand what is happening here, we should consider two other issues. One issue is that we could have struct X in two different translation units (different source files compiled separately), and calling a function defined with a struct X * parameter in one unit from another unit that defines struct X is allowed. This is because that, although the two struct X types in the two translations units are different, they are compatible. 6.2.7 1 says:
… Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if…
Oddly, this rule only applies to structures declared in separate translation units. If we defined void foo(struct X *p { … } prior to defining struct X in one translation unit, they are different and incompatible types, but, if we define them in separate units, they are compatible types!
The second issue is how can this code work when the structure declarations have separate scopes:
struct X;
void foo(struct X *p);
The first struct X has file scope (per 6.2.1 4), and the second struct X has function prototype scope. The rule in 6.7.2.3 4 only applies if the declarations have the same scope, so it does not say these declare the same struct X. Instead, there is another rule, in 6.7.2.3 9:
If a type specifier of the form struct-or-union identifier or enum identifier occurs other than as part of one of the above forms, and a declaration of the identifier as a tag is visible, then it specifies the same type as that other declaration, and does not redeclare the tag.
(The “above forms” are definitions or stand-alone declarations.) This causes the struct X in the function declaration after a prior file-scope struct X to specify the same type.
Error in Argument
The second error is in the second argument passed to the function in this statement:
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
Fault_Flag is an array, so *Fault_Flag is the first element of the array. This is a structure, not a pointer. To pass a pointer to the first element of the array, use:
Fault_Bits_To_Flags( Master_Fault_Byte, Fault_Flag);

Can a structure tag be used before its scope?

In the following example:
#include <stdio.h>
#include <stdlib.h>
struct B b;
struct B{int a;};
struct B;
int main()
{
b.a=3;
printf("%d\n", b.a);
return 0;
}
The file scope of structure tag B starts from its first definition/declaration struct B{int a;};.
How can struct B b; refer to B before B's scope without error?
Is struct B; a structure type declaration, or a structure type definition? Why does it not conflict with the other definition struct B{int a;}; in the same file scope?
struct B; is a structure declaration. There can be any number of declarations of the same object. For the kinds of objects that have multiple possible declarations, the declarations have to be compatible — for example you can have multiple prototypes for the same function, but they need to use the same argument and return types. For a structure, there's only one way to declare it without defining it, and it just says “there's a structure called B”. So it's ok to repeat struct B; as many times as you want.
struct B{int a;}; is a structure definition. There can only be one definition of a given object. Certain uses of an object require a prior definition, others only require a prior declaration. For example, you can define a variable whose type is a pointer to an undefined structure:
struct S;
struct S *p = NULL;
But you can't define a variable whose type is an undefined structure:
struct S;
struct S s = {0};
The reason for this difference is that a structure that hasn't been defined yet is an incomplete type — a type for which the compiler doesn't have a size. This isn't a problem to define a pointer, but it is a problem to define an object of the incomplete type: the compiler wouldn't know how much memory is required.
At this point, you may wonder why struct B b; is OK. After all, struct B hasn't even been declared, let alone defined.
The first part of why it's ok is that struct B b; declares the structure B in passing. So by the time struct B is needed to do something with b, the structure has just been declared.
The second part of why it's ok is that struct B b; is not exactly a definition. If it was a definition, then the compiler would need to know how much space to reserve, and an incomplete type would not be ok. This is what would happen if the variable was defined in a function:
void f(void) {
struct B b; // error: storage size of ‘b’ isn’t known
}
But when struct B b; is at the top level of a file, it's a tentative definition. A tentative definition is a declaration; for this, the structure doesn't need to have been defined. When the compiler gets to the end of the file, any tentative definition that hasn't had a proper definition, and for which a definition is needed, becomes a definition. At this point, the structure needs to have been defined. In your example program, b has a tentative definition, and that definition becomes a proper definition at the end of the file.
It's ok to not define the structure if the variable is unused, because it's ok to declare a variable with an incomplete type if the variable is not used.
struct B b;
// end of file
But if the variable is used in a way that requires a complete type, then the structure must have been defined at that point.
struct B b;
void f(void) {
sizeof(b); // error: invalid application of ‘sizeof’ to incomplete type ‘struct B’
}
struct B{int a;}; // too late
Question: How can struct B b; refer to B before B's scope without error?
Answer: From http://c0x.coding-guidelines.com/6.7.2.3.html in section 1471,
"If a type specifier of the form struct-or-union identifier
occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type."
So, you can use the struct tag as forward declaration before the struct type definition.
Question: Is struct B; a structure type declaration, or a structure type definition? Why does it not conflict with the other definition struct B{int a;}; in the same file scope?
Answer: From the same above link in section 1472,
"If a type specifier of the form struct-or-union identifier or enum identifier occurs other than as part of one of the above forms, and a declaration of the identifier as a tag is visible, then it specifies the same type as that other declaration, and does not redeclare the tag."
struct B; is a structure type declaration, struct B{int a;}; is a structure type definition and that's how they do not conflict each other.
You may choose to use the typedef to get rid of the confusion and show more visibility into your structure declaration:
typedef struct B B;
struct B{
int a;
};
B b;

Nested Structure Syntax

I have a quick question..is there any difference in these:
struct myinnerstruct
{
int x;
};
struct mystruct
{
struct myinnerstruct m;
int y;
};
AND THIS
struct mystruct
{
int x;
struct myinnerstruct
{
int y;
};
struct myinnerstruct m;
};
These both work as far as I can tell, but I'm wondering if there's a reason to pick one or the other. Thanks
The difference is that the second one is invalid.
The stuff between the { and } in a struct declaration is a sequence of member declarations. Your
struct myinnerstruct
{
int y;
};
is a type declaration; it doesn't declare a member of the enclosing struct, so it's illegal in that context.
What you can do is this:
struct mystruct
{
int x;
struct myinnerstruct
{
int y;
} m;
};
The declaration of m is a member declaration, so it's ok; it also declares the type struct myinnerstruct. But in my opinion, it's poor style. The type struct myinnerstruct remains visible after the declaration of struct mystruct is completed; see below for the explanation.
If you really want a struct within a struct like that, and you're not going to use struct myinnerstruct anywhere else, you could leave it without a tag:
struct mystruct
{
int x;
struct
{
int y;
} m;
};
But then you might as well declare y as a member of struct mystruct.
If you want struct innerstruct to be a named type, just declare it separately, as you did in your first example.
Here's the explanation of why struct innerstruct remains visible.
The C99 standard (large PDF), section 6.2.1 paragraph 2, says:
For each different entity that an identifier designates, the
identifier is visible (i.e., can be used) only within a region of
program text called its scope. Different entities designated by the
same identifier either have different scopes, or are in different name
spaces. There are four kinds of scopes: function, file, block, and
function prototype. (A function prototype is a declaration of a
function that declares the types of its parameters.)
The C90 and C11 standards have essentially the same wording.
The { braces } in a struct declaration do not define a block, nor do they define any of the other possible kinds of scope, so anything declared between the braces is not scoped to that region; it must be scoped to some surrounding context. It happens that the syntax lets you declare struct myinnerstruct inside another struct definition -- but only if it's part of a member definition. I think this is allowed only because the designers of the language didn't go to any extra effort to disallow it; it's just a side effect of other rules. You can do it, but I don't recommend it.
A reason to choose one or the other would be conventional expectations.
A structure declaration nested within another would not be expected to be reused elsewhere, even though it can be.
Also, there is a psychological clash by not putting things of the same level of abstraction side-by-side. It is perfectly legal to do it, but it makes understanding the code a little harder and maybe more irritating.

How is it legal to reference an undefined type inside a structure?

As part of answering another question, I came across a piece of code like this, which gcc compiles without complaint.
typedef struct {
struct xyz *z;
} xyz;
int main (void) {
return 0;
}
This is the means I've always used to construct types that point to themselves (e.g., linked lists) but I've always thought you had to name the struct so you could use self-reference. In other words, you couldn't use xyz *z within the structure because the typedef is not yet complete at that point.
But this particular sample does not name the structure and it still compiles. I thought originally there was some black magic going on in the compiler that automatically translated the above code because the structure and typedef names were the same.
But this little beauty works as well:
typedef struct {
struct NOTHING_LIKE_xyz *z;
} xyz;
What am I missing here? This seems a clear violation since there is no struct NOTHING_LIKE_xyz type defined anywhere.
When I change it from a pointer to an actual type, I get the expected error:
typedef struct {
struct NOTHING_LIKE_xyz z;
} xyz;
qqq.c:2: error: field `z' has incomplete type
Also, when I remove the struct, I get an error (parse error before "NOTHING ...).
Is this allowed in ISO C?
Update: A struct NOSUCHTYPE *variable; also compiles so it's not just inside structures where it seems to be valid. I can't find anything in the c99 standard that allows this leniency for structure pointers.
As the warning says in the second case, struct NOTHING_LIKE_xyz is an incomplete type, like void or arrays of unknown size. An incomplete type can only appear in a struct as a type pointed to (C17 6.7.2.1:3), with an exception for arrays of unknown size that are allowed as the last member of a struct, making the struct itself an incomplete type in this case. The code that follows cannot dereference any pointer to an incomplete type (for good reason).
Incomplete types can offer some datatype encapsulation of sorts in C...
The corresponding paragraph in http://www.ibm.com/developerworks/library/pa-ctypes1/ seems like a good explanation.
The parts of the C99 standard you are after are 6.7.2.3, paragraph 7:
If a type specifier of the form
struct-or-union identifier occurs
other than as part of one of the above
forms, and no other declaration of the
identifier as a tag is visible, then
it declares an incomplete structure or
union type, and declares the
identifier as the tag of that type.
...and 6.2.5 paragraph 22:
A structure or union type of unknown
content (as described in 6.7.2.3) is
an incomplete type. It is completed,
for all declarations of that type, by
declaring the same structure or union
tag with its defining content later in
the same scope.
The 1st and 2nd cases are well-defined, because the size and alignment of a pointer is known. The C compiler only needs the size and alignment info to define a struct.
The 3rd case is invalid because the size of that actual struct is unknown.
But beware that for the 1st case to be logical, you need to give a name to the struct:
// vvv
typedef struct xyz {
struct xyz *z;
} xyz;
otherwise the outer struct and the *z will be considered two different structs.
The 2nd case has a popular use case known as "opaque pointer" (pimpl). For example, you could define a wrapper struct as
typedef struct {
struct X_impl* impl;
} X;
// usually just: typedef struct X_impl* X;
int baz(X x);
in the header, and then in one of the .c,
#include "header.h"
struct X_impl {
int foo;
int bar[123];
...
};
int baz(X x) {
return x.impl->foo;
}
the advantage is out of that .c, you cannot mess with the internals of the object. It is a kind of encapsulation.
You do have to name it. In this:
typedef struct {
struct xyz *z;
} xyz;
will not be able to point to itself as z refers to some complete other type, not to the unnamed struct you just defined. Try this:
int main()
{
xyz me1;
xyz me2;
me1.z = &me2; // this will not compile
}
You'll get an error about incompatible types.
Well... All I can say is that your previous assumption was incorrect. Every time you use a struct X construct (by itself, or as a part of larger declaration), it is interpreted as a declaration of a struct type with a struct tag X. It could be a re-declaration of a previously declared struct type. Or, it can be a very first declaration of a new struct type. The new tag is declared in scope in which it appears. In your specific example it happens to be a file scope (since C language has no "class scope", as it would be in C++).
The more interesting example of this behavior is when the declaration appears in function prototype:
void foo(struct X *p); // assuming `struct X` has not been declared before
In this case the new struct X declaration has function-prototype scope, which ends at the end of the prototype. If you declare a file-scope struct X later
struct X;
and try to pass a pointer of struct X type to the above function, the compiler will give you a diagnostics about non-matching pointer type
struct X *p = 0;
foo(p); // different pointer types for argument and parameter
This also immediately means that in the following declarations
void foo(struct X *p);
void bar(struct X *p);
void baz(struct X *p);
each struct X declaration is a declaration of a different type, each local to its own function prototype scope.
But if you pre-declare struct X as in
struct X;
void foo(struct X *p);
void bar(struct X *p);
void baz(struct X *p);
all struct X references in all function prototype will refer to the same previosly declared struct X type.
I was wondering about this too. Turns out that the struct NOTHING_LIKE_xyz * z is forward declaring struct NOTHING_LIKE_xyz. As a convoluted example,
typedef struct {
struct foo * bar;
int j;
} foo;
struct foo {
int i;
};
void foobar(foo * f)
{
f->bar->i;
f->bar->j;
}
Here f->bar refers to the type struct foo, not typedef struct { ... } foo. The first line will compile fine, but the second will give an error. Not much use for a linked list implementation then.
When a variable or field of a structure type is declared, the compiler has to allocate enough bytes to hold that structure. Since the structure may require one byte, or it may require thousands, there's no way for the compiler to know how much space it needs to allocate. Some languages use multi-pass compilers which would be able find out the size of the structure on one pass and allocate the space for it on a later pass; since C was designed to allow for single-pass compilation, however, that isn't possible. Thus, C forbids the declaration of variables or fields of incomplete structure types.
On the other hand, when a variable or field of a pointer-to-structure type is declared, the compiler has to allocate enough bytes to hold a pointer to the structure. Regardless of whether the structure takes one byte or a million, the pointer will always require the same amount of space. Effectively, the compiler can tread the pointer to the incomplete type as a void* until it gets more information about its type, and then treat it as a pointer to the appropriate type once it finds out more about it. The incomplete-type pointer isn't quite analogous to void*, in that one can do things with void* that one can't do with incomplete types (e.g. if p1 is a pointer to struct s1, and p2 is a pointer to struct s2, one cannot assign p1 to p2) but one can't do anything with a pointer to an incomplete type that one could not do to void*. Basically, from the compiler's perspective, a pointer to an incomplete type is a pointer-sized blob of bytes. It can be copied to or from other similar pointer-sized blobs of bytes, but that's it. the compiler can generate code to do that without having to know what anything else is going to do with the pointer-sized blobs of bytes.

Resources