2

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.

Community
  • 1
  • 1
Jacquen
  • 986
  • 8
  • 18
  • 8
    It's a data type, it's only visible in the compilation unit where it's defined. That's why you put it in a header if you want to share it accross compilation units. – nicomp Aug 29 '18 at 22:43
  • @nicomp: so you're saying that a struct declaration, or any data type declaration for that matter, already has the behavior I want, that of not being in the global namespace, without the use of 'static', as long as it's not put in a header? – Jacquen Aug 29 '18 at 22:51
  • 3
    The word `static` applies to the variable declared with it, not the type. For example: `static struct timeval startw`, here `startw` would be considered static not `timeval`. [Reference](https://stackoverflow.com/questions/22270950/c-static-struct) – whatthefish Aug 29 '18 at 22:55
  • Yes, I am saying that. You can't 'extern' a user-defined data type. – nicomp Aug 29 '18 at 23:02
  • Also, there is no namespace in C as far as I know, but someone will scurry off to the xyz standards document and send me straight. – nicomp Aug 29 '18 at 23:03
  • @nicomp "Namespace" in C just refers to the idea that normally visible object/function/typedef names, the tags following a `struct` or `enum` keyword, labels in a function, and struct members are separate classifications of identifiers that do not collide. – aschepler Aug 29 '18 at 23:06
  • >static struct { int number; }thing; Something like this would be valid. – Leon Trotsky Aug 29 '18 at 23:21
  • 1
    Is thing being declared in a header file? – jwdonahue Aug 29 '18 at 23:55
  • Another suggestion would be to use `typedef struct { int number; } thing;`. – jxh Aug 30 '18 at 00:05
  • As far as I can tell the standard doesn't define the behaviour of the OP code. There isn't any text like "`static` is ignored except where it has defined meaning". So it would be undefined behaviour by omission. – M.M Aug 30 '18 at 00:42
  • @M.M I'm not sure this would fall under the "omission of any explicit definition of behavior" clause. The Standard says things about effects of the keyword on the objects or function declared by a declaration containing it, and for this declaration the number of objects and functions declared happens to be zero. I note clang++, g++, and MSVC all agree the code is acceptable but worth a warning. – aschepler Aug 30 '18 at 01:01
  • @aschepler this is a C question. Can you indicate which clause would cover the behaviour of `static` in this code? – M.M Aug 30 '18 at 03:17
  • @M.M Oops, I meant clang, gcc, and MSVC in C mode (which I did use for the test, just typed the wrong names here). And no, I can't really quote anything that directly supports my interpretation. I'm just vaguely unconvinced that this is a "behavior" (though certainly "behavior" can cover some aspects of translation, not just execution). – aschepler Aug 30 '18 at 03:43
  • @M.M Or actually, there's 6.7/6 "The declaration specifiers consist of a sequence of specifiers that indicate the linkage, storage duration, and part of the type of the entities that the declarators denote." The specifiers in that declaration do indicate the linkage and storage duration, and influence the type, of all zero declarators. This is considered okay for at least the "part of the type" phrase... – aschepler Aug 30 '18 at 03:52
  • @aschepler That's what I said. – nicomp Aug 30 '18 at 09:32

3 Answers3

6

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;
0___________
  • 60,014
  • 4
  • 34
  • 74
4

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).

M.M
  • 138,810
  • 21
  • 208
  • 365
1

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.)

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • I am amazed you attempted to cover this without mentioning scope. Linkage only applies to objects, not types. The OP is trying to hide a type, therefore they must control its scope. – jwdonahue Aug 29 '18 at 23:59
  • @jwdonahue scope has nothing to do with this question. Also your claim "linkage only applies to objects" is incorrect; it applies to objects and functions. Nor is it clear why you try to point out that linkage doesn't apply to types, since that fact is the basis of most of this answer. Maybe you could write your own answer – M.M Aug 30 '18 at 00:40
  • @jwdonahue Sure, in some cases it might help to define a struct within a function. But that's not an option if you want to use the struct in multiple functions and/or in parameter or return types of static functions. – aschepler Aug 30 '18 at 00:47