C struct with file scope - c

Question: Are the tags on structures that are declared as static at file scope private to the file in the same way that the actual struct variable being declared will be? Or are the structure tags common across files?
This question came from a problem I am having with the MSVS2019 debugger showing me the wrong values and struct member names in some files. (You can read about the bug here, if you're interested: Visual Studio 2019 Debugger Issue) The files were all cloned from an original and all have something like this:
static struct MyPrivateData_s
{
char *szData[64];
} myData;
static int myCount;
The actual members of the struct vary from file-to-file and the values are quite different for each.
I know that variables that are declared static, but above any functions in a source file have "file scope" -- are global to that file only. I'm pretty certain the VS debugging system has a problem, but it made me wonder about how (or even if) the static storage class affects the structure tag.
If the tag is treated like the name of the struct and other variables, then it is private to the file. However, if the tag is treated differently, it may be triggering the VS bug. Remember, I am asking about only the structure tag, not the name of the actual structure variable. It would also be good to know how names from a typedef are affected by 'static' as well.
I have been trying to find the answer in all of the various C references I own and can find on line, but I (a) don't know the right question to ask and/or (b) am not understanding (or recognizing?) the answer when I find it. Hopefully a C guru can help me out.
FWIW, I think that anything following static at file scope should be restricted to the file where it is found. In fact, only below the point it is found in the file. That is how I have always coded and I have never encountered an issue before this debugger thing made me wonder about this. Thanks!
I think this may answer my question: Limit Struct Scope even though it does not explicitly use the term "tag". Instead, it appears to be calling the tag a "type", which, it becomes when prefixed by 'struct'. So static has no effect, but the fact that the tag appears in a C file and NOT in a common header means that the tag is private to the file. Sorry to have been a bother.

static does not affect structure tags or scope.
There is no scope beyond file scope (C 2018 6.2.1 1). Identifiers in different scopes can refer to the same object via linkage (6.2.2 1). If the different scopes are in different translation units, the identifiers can refer to the same object if they have external linkage.
Structure tags do not have linkage (6.2.2 6: “The following identifiers have no linkage: an identifier declared to be anything other than an object or a function;…”) Therefore, structure tags in different translation units refer to different entities.
This means that structure types in different translation units are different types. One would then wonder how the same structure can be used in different translation units. Per 6.2.7 1, structure types in different translation units may be compatible. For structures, compatibility largely requires identical definitions, with some allowances such as possibly omitting a tag.
The presence of static in a declaration (but not inside [ and ]) affects linkage (6.2.2 3) and storage duration (6.2.4 3) for objects and functions.
This answers this question:
Question: Are the tags on structures that are declared as static at file scope private to the file in the same way that the actual struct variable being declared will be? Or are the structure tags common across files?
static affects neither structure tags nor scope. It affects whether object and function identifiers can be related across translation units due to linkage, not scope.
typedef names are aliases.
It would also be good to know how names from a typedef are affected by 'static' as well.
C 2018 6.7.8 3 says “… A typedef declaration does not introduce a new type, only a synonym for the type so specified…” As above, static affects only objects and functions; it does not affect types or type names.

Try this instead:
struct _myprivdata_s_ {
char *szData[64];
};
typedef struct _myprivdata_s_ MyPrivateData_s;
static MyPrivateData_s myData;
static int myCount;

Related

Why is redeclaring functions legal in C?

void test(void){
//
}
void test(void); // <-- legal
int main(){
test();
int i = 5;
// int i; <-- not legal
return 0;
}
I understand that functions can have multiple declarations but only 1 definition,
but in my example the declaration is coming after the definition. Why would this be useful? Same cannot be done with block scoped variables.
I found this post which explains the behaviour in C++, not sure if the same applies to C:
Is a class declaration allowed after a class definition?
The underlying reason has to do with the way programs are typically compiled and linked on systems on which C is the "natural language", and the origin of the C language. The following describes conceptually how a program is generated from a collection of source files with static linking.
A program (which may or may not be written in C) consists of separate units — the C term is "translation units", which are source files — which are compiled or assembled to object files.
As a very rough picture such object files expose data objects (global variables) and executable code snippets (functions), and they are able to use such entities defined in other translation units. For the CPU, both are simply addresses. These entities have names or labels called "symbols" (function names, variable names) which an object file declares as "needed" (defined elsewhere) or "exported" (provided for use elsewhere).
On the C source code level the names of objects that are used here but defined elsewhere are made known to the compiler by "extern" declarations; this is true for functions and variables alike. The compiler conceptually generates "placeholder addresses" whenever such an object is accessed. It "publishes" the needed symbols in the object file, and the linker later replaces the symbolic placeholders with the "real" addresses of objects and executable code snippets when it creates an executable.
It does not hurt to declare the use of an external object or function multiple times. No code is generated anyway. But the definition, where actual memory is reserved for an object or executable code, can in general only occur once in a program, because it would otherwise be a duplicate code or object and create an ambiguity. Local variables don't have declarations like global variables; there is no need to declare their use far away from their definition. Their declaration is always also a definition, as in your example, therefore can only occur once in a given scope. That is not different for global variable definitions (as opposed to extern declarations) which can only occur once in the global scope.
Let's say you have these files:
// foo.h
#pragma once
void foo();
// helpers.h
#pragma once
#include "foo.h"
// ...
void bar();
// foo.c
void foo() {
// ...
}
#include "helpers.h"
// ...
Here, there is a declaration of foo after it's fully defined. Should this not compile? I think it's totally reasonable to expect #include directives to not have such effects.
I understand that functions can have multiple declarations but only 1 definition, but in my example the declaration is coming after the definition.
So?
Why would this be useful?
At minimum, it is useful for simplifying the definition of the language. Given that functions may be declared multiple times in the same scope, what purpose would be served by requiring the definition, if any, to be the last one? If multiple declaration is to be allowed at all -- and there is good reason for this -- then it is easier all around to avoid unnecessary constraints on their placement.
Same cannot be done with block scoped variables.
That's true, but for a different reason than you may suppose: every block-scope variable declaration is a definition, so multiple declarations in the same scope result in multiple definitions in the same scope, in violation of the one-definition rule.
A better comparison would be with file-scope variable declarations, which can be duplicated, in any order relative to a single definition, if present.

What is and isn't available to linked files in C?

As of late, I've been trying to work through opaque pointers as a programming concept and one of the main things I've had difficulties with is figuring out what is or isn't available to other files. In a previous question, I failed in trying to create an opaque pointer to a struct and even though the answer explained how to fix that, I still don't quite understand where I went wrong.
I think that if a struct is defined in file2.c, file1.c can use it if both files include header.h which includes a declaration of the struct? That doesn't entirely make sense to me. header.h is used by both files, so I can see how they would access the stuff in it, but I don't understand how they would use it to access each other.
When I started programming, I thought it was pretty straight forwards, where you have program files, they can't access anything in each other, and those program files can #include header files with definitions and declarations in them (e.g. file1.c has access to variables/functions/etc. defined in header.h). Turns out I was wrong and things are quite a bit more complicated.
So from what I can tell, func() defined in header.h can be used by file1.c without being declared in file1.c, if file1.c includes header.h. As opposed to var defined in header.h which needs to be declared in file1.c with the extern keyword? And I think if var is defined in file2.c, file1.c can use it if it extern declares it, even if neither file1.c nor file2.c include header.h?
I apologize if the previous paragraphs makes no sense, I'm having quite a bit of difficulty with trying to describe something that confuses me. By all means, please edit this if you are able to fix mistakes or whatnot.
Books and webpages don't seem to help at all. They end up giving me misconceptions because I already don't understand something and draw the wrong conclusions, or they bring up concepts that throw me off even more.
What I'm looking what I'm looking for is an answer that lays this all down in front of me. For example 'this can access this under these circumstances', 'this cannot access this'.
Functions defined in one .c file can use anything defined in another .c file except for those things which are marked as static. Functions and global variables which are marked as static cannot be accessed from other translation units.
Whether something is declared in a header file or not doesn't really matter--you can declare functions locally in the same .c file which calls them if you want.
Your question asks about “access” at several points, but I do not think that is what you mean to use. Any object or function can be accessed (for an object: read or written, for a function: called) from anywhere as long as a pointer to it is provided in some way). I think what you mean to ask is what names are available.
Any declaration that is outside of a function is an external declaration. In this use of “external” in the C standard, it simply means outside of a function. (That includes a function declaration or definition; although it is declaring or defining a function, it is not inside itself or any other function declaration, so it is outside of any function.)
Any identifier for an object or function with an external declaration has either internal linkage or external linkage. If it is first declared with static, it has internal linkage (and may be later declared with extern, but that will not change the linkage). Otherwise, it has external linkage.
Any identifier with external linkage will refer to the same object or function in all translation units (provided other rules of the C standard are satisfied—a program can do various things that will result in behavior not defined by the C standard).
Thus your answer is: The name of any object or function that is (a) defined outside of any function and (b) not initially declared with static is available to be linked to from other translation units.
Some technicalities that may be of interested:
What people think of as a variable is two things: an identifier (the name) and an object (a region of memory that stores the value).
Identifiers have scope, which is where they are visible in the source code. Identifiers declared outside functions have file scope; they are visible for the rest of the translation unit. Identifiers declared inside functions have various other types of scope: function scope, function prototype scope, and block scope.
You may sometimes seem people refer to global scope or external scope, but these are misnomers; they are not terms used in the C standard.
Linkage is related to scope and is sometimes confused with it, but linkage is a different concept: Two identical identifiers declared in different places can be made to refer to the same thing. Those identifiers have different scopes, notably one having file scope in one translation unit and the other having file scope in a different translation unit. Since each translation unit is compiled separately, the compiler generates code regarding each identifier separately. When the object modules are linked, then the code is bounded together, causing the separate identifiers to refer to the same object or function.
Identifiers can be declared with extern inside functions, but these can only link to objects or functions defined elsewhere; external definitions cannot appear inside functions.

