#include <stdio.h>
volatile int isInit_STD;
volatile int isInit_STD;
int main() {
printf("v-%d-addr%x\n",isInit_STD,&isInit_STD);
isInit_STD = 1;
printf("v-%d-addr%x\n",isInit_STD,&isInit_STD);
return 0;
}
and the result is:
v-0-addr387fd040
v-1-addr387fd040
why volatile can repeat declare?
It turns out they are all the same, the same address.
If one of them deletes the 'volatile', that can't be compiled success.
I want to know the reason, looking forward to your reply.
The C standard says that (C17 6.7/4)
All declarations in the same scope that refer to the same object or function shall specify compatible types.
That means that as long as you use the same name, same type and same type qualifiers (volatile etc), you can declare the variable as many times as you like, and it will all refer to the same object.
And the opposite: if you use different types or qualifiers, but give the variable the same name, it is a constraint violation and the compiler must issue a diagnostic message.
Apart from what standard C allows, common sense states that we should avoid having multiple declarations of the same variable when possible. Good program design practices also state that we should avoid declaring objects at file scope, or if that's not possible, avoid using external linkage ("globals") and instead enforce interal linkage by declaring the variable static.
I want to know the reason
You can repeat a declaration of anything as many times as you want, as long as the declarations are "the same". It's not specific to volatile, just there has to be no conflict. All declarations refer to the same thing.
The following is an actual whole .c file:
// 3 declarations of function main.
int main();
int main();
int main();
// 3 declarations of struct A type.
struct A;
struct A;
struct A;
// 3 declarations of variable a
extern volatile int a;
extern volatile int a;
extern volatile int a;
// 3 declarations of variable b
int b;
int b;
int b;
// 3 declarations of variable c
volatile int c;
volatile int c;
volatile int c;
// example with conflicts:
int d;
// volatile int d; // error - conflict with above, d is not volatile
// static int d; // error - conflict with above, d is not static
extern int d; // Fine! Stuff declared at file scope is implicitly extern.
Related
Why must a struct member always have an Identifier? The answer of course is because that is how the language is defined, but I'd like to understand the reason behind it.
typedef union {
int a;
struct {
int a; //Why is an identifier necessary here?
int b;
} s;
} u;
There are grammar complications here. Consider int a, b, c;. That declares three objects. int a, b; declares two, and int a; declares one. So how many should int; declare? When a declaration with no declarator appears in other contexts, it does not declare any object. For example, struct foo { int x; }; defines the type struct foo, but it does not declare an object of that type.
We could make an exception for declarations in structures, and say that, if they have no declarators, then they declare one unnamed member. But then we are introducing another special case in to the grammar. Then struct foo { int x; };, which has no declarator, would declare a member object of type struct foo when it appears inside a structure definition, but it would not declare any object when it appears outside of a structure definition.
So this adds complications to the language. And it is not necessary; somebody who wants a member in a structure can always give it a name and can choose a name that will not interfere with other code.
Actually, bit field members do not need a name, at least according to gcc -std=c99 -Wall -Wextra -pedantic, which gives no warning when compiling this code:
struct Foo
{
char x;
unsigned :8;
};
If you really don't want to have an identifier for a member that isn't a bit-field, you can name it something like _reserved0 to explicitly show that this is just reserved space that you don't want to access from your code.
I don't know the opinions of the people who wrote the C standard. Maybe they were thinking a struct member without a name was almost always a bug (i.e. the programmer forgot the name), and they wanted to help people catch those bugs, but they made a few exceptions to the rule.
//Why is an identifier necessary here?
This a is distinct from the a outside the structure. The compiler needs to know which one you want to access
If you use distinct names you can use anonymous structure in your union
typedef union {
int a;
struct {
int b;
int c;
};
} u;
u foo(int x, int y, int z)
{
u un;
u.a = x;
u.b = y;
u.c = z;
}
main.h
struct tagname {
int m1;
int m2;
};
main.c
#include "main.h"
int main(void) {
struct tagname d1;
d1.m1 = 7;
struct tagname {
float s1;
float s2;
float s3;
};
struct tagname e1;
e1.s1 = 0;
}
I am using XC16 v1.60 (which I believe uses GCC v4.5.1 as the base) with -Wall, -Wextra, -Wshadow, and a host of other flags which I don't think are relevant, and I would have thought (hoped?) that the compiler would issue a warning here. What am I missing?
Edit: Apologies, I have updated the question with the extra detail desired.
C allows new declarations of identifiers in new scopes. When you declare a function or start a compound statement with {, that starts a new scope. Iteration and selection statements also start new scopes. Inside a new scope, a new declaration of an identifier generally hides the previous declaration. Since this is legal C, the compiler allows this.
In GCC 4.5.1, the documentation for -Wshadow says it warns “whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.” A structure tag is not a local variable or a built-in function.
Incidentally, the return type of main should be int except in special situations; using int main(void) or int main(int argc, char *argv), not void main(void).
The way I understand extern is that we are able to declare a variable anywhere in a program and use it, but we can just define it once. I am getting an error in the following program.
hello.c
#include <stdio.h>
#include "function.h"
extern int c;
int main()
{
int c;
c=10;
printf("%d\n",c);
printExternValue();
return 0;
}
function .h
void printExternValue();
function .c
#include "function.h"
#include "stdio.h"
extern int c;
void printExternValue()
{
printf("%d\n",c);
}
I expect this program to print out:
10
10
But it's not doing so since it's giving an error. I re-declared the variable c in the function.c file with the intention of using the value that is stored in the so called external storage.
Error: function.c:(.text+0x6): undefined reference to `c'
I am currently reading a PDF file from tutorialspoints which I think to be very redundant since the intention of creating a variable with the aggregate extern is useless. The right way this should be done is that they define the variables outside the function is that right?
#include <stdio.h>
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main ()
{
/* variable definition: */
int a, b;
int c;
float f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c);
f = 70.0/3.0;
printf("value of f : %f \n", f);
return 0;
}
Variable declread as
extern int c;
is an external declaration that potentially requires an external definiton. "External" in this case means "located outside of any function". Your c declared locally in main() does not fullfill that role.
Since you are using that externally declared variable c in your code you have to define it and define it only once.
You need
int c;
or
int c = 0;
or
extern int c = 0;
it one of your implementation files, at file scope. All of these are definitions. Any of them will define your variable.
Define your variable once in one of your files (to reserve space),
int c = 0;
Declare your variable references everywhere else (in all of your other files) (to reference said space),
extern int c;
But that could be confusing, so name them indicative of the 'global' use,
int glob_a, glob_b;
int glob_c;
float glob_f;
And declare your variable references everywhere else,
extern int glob_a, glob_b;
extern int glob_c;
extern float glob_f;
But you really want to avoid littering you namespace, so when you have a collection of globals, declare a struct that contains them (in a header file probably called globals.h),
typedef struct globals_struct {
int a, b;
int c;
float f;
} globals_t;
And once (in your file main.c that declares main()), you define the struct,
#include globals.h
globals_t globs;
And everywhere else, reference the space,
#include globals.h
extern globals_t globs;
Often, you will see a stanza such as this, where MAIN is only declared in one file,
#ifndef MAIN
extern globals_t globs;
#else
globals_t globs;
#endif
Use your globals,
int my_a = globs.a;
int my_b = globs.b;
int my_f = globs.f;
Notice how you have avoided needless namespace pollution?
Because extern just tells the compiler (actually the linker) that a variable is being defined elsewhere and needs to be linked against.
I have the following piece of code where I define a couple of external (global) variables after the place in code where I need to use them.
In order to do so I use the keyword extern to declare them without reserving storage for them.
int main(int argc,char *argv[])
{
extern int a;
extern double b;
/* ...use the variables somehow... */
{
int a = 10;
static double b = 2.0;
if I do so, the compiler complains that I'm defining the b variable to be static (thus with internal linkage),when before I declared it to be extern.
But if I invert the order and define it before using it and declare it inside main ( which is otpional I know...) everithing is fine.
static double b = 2.0;
int main(int argc,char *argv[])
{
extern int a;
extern double b;
/* ...use the variables somehow... */
{
int a = 10;
so what if I'd like to use an external private variable (i.e. with internal linkage) before I define it? is it forbidden and why?
The extern keyword tells the compiler that the variable we refer to is located in a different translation unit (another source file basically), while the static keyword means that the variable (in the case of global variables) is local to the current translation unit and cannot be seen in other source files, so it makes no sense to use the two keywords together.
Once you have declared b as global in the same file, it is visible in main and there is no need to declare it again, you just can use it.
If on the other hand it is declared in a different translation unit as a global variable, the extern keyword becomes necessary.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I share variables between different .c files?
If I have two source files, and one header: file1.c, file2.c, and header.h, and:
--header.h--
int i;
--file1.c--
#include <header.h>
i = 10;
int main() {
func();
return 0;
}
--file2.c--
#include <header.h>
void func() {
printf("i = %d\n", i);
return;
}
I get the warning that i defaults to an int. What could I do if I want to have i as a float for instance?
Make it
extern int i;
in the header and
int i = 10;
in file1.c.
The warning means that for the (incomplete) declaration i = 10; in file1.c, the "implicit int" rule is applied, in particular, that line is interpreted as a declaration (since an assignment cannot appear outside function scope).
You have a couple of errors in your code. The first is that you define the variable i in the header file, which means that it will be defined in all source files that include the header. Instead you should declare the variable as extern:
extern int i;
The other problem is that you can't just assign to variables in the global scope in file1.c. Instead it's there that you should define the variable:
int i = 10;
Declare it as extern in the header (this means memory for it is reserved somewhere else):
/* header.h */
extern int i;
Then define it in only one .c file, i.e. actually reserve memory for it:
/* file1.c */
int i = <initial value>;
In the header use
extern int i;
in either file1.c or file2.c have
int i = 20;
If you want float just change int to float
In 99.9% of all cases it is bad program design to share non-constant, global variables between files. There are very few cases when you actually need to do this: they are so rare that I cannot come up with any valid cases. Declarations of hardware registers perhaps.
In most of the cases, you should either use (possibly inlined) setter/getter functions ("public"), static variables at file scope ("private"), or incomplete type implementations ("private") instead.
In those few rare cases when you need to share a variable between files, do like this:
// file.h
extern int my_var;
// file.c
#include "file.h"
int my_var = something;
// main.c
#include "file.h"
use(my_var);
Never put any form of variable definition in a h-file.