Just started with K & R and on the 2nd chapter, there is the line:
Declarations list the variables to be
used and state what type they have and
perhaps what their initial values are.
So:
int x = 42 is a definition.
and int x is a declaration but also a definition since every definition is a declaration.
But when we assign an intial value like K & R say, doesn't that make the declaration a definition?
You confuse two things:
A declaration states (declares) what an object's* type, name and scope is
A definition defines what a object's content is
* object as in: variable, function etc., not an OOP object.
A definition is hence very often also a declaration, since you cannot define what is in an object when you do not state what the type of the object is. Easiest to remember is just: "Every definition is a declaration, but not every declaration is a definition"
For variables
There is only 1 way to declare without defining the variable:
extern typeX variable_name
This tells the compiler that there is a variable called variable_name with type typeX, but not where to get it.
Every other way to declare a variable is also a definition, since it tells the compiler to reserve space for it and perhaps give it an initial value.
The difference is much clearer in structs and functions:
For Structs
A declaration:
struct some_struct{
int a;
int b;
}
This declares some_struct to the compiler with a and b as struct variables both with type int.
Only when you define them space is reserved and you can use them:
void foo(){
struct some_struct s;
s.a = 1; // For this to work s needs to be defined
}
For functions:
The difference is much more clear
declaration:
// This tells the compiler that there is a function called "foo" that returns void and takes void arguments
void foo();
A definition could be like the one above (in the struct part)
Basically you can say that a declaration simply tells the compiler that there is somewhere a variable with that name and type. It does produce any code, and in C, this has to be done with the extern keyword on variables. Function prototypes (without implementation) are also mere declarations, and don't need the extern keyword, but you can still provide it.
A definition produces code, e.g. allocates memory on the stack or heap for a variable, or the body for methods.
In that sense, both of your statments are definitions, and any definition is also a delcaration.
I think that might by a mistake by K&R...
Related
I am trying to understand a C program and here is the following lines that I don't understand them:
static A B(float* array, int numel);
static int C(D_TYPE* array, int numel);
Is variable A declared to be a scalar and B is a matrix? Why there is no "," between A and B? Is array declared as a pointer?
In the second line, the variable "D_TYPE" is appeared for the first time. I assumed that this variable is imported from the header files, but I couldn't find it inside any other included files.
The code tells that:
Somewhere (rest of the code, header file, whatever) a type 'A' is (or should be) declared. Can be anything from a custom data structure (struct) or a numeric type defined via a typedef.
B is a function (well actually a prototype of a function) that returns an 'A'. B takes a pointer to float (that by the name is implied to be an array, which in C are almost the same thing) and an integer as parameters. This is somewhat standard in C when you have to pass an array to a function.
C is a function's prototype that states that function C returns an integer. As arguments it takes a pointer to 'D_TYPE', which, again is a type that is or should be defined somewhere, and an integer.
static is used in both case probably to limit the visibility of the two functions only to the header file, which is unusual.
Personal considerations: names like 'a' or 'b' should be used only as argument values for very simple (not to say stupid) cases, like a Max(a, b) function or something similar.
In your code you have 2 function declarations, both B and C are names of functions.
The first function returns a variable of type static A and takes as arguments a float* and an int
The second one returns a variable of type static int and takes as arguments a D_TYPE* and an int, you probably have D_TYPE defined somewhere in your code or in a header file somewhere. We don't know what this D_TYPE is but it could be either a struct, a #define or a typedef, this is the same for A.
These are only the declarations of the functions, somewhere in your code you will have
static A B(float* array, int numel){
//some code
}
and
static int C(D_TYPE* array, int numel){
// some code
}
and these would be the definitions of the two functions
There isn't a , between A and B because that's just an error in C (programming language not the function), it would be the same as writing
static int , C(D_TYPE* array, int numel);
in your second declaration and this is, of course, wrong
static A B(float* array, int numel);
static is storage class, refer storage classes in c
A is a return type , that can vary from a primitive int , char to any complex struct type or even a pointer
B is name of fuction
static int C(D_TYPE* array, int numel);
here C is a function and D_TYPE is some type which might be typedefed some where in your files
You do not declare any variables here.
Both are function prototypes and A is the return type of the function B.
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 3 years ago.
There is a code snippet as below,
int var1;
extern int var2;
It is a multiple choice.
The answer is, First statement declares and defines var1, but second statement only declares var2.
But I think it is supposed to be "Both statements only declare variables, don’t define them."
Which one is correct?
This might help. source
Declaration of a variable is for informing to the compiler the
following information: name of the variable, type of value it holds
and the initial value if any it takes. i.e., declaration gives details
about the properties of a variable. Whereas, Definition of a variable
says where the variable gets stored. i.e., memory for the variable is
allocated during the definition of the variable.
In C language definition and declaration for a variable takes place at
the same time. i.e. there is no difference between declaration and
definition. For example, consider the following declaration
int a;
Here, the information such as the variable name: a, and data type:
int, which is sent to the compiler which will be stored in the data
structure known as symbol table. Along with this, a memory of size 2
bytes(depending upon the type of compiler) will be allocated.
Suppose, if we want to only declare variables and not to define it
i.e. we do not want to allocate memory, then the following declaration
can be used
extern int a;
In this example, only the information about the variable is sent and
no memory allocation is done. The above information tells the compiler
that the variable a is declared now while memory for it will be
defined later in the same file or in different file.
The answer depends on several factors.
If these declarations
int var1;
extern int var2;
are block scope declarations then the first declaration is also a definition and the second declaration is just a declaration without a definition. The variable var1 is not initialized that is it has an indeterminate value.
If these declarations are declarations of the file scope then whether the first declaration is a definition is defined by whether the declaration has an external definition.
If the declaration does not have an external definition then this declaration named as tentative definition is a definition and have an implicit initializer equal to 0.
As for the second declaration then again whether it is a definition depends on whether there is an external definition or not. If there is no external definition then the linker can either create the definition or issue an error.
In C a declaration with the file scope is also a definition when either it has an initializer or it is a tentative definition without an external definition.
Actually, the extern keyword extends the visibility of the C variables and C functions.
Declaring vs Defining a variable?
Declaration of a variable/function simply declares that the variable/function exists somewhere in the program but the memory is not allocated for them.
Snippet 1:
extern int var;
int main(void)
{
var = 10;
return 0;
}
Snippet 1 throws an error in compilation. Because var is declared but not defined anywhere. Essentially, the var isn’t allocated any memory. And the program is trying to change the value to 10 of a variable that doesn’t exist at all.
Snippet 2:
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
Supposing that "somefile.h" has the definition of var. Snippet 2 will be compiled successfully.
If we declare an object or function without defining it, how are we allowed to use it before its declaration and how are we not allowed to use it before its declaration ? (For a similar question using a forwarded declared structure tag before its definition, basically how we are allowed to use an incomplete type and how not, see https://stackoverflow.com/a/45725061/3284469)
Does it matter if the declaration appears in file scope or block scope?
Does it matter if its definition appears in the same or a different translation unit?
For example
extern int i;
(what can we do with i here?)
(what can't we do with i here?)
int A = i+3; // error: initializer element is not constant. This is an error not due to forward declaration of int i
int i = 3;
void fun();
(what can we do with fun here?)
(what can't we do with fun here?)
void fun(){};
Declaring an object is a promise to provide a definition at some other place. Once you declare a function or an external variable, from that point on you are allowed to do anything that you would be allowed to do to a function or a variable that you have defined.
The scope of the declaration has no effect on what you can do, only on the location in code where you can do it.
In most cases, code translator requires all external references to be satisfied at the time the code is linked. Otherwise, you get a linking error.
One exception to this rule is using declared object in a sizeof expression, which does not require an access to underlying object:
extern int undefined;
size_t res = sizeof(undefined);
The above will not break a link, because sizeof expression does not generate access to its arguments.
You can do anything with the declaration except for inlining it. For example:
void fun();
inline void fun(){}
After the declaration you can call the function, unless the definition is marked inline in which case it will result in a linker error because the definition does not emit a symbol to link against. Even if you don't say inline explicitly, an optimizing compiler may inline calls to the function if the definition has been seen.
www.cprogramming.com say's:
When you declare a variable, a function, or even a class all you are
doing is saying: there is something with this name, and it has this
type. The compiler can then handle most (but not all) uses of that
name without needing the full definition of that name. Declaring a
value--without defining it--allows you to write code that the compiler
can understand without having to put all of the details. This is
particularly useful if you are working with multiple source files, and
you need to use a function in multiple files. You don't want to put
the body of the function in multiple files, but you do need to provide
a declaration for it.
extern int i;
Here, an integer type variable i has been declared (but no definition i.e. no memory allocation for variable i so far). And we can do this declaration as many times as needed.
void fun();
Function fun() declare, but not defined. but it does tell the compiler that it can use this function and expect that it will be defined somewhere.
what can we do with i here
With
extern int i;
i can be declared as many times as required in the program.
You can have an initializer
extern int i = 0;
what can't we do with i here?
You can't use i without defining it in the program.
extern int i;
int main(void)
{
i = 10; // Will through an error
return 0;
}
In case of function this keyword only tells that the linkage for the function is extern. By default linkage of a function declaration/definition is extern.
#include <stdio.h>
int main()
{
extern int a;
extern int a;
int a = 10;
return 0;
}
what is the problem with this code? Since multiple declaration is allowed in c what is the problem with this code
The problem with the code is that the compiler is first informed that a is a global variable (due to the extern keyword); and then a is defined as a local 'automatic' variable. Hence there is a conflict in the defined scope of a
As an alternative to automatic variables, it is possible to define variables that are external to all functions, that is, variables that can be accessed by name by any function. (This mechanism is rather like Fortran COMMON or Pascal variables declared in the outermost block.) Because external variables are globally accessible, they can be used instead of argument lists to communicate data between functions. Furthermore, because external variables remain in existence permanently, rather than appearing and disappearing as functions are called and exited, they retain their values even after the functions that set them have returned. —The C Programming Language
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context. ... You should note that we are using the words definition and declaration carefully when we refer to external variables in this section. Definition refers to the place where the variable is created or assigned storage; declaration refers to places where the nature of the variable is stated but no storage is allocated. —The C Programming Language
From your question I observe that you are visualizing your program something like this
#include <stdio.h>
int main()
{
extern int a; //declaration
extern int a; //declaration
int a = 10; //declaration + definiton
return 0;
}
With above understanding of extern keyword. Your question is obvious.
Let us understand use extern of keyword thoroughly.
Extern variable declaration is a promise to the compiler that there would be a definition of a global variable some place else. Read This. In other words extern keyword tell the compiler that forget about this variable at the moment and left it to linker to link it with its definition. That is extern variables are actually linked to its definition by linker. Moreover Local variables have no linkage at all. So while searching for its definition compiler found a definition without linkage. Thats the error.
As a rule of thumb just remember when you declare any variable as extern inside any function then you can only define it outside of that function.(However there is no use of it).
I am new to C and I experience some confusion between the declaration and definition of a variable. Another thing I would like to know is if the following is true:
"Declaration appears many times and definition comes once."
Also:
int x;
Is this a declaration only? Since memory is allocated for x then why isn't this a definition instead of a declaration?
Simply writing int x; at either global scope or local scope, is both a declaration and definition. Typically, the declaration tells the compiler "This variable will exist, at some point, under this name, so you can use it." The definition tells the compiler to actually arrange for the variable to be created - obviously this can only happen once.
Typically the way you'll use this is by putting in a header file:
// Foo.h
#ifndef FOO_H
#define FOO_H // make sure structs aren't redefined
extern int bar; // Declare a variable bar
#endif
And in a single source file
#include "foo.h"
int bar; // Define bar
If you were to define bar in multiple files, you would get an error; you can't create the variable twice. But you do have to tell the compiler about it in every source file you use bar in. Hence the extern declaration.
The precise semantics are defined in §6.9.2 of the C standard and can be summarized as follows:
When a variable is declared at file scope with an initializer, it is an external definition. (§6.9.2/1)
When a variable is declared at file scope without an initializer, and without a storage-class specifier or with the static storage-class specifier, it is a tentative definition. If the translation unit (file) has one or more tentative definitions and no external definition, the compiler automatically adds a true file scope declaration at the end of the translation unit, with a zero initializer. (§6.9.2/2)
What this means is that, strictly speaking, int x; is not a definition; but it automatically creates a definition if and only if there is no other definition with an initializer, and no static definition (this third case is undefined behavior due to linkage disagreement per §6.2.2/7)
Note that extern int x; is not an external definition. It is a declaration with an extern storage class specifier. As such, extern int x; alone does not cause a definition to be created, but if you have both:
extern int x;
int x;
Then you will end up having a definition created at some point in the file.
It is also, technically speaking, legal to do this:
extern int x;
int x;
int x = 42;
In this case, the int x; in the middle is superfluous and has no effect. That said, this is poor form, as it's confusing in this case where the actual definition is.
This isn't something you see too much in C, but it works like this:
In a header file, you can have a line like this:
extern int x; //declaration
Because of the extern modifier, this tells the compiler that there is an int named x somewhere. The compiler doesn't allocate space for it - it just adds int x to the list of variables you can use. It'll only allocate space for x when it sees a line like this:
int x; //definition
You can see that because only the int x; line changes your executable, you can have as many extern int x; lines as you feel like. As long as there's only int x; line, everything will work like you want it to - having multiple declarations doesn't change a thing.
A better example comes from C++ (sorry if this is a C-only question - this applies to structs as well, but I don't know the syntax off the top of my head):
class Pineapple; //declaration
Pineapple* ptr; //this works
Pineapple pine; //this DOES NOT work
This declaration tells the compiler that there's a class called "Pineapple". It doesn't tell us anything about the class (how big it is, what its members are). We can use pointers to Pineapples now, but we can't yet have instances - we don't know what makes up a Pineapple, so we don't know how much space an instance takes up.
class Pineapple
{
public:
int ounces;
char* name;
}; //definition
Pineapple* ptr; //still works
Pineapple pine; //this works now too!
//we can even get at member variables, 'cause we know what they are now:
pine.ounces = 17;
After a definition, we know everything about the class, so we can have instances, too. And like the C example, you can have multiple declarations, but only one definition.
Hope this helps!