C compiler ignores 'static' for declaration of struct

In C, if I declare a structure like so:
static struct thing {
int number;
};
and compile it (with gcc in this case), the compiler prints this warning:
warning: 'static' ignored on this declaration
[-Wmissing-declarations]
Why is this?
My intention in making the struct static would be to keep thing out of the global namespace so that another file could declare its own thing if it wanted.
You cant define the storage without defining the actual object.
static struct thing {
int number;
}obj1,obj2;
is ok and:
struct thing {
int number;
};
static struct thing x,y;
Struct tags (and typedef names) have no linkage, which means they are not shared across translation units. You might use the term "private" to describe this. It is perfectly fine for two different units to define their own struct thing.
There would only be a problem if it was attempted to make a cross-unit call of a function with external linkage that accepts a struct thing or type derived from that. You can minimize the chance of this happening by ensuring that functions with external linkage are only called via prototypes in header files (i.e. don't use local prototypes).
You can't use static on this way to control the linkage of a type like you could for a function or object, because in C types never have linkage anyway.
"Global namespace" isn't quite the term you want here. C describes names of objects and functions as having "external linkage" if the same name can be declared in different translation units to mean the same thing (like the default for functions), "internal linkage" if the same name can be redeclared within the same translation unit to mean the same thing (like declarations marked static), or "no linkage" when a declaration names a different object or function from any other declaration (like variables defined within a function body). (A translation unit, roughly speaking, is one *.c file together with the contents of the headers it includes.) But none of this applies to types.
So if you want to use a struct type that's essentially private to one source file, just define it within that source file. Then you don't need to worry about another usage of the same name colliding with yours, unless maybe somebody adds it to a header file that the source file was including.
(And just in case a C++ user comes across this Q&A, note the rules for this in C++ are very different.)

Same name structure with different definition in C

Is it allowed to use same name structure with different definitions in 2 different c files in the same project. For eg.
File1.c
typedef struct
{
unsigned int unVar;
} abc;
File2.c
typedef struct
{
int var;
} abc;
abc is used in both the files. When i compile these file as part of same project there are no errors, but i want to understand whether this is correct usage.
6.7.2.1 Structure and union specifiers
The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type,
within a translation unit.
Types are defined only within a translation unit, a .c file in this case.
There is no problem with defining two types with the same name in two different translation units.
However those two types are not compatible unless they follow the rules described in 6.2.7., p1. The types you defined are not compatible.
This is type definition. It is local for each .c file and there is no reason to get error. Definitions have to be made in header files and then you will not have such problem.
Symbols' names (variables', functions) must be unique within a translation unit.
A translation unit is a basic compilation unit for C and C++. It consists of a source file, along with all included files (either directly or indirectly).
In your case, you have two independent source files, each defining a struct; but they "can't see" each other, as they are within separate translation units.
You might get into trouble, however, during linking, if there are multiple symbols with the same name across target linking objects (as long as these symbols are exported, which can be modified with static keyword).
It is a correct usage to define two structs with the same name in two different *.c files because they are only valid for the current scope in the *.c where it is defined.
But further I would not recommend to do this to avoid any confusion of you and any other developer who has to work with two types of the same name that do doing other things.
Each definition is local to the file in which it appears. Since you compile the files separately, the compiler only sees one at a time. The linker binding the object files together does not verify type consistency, it only resolves symbols by name.
If you want to pass a st_localAscdData or a pointer to a st_localAscdData to a function from a different module, you must ensure consistency between the types declared in the different modules. This is the purpose of header files. Shared declarations belong in header files, that must be included in all modules that share a given type or function.
Global type consistency is not enforced by the C language, nor C++ to some extend, it is the programmers responsibility. Coding rules are guidelines to help programmers avoid pitfalls from this shortcoming.
You expect a redefined error (which will happen with cpp compiler) but it won't happen in C compiler.
This issue not just happen with structure but also with all kinds of variable.
I have make a question for this and have some detail and quality answer.
Does C have One Definition Rule like C++?

