I was making a simple C program
#include<stdio.h>
static int a;
a = 5;
int main()
{
printf("%d",a);
return 0;
}
Compiler error: "non static declaration of 'a' follows static declaration"
What does this error mean?
what this error log means?
It is a little tricky: what looks like an assignment
a = 5;
is treated as
int a = 5;
due to an old C rule that allowed you to declare int variables and int-returning functions without specifying their type explicitly (this is definitely not a good idea in the modern version of C).
Note that this is treated as a declaration with an implicit int only in the scope outside a function body.
You can fix it by combining the declaration with initialization, like this:
static int a = 5;
Outside a function you can only declare variables, you cannot have actual code statements.
a = 5;
is being interpreted as another declaration, when your intent I think is to write some code.
instead declare and initialise a at the same time
static int a = 5;
Your first declaration of a is static (ahas internal linkage).
The second declaration is not static (a has external linkage). Yes, a = 5; is a declaration with implicit type int in this case.
Both do not agree.
Btw. for functions this would be o.k. because the second declaration would "inherit" the internal linkage.
We cannot write any assignment statement globally. For example:
#include <stdio.h>
static int i=10; //Initialization statement
i=25; //Assignment statement
int main(){
printf("%d",i);
return 0;
}
Output: Compilation error
Note: Assigning any value to the variable at the time of declaration is known as initialization while assigning any value to variable not at the time of declaration is known assignment.
You can't set value as you did it: a = 5; before main(...). See code below:
static int a = 1; //default = 0;
int main()
{
printf("a = %d\n", a);
a = 2;
printf("a = %d\n", a);
return 0;
}
Output:
a = 1
a = 2
A = 5 is considered as an attempt to create another variable called a. You should put the = 5 after static int a.
Static int a = 5;
Just a little modification to your code will help you to understand it.
#include<stdio.h>
//static int a; //comment this statement
a = 5;
int main()
{
printf("%d",a);
return 0;
}
now compile this code [please enable your compiler's warnings]
Then you will get a warning something like this
data definition has no type or storage class [enabled by default]
So now try to understand this warning it means that compiler treat statement a=5 as a definition but without data type. But compiler unable default data type that is int.
so this statement is equivalent to
int a=5;
Related
This question already has answers here:
Why are we not allowed to have assignment statements in the file scope in C?
(2 answers)
Closed 3 years ago.
I have some questions about global section rules in C, I'll state my question in cases.
Case 1: Why is this not allowed, says redefinition.
int a = 4;
a = 5;
int main()
{
printf("Hello World");
return 0;
}
Case 2: Why is this not allowed.
int a;
int b;
a = b;
int main()
{
printf("Hello World");
return 0;
}
Case 3: Why is this not allowed.
int a;
a = 4;
a = 5;//if this is removed, it works fine
int main()
{
printf("Hello World");
return 0;
}
Case 4: Why is this allowed, but test is not printed.
int test(void)
{printf("test");}
test();
int main()
{
printf("Hello World");
return 0;
}
Thanks.
case 1:
because you're doing assignment outside of function.
case 2:
because you're doing assignment outside of function.
case 3:
because you're doing assignment outside of function.
The first assignment is considered as initialization that's why it's fine.
case 4:
because you're just declaring test() function again with different signature if the default is not int.
and, You're not calling test() from the main function.
int test(void)
{
printf("test");
return 0; // it can cause a warning if missing
}
int main()
{
printf("Hello World");
test();
return 0;
}
The "global" section is actually compiled into a segment in the binary executable that is then loaded into memory when you program runs.
The exact details of how it works depend on the specific OS you build for, but basically, the only thing that you can do in the global section is declare or define initialized or uninitialized variables.
In your case 1 you fist define an initialized global variable a, but then you try to assign a new value to it.
This is actual code that needs to run after the program is loaded, so it has to be inside a function!
Your case 2 is almost same as one: you define 2 uninitialized global variables, but then you add code to manipulate them.
This code has to be inside a function!
case 3 is more interesting:
If you try to compile it, you should get warnings like this:
warning: data definition has no type or storage class a = 4;
warning: type defaults to ‘int’ in declaration of ‘a’ [-Wimplicit-int]
The compiler thinks you are defining a variable without a type, but with a value, so it assigns a default type of int to it.
Notice this will also work:
int a;
int a = 4;
And will remove the warnings.
The compiler will treat the first line as declaration only (an intent to have a variable named a, but not the actual variable) and the second line will be the actual definition, creating the variable and initializing it with value 4.
Keep in mind, that in C, initializing a variable, and assigning value to it are two slightly different things with different rules.
Finally case 4 is very simple:
"test" is not printed because you never call the function test().
int test(void)
{printf("test");}
test();
This code is same as this code:
int test(void);
int main() {
...
}
int test(void)
{
printf("test");
}
What you did with the last line in you example is simply declare a function.
You told the compiler that somewhere in your code exists a function named test that expects no parameters and returns an integer value. (if you do not specify return type for function C default to int!)
Anything you write int the global scope the compiler will try to interpret as a declaration (you tell the compiler something exists) or a definition (you tell the compiler what something is).
If it can not interpret your statement this way you will get a compilation error.
You can not run code from global scope in C.
When I try to compile this I'm being told by gcc that I have conflicting types for pack_cui(C).
I don't see how I could be getting conflicting types as I know I'm passing in a char*. I'm new to C so I'm sure I'm missing something obvious.
int main(){
char* C = malloc(sizeof(char) * 4);
C[0] = 1;
C[1] = 2;
C[2] = -1;
C[3] = 4;
pack_cui(C);
return 0;
}
unsigned int pack_cui(char* C){
unsigned int new_int = 0;
unsigned int i;
for(i = 0; i < 4; i++){
new_int = new_int | (unsigned int)(signed int)C[i];
if(i != 3) new_int = new_int << 8;
}
return new_int;
}
The error I received was
hw12.c:17:14: error: conflicting types for ‘pack_cui’
unsigned int pack_cui(char* C){
^
hw12.c:13:5: note: previous implicit declaration of ‘pack_cui’ was here
pack_cui(C);
Add a prototype for pack_cui before main:
unsigned int pack_cui(char* C);
Otherwise, when the compiler sees the call to pack_cui, it has to guess the type, and in this case it guesses wrong.
When you call an undeclared function, the C89 standard mandates an implicit declaration. This declaration would be:
int pack_cui();
The () is not the same as (void), it indicates that the function takes an unspecified number of arguments, whereas (void) means zero. This is left over from pre-ISO/ANSI C, back in the K&R days.
You don't want that, because that is the wrong declaration. Create your own declaration at the top, above main():
unsigned pack_cui(char *);
Move the definition of pack_cui from below the main function, to above the main function. Or set up and include a header file that declares pack_cui.
Also, once this is done, recompile with warnings enabled, so that you catch the other issue with your code:
$ gcc -Wall foo.c
You should include stdlib.h, at least.
When you call a C function, whether it's one of your own or one declared by the standard library, you must have a visible declaration of that function so the compiler knows how to generate the code to call it. That declaration should be a prototype, i.e., a declaration that specifies the types of the function's parameters. A function definition (with the { ... } containing the code that implements the function) provide a declaration.
In your example, no declaration of pack_cui is visible at the point of the call; it's not defined until later.
You can fix this by moving the definition of pack_cui above the definition of main, or by adding a "forward declaration" and leaving the definitions where they are.
The latter would look like this:
unsigned int pack_cui(char* C); /* a declaration, not a definition */
int main(void) { /* definition of main */
/* ... */
}
unsigned int pack_cui(char* C) { /* definition of pack_cui */
/* ... */
}
Either approach is acceptable.
For much the same reason, you need to provide a declaration for the malloc function. You should do this by adding
#include <stdlib.h>
to the top of your source file.
I am reading a book on the C language ('Mastering C'), and found the topic on scope resolution operator (::) on page 203, on Google Books here.
But when I run the following code sample (copied from the book), the C compiler gives me an error. I searched on the internet but I am unable to find any reference to a scope resolution operator in C.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a);
printf("%d\n", ::a);
return 0;
}
So if I want to access a global variable then how could I do that from within the main() function ?
No. C does not have a scope resolution operator. C++ has one (::). Perhaps you are (or your book is) confusing C with C++.
You asked how you could access the global variable a from within a function (here main) which has its own local variable a. You can't do this in C. It is lexically out of scope. Of course you could take the address of the variable somewhere else and pass that in as a pointer, but that's a different thing entirely. Just rename the variable, i.e. 'don't do that'
No, namespaces are a feature of C++.
It is, however, possible to refer to global a in your example.
You can achieve this by using the extern keyword:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
printf("%d\n",a);
{ // Note the scope
extern int a; // Uses the global now
printf("%d\n", a);
}
return 0;
}
That's a bit tricky, though. It's bad style. Don't do that.
:: operator is available in C++ not C. If you wanted to access the global variable, use
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a); //prints 10
{
extern int a;
printf("%d", a); //prints 50
}
return 0;
}
Or you could use a pointer which holds the address of the global variable a and then dereference the pointer if you want to print the value of the global variable a.
No (the :: operator is C++ specific). In C, if you use the same identifier in different overlapping scopes (say, file scope a and block scope a), the block scope identifier shadows the file scope identifier and there is no way to refer to the shadowed identifier.
It is generally best programming practice to avoid shadowed variables. Many lint type programs can warn about this situation.
In plain C, there is no scope resolution. You have to name your variables differently.
That means that all variables a below are different ones:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
{
int a = 20;
int i;
for (i = 0; i < 10; i++) {
int a = 30;
}
}
return 0;
}
You may use pointers to access and edit global variables in C.
#include <stdio.h>
#include <stdlib.h>
int a;
a=78;
int *ptr=&a; //pointer for global a
int main()
{
int a=0;
printf("%d",a); //Prints 0 as local variable
printf("%d",*ptr);
ptr=30; //changes the value of global variable through pointer
printf("%d",*ptr); //Now it prints 30
return 0;
}
It entirely depends on what kind of compiler you're using to execute your code.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d\n",a);
printf("%d\n", ::a);
return 0;
}
Try running this code in Turbo C compiler, and you will get the results.
Now, regarding the C book that you're following, the examples codes present in the book must be in terms with Turbo C/C++ compiler and not the gcc compiler.
I have this source of a single file that is successfully compiled in C:
#include <stdio.h>
int a;
unsigned char b = 'A';
extern int alpha;
int main() {
extern unsigned char b;
double a = 3.4;
{
extern a;
printf("%d %d\n", b, a+1);
}
return 0;
}
After running it, the output is
65 1
Could anybody please tell me why the extern a statement will capture the global value instead of the double local one and why the printf statement print the global value instead of the local one?
Also, I have noticed that if I change the statement on line 3 from
int a;
to
int a2;
I will get an error from the extern a; statement. Why does not a just use the assignment double a=3.4; ? It's not like it is bound to be int.
It's not like it is bound to be int.
Actually, it is. In the declaration
extern a;
The (implicit) type of a is indeed int. Declarations in C without any specific type always default to int.
In addition, an extern declaration cannot refer to a local variable (even one declared within the same function).
The line
extern a;
shadows the previous declaration. Until the scope where this is declared ends, this declaration takes precedence over the definition
double a = 3.4;
Can anyone please tell me is there any special requirement to use either EXTERN or GLOBAL variables in a C program?
I do not see any difference in a program like below, if I change from gloabl to extern.
#include <stdio.h>
#include <stdlib.h>
int myGlobalvar = 10;
int main(int argc, char *argv[])
{
int myFunc(int);
int i;
i = 12;
myGlobalvar = 100;
printf("Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
i = myFunc(10);
printf("Value of passed value : %d\n",i);
printf("again Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
system("PAUSE");
return 0;
}
int myFunc(int i)
{
i = 20 + 1000;
//extern int myGlobalvar;
myGlobalvar = 20000;
// printf("Value of passed value : %d",i);
return i;
}
If uncomment extern int myGlobalvar, the value does not change.
Is there any correct difference between both?
Can anyone please correct me?
The keyword extern means "the storage for this variable is allocated elsewhere". It tells the compiler "I'm referencing myGlobalvar here, and you haven't seen it before, but that's OK; the linker will know what you are talking about." In your specific example it's not particularly useful, because the compiler does know about myGlobalvar -- it's defined earlier in the same translation unit (.c or .cc file.) You normally use extern when you want to refer to something that is not in the current translation unit, such as a variable that's defined in a library you will be linking to.
(Of course, normally that library would declare the extern variables for you, in a header file that you should include.)
From Here:
A global variable in C/C++ is a variable which can be accessed from any module in your program.
int myGlobalVariable;
This allocates storage for the data, and tells the compiler that you want to access that storage with the name 'myGlobalVariable'.
But what do you do if you want to access that variable from another module in the program? You can't use the same statement given above, because then you'll have 2 variables named 'myGlobalVariable', and that's not allowed. So, the solution is to let your other modules DECLARE the variable without DEFINING it:
extern int myGlobalVariable;
This tells the compiler "there's a variable defined in another module called myGlobalVariable, of type integer. I want you to accept my attempts to access it, but don't allocate storage for it because another module has already done that".
Since myGlobalvar has been defined before the function myFunc. Its declaration inside the function is redundant.
But if the definition was after the function, we must have the declaration.
int myFunc(int i)
{
i = 20 + 1000;
extern int myGlobalvar; // Declaration must now.
myGlobalvar = 20000;
printf("Value of passed value : %d",i);
return i;
}
int myGlobalvar = 10; // Def after the function.
In short: GLOBAL variables are declared in one file. But they can be accessed in another file only with the EXTERN word before (in this another file). In the same file, no need of EXTERN.
for example:
my_file.cpp
int global_var = 3;
int main(){
}
You can access the global variable in the same file. No need to use EXTERN:
my_file.cpp
int global_var = 3;
int main(){
++global_var;
std::cout << global_var; // Displays '4'
}
Global variable, by definition, can also be accessed by all the other files.
BUT, in this case, you need to access the global variable using EXTERN.
So, with my_file.cpp declaring the global_var, in other_file.cpp if you try this:
other_file.cpp
int main(){
++global_var; // ERROR!!! Compiler is complaining of a 'non-declared' variable
std::cout << global_var;
}
Instead, do:
int main(){
extern int global_var;//Note: 'int global_var' without 'extern' would
// simply create a separate different variable
++global_var; // and '++global_var' wouldn't work since it'll
// complain that the variable was not initiazed.
std::cout << global_var; // WORKING: it shows '4'
}
myGlobalVar as you've defined it is a global variable, visible from all the places in your program. There's no need declaring it extern in the same .c file . That is useful for other .c files to let the compiler know this variable is going to be used.