Why and when to use static structures in C programming?

I have seen static structure declarations quite often in a driver code I have been asked to modify.
I tried looking for information as to why structs are declared static and the motivation of doing so.
Can anyone of you please help me understand this?
The static keyword in C has several effects, depending on the context it's applied to.
when applied to a variable declared inside a function, the value of that variable will be preserved between function calls.
when applied to a variable declared outside a function, or to a function, the visibility of that variable or function is limited to the "translation unit" it's declared in - ie the file itself. For variables this boils down to a kind of "locally visible global variable".
Both usages are pretty common in relatively low-level code like drivers.
The former, and the latter when applied to variables, allow functions to retain a notion of state between calls, which can be very useful, but this can also cause all kinds of nasty problems when the code is being used in any context where it is being used concurrently, either by multiple threads or by multiple callers. If you cannot guarantee that the code will strictly be called in sequence by one "user", you can pass a kind of "context" structure that's being maintained by the caller on each call.
The latter, applied to functions, allows a programmer to make the function invisible from outside of the module, and it MAY be somewhat faster with some compilers for certain architectures because the compiler knows it doesn't have to make the variable/function available outside the module - allowing the function to be inlined for example.
Something that apparently all other answers seem to miss: static is and specifies also a storage duration for an object, along with automatic (local variables) and allocated (memory returned by malloc and friends).
Objects with static storage duration are initialized before main() starts, either with the initializer specified, or, if none was given, as if 0 had been assigned to it (for structs and arrays this goes for each member and recursively).
The second property static sets for an identifier, is its linkage, which is a concept used at link time and tells the linker which identifiers refer to the same object. The static keyword makes an identifier have internal linkage, which means it cannot refer to identifiers of the same name in another translation unit.
And to be pedantic about all the sloppy answers I've read before: a static variable can not be referenced everyhere in the file it is declared. Its scope is only from its declaration (which can be between function definitions) to the end of the source file--or even smaller, to the end of the enclosing block.
struct variable
For a struct variable like static struct S s;, this has been widely discussed at: What does "static" mean in C?
struct definition: no effect:
static struct S { int i; int j; };
is the exact same as:
struct S { int i; int j; };
so never use it. GCC 4.8 raises a warning if you do it.
This is because struct definitions have no storage, and do no generate symbols in object files like variables and functions. Just try compiling and decompiling:
struct S { int i; int j; };
int i;
with:
gcc -c main.c
nm main.o
and you will see that there is no S symbol, but there is an i symbol.
The compiler simply uses definitions to calculate the offset of fields at compile time.
This is struct definitions are usually included in headers: they won't generate multiple separate data, even if included multiple times.
The same goes for enum.
C++ struct definition: deprecated in C++11
C++11 N3337 standard draft Annex C 7.1.1:
Change: In C ++, the static or extern specifiers can only be applied to names of objects or functions
Using these specifiers with type declarations is illegal in C ++. In C, these specifiers are ignored when used
on type declarations.
See also: https://stackoverflow.com/a/31201984/895245
If you declare a variable as being static, it is visible only in that translation unit (if globally declared) or retains its value from call to call (if declared inside a function).
In your case I guess it is the first case. In that case, probably the programmer didn't want the structure to be visible from other files.
The static modifier for the struct limits the scope of visibility of the structure to the current translation unit (i.e. the file).
NOTE: This answer assumes (as other responders have indicated) that your declaration is not within a function.

Resources