What exactly are C++ definitions, declarations and assignments? - c++

I tend to use the words define, declare and assign interchangeably but this seems to cause offense to some people. Is this justified? Should I only use the word declare for the first time I assign to a variable? Or is there more to it than that?

A definition is where a value or function is described, i.e. the compiler or programmer is told precisely what it is, e.g.
int foo()
{
return 1;
}
int var; // or, e.g. int var = 5; but this is clearer.
A declaration tells the compiler, or programmer that the function or variable exists. e.g.
int foo();
extern int var;
An assignment is when a variable has its value set, usually with the = operator. e.g.
a = b;
a = foo();

Define and declare are similar but assign is very different.
Here I am declaring (or defining) a variable:
int x;
Here I am assigning a value to that variable:
x = 0;
Here I am doing both in one statement:
int x = 0;
Note
Not all languages support declaration and assignment in one statement:
T-SQL
declare x int;
set x = 0;
Some languages require that you assign a value to a variable upon declaration. This requirement allows the compiler or interpreter of the language to infer a type for the variable:
Python
x = 0

It is important to use the correct terminology, otherwise people will not know what you are talking about, or incorrectly assume that you don't know what you are talking about.

These terms often have precise meanings in the standards for various languages. When that is the case they should not be conflated.
In c for instance:
a function may be defined only once (when you say what it does), but it may also be declared before that (when you say what arguments it takes and what type it returns).
likewise a variable is declared when you say what type it is, and this happens only once for each scope. But you may assign a value repeatedly. (Some languages also differentiate between initialization (giving a variable a value at declaration time) and assignment (changing the value later).)

General Role:
Definition = declaration + reserved space.
Definition, declaration, and assignment have two cases:
for Variables.
for Functions.
For Variables:
-- Definition:
To tell the compiler to reserve memory for the variable.
int x;
-- Declaration:
To tell the compiler that the variable defined in somewhere else.
extern int x;
-- Assignment:
To tell the compiler to put the value in the variable.
x = 0;
For Functions:
-- Definition:
int functionDef(int x){
int x;
...
...
...
return x;
}
-- Declaration:
It is just the prototype of the function.
int functionDef(int x);

The differences can seem subtle, but they are important. Not every language makes the same distinctions, but in C++ a variable declaration makes the type and name of the variable known to the compiler
int i;
A variable definition allocates storage and specifies an initial value for the variable.
i = 1;
You can combine a variable declaration and definition into one statement, as is commonly done.
int x = 1;
Declaring a variable inside a function will also set aside memory for the variable, so the following code implicitly defines variable a as a part of its declaration.
int main()
{
int a;
return 0;
}
Since variable a is automatically defined by the compiler, it will contain whatever value was in the memory location that was allocated for it. This is why it is not safe to use automatic variables until you've explicitly assigned a known value to them.
An assignment takes place any time you change the value of a variable in your program.
x = 2;
x++;
x += 4;
A function declaration, similar to the variable declaration, makes the function signature known to the compiler. This allows you to call a function in your source code before it is defined without causing a compiler error.
int doSomething(float x);
A function definition specifies the return type, name, parameter list, and instructions for a function. The first three of these elements must match the function declaration. A function must only be defined once in a given program.
int doSomething(float x)
{
if( x < 0 )
{
x = -x;
}
return static_cast<int>(x);
}
You can combine the function decalartion and definition into one, but you must do so before the function is called anywhere in your program.

It might depend on the language, as has been said. I think it really depends on whether the words are used for things like classes. For most of the data types discussed here, the question might not have much relevance. In C++ (see c++ - What is the difference between a definition and a declaration?), a class or struct always has precisely one definition but can be declared zero or more times. A class cannot be declared without a definition. So "declared" might be synonymous with "used".
In most languages, simple types such as integers do not need definitions in the manner that classes do.

The correct answer depends on which language you're talking about. Computer languages often have specific terminology, either because of the language specification or the community grown up around the language. COBOL, back when I used it, had a much different terminology than more mainstream languages (in the sense of languages closer to the mainstream of language development, not mainstream business). Forth developed some strange terminology.
If you know English, you can usually get a good idea as to what a word means from its normal meaning, but never count on it too much. The same is true with specific words across languages or language communities.

Related

what is redefining static variable in c++? [duplicate]

I tend to use the words define, declare and assign interchangeably but this seems to cause offense to some people. Is this justified? Should I only use the word declare for the first time I assign to a variable? Or is there more to it than that?
A definition is where a value or function is described, i.e. the compiler or programmer is told precisely what it is, e.g.
int foo()
{
return 1;
}
int var; // or, e.g. int var = 5; but this is clearer.
A declaration tells the compiler, or programmer that the function or variable exists. e.g.
int foo();
extern int var;
An assignment is when a variable has its value set, usually with the = operator. e.g.
a = b;
a = foo();
Define and declare are similar but assign is very different.
Here I am declaring (or defining) a variable:
int x;
Here I am assigning a value to that variable:
x = 0;
Here I am doing both in one statement:
int x = 0;
Note
Not all languages support declaration and assignment in one statement:
T-SQL
declare x int;
set x = 0;
Some languages require that you assign a value to a variable upon declaration. This requirement allows the compiler or interpreter of the language to infer a type for the variable:
Python
x = 0
It is important to use the correct terminology, otherwise people will not know what you are talking about, or incorrectly assume that you don't know what you are talking about.
These terms often have precise meanings in the standards for various languages. When that is the case they should not be conflated.
In c for instance:
a function may be defined only once (when you say what it does), but it may also be declared before that (when you say what arguments it takes and what type it returns).
likewise a variable is declared when you say what type it is, and this happens only once for each scope. But you may assign a value repeatedly. (Some languages also differentiate between initialization (giving a variable a value at declaration time) and assignment (changing the value later).)
General Role:
Definition = declaration + reserved space.
Definition, declaration, and assignment have two cases:
for Variables.
for Functions.
For Variables:
-- Definition:
To tell the compiler to reserve memory for the variable.
int x;
-- Declaration:
To tell the compiler that the variable defined in somewhere else.
extern int x;
-- Assignment:
To tell the compiler to put the value in the variable.
x = 0;
For Functions:
-- Definition:
int functionDef(int x){
int x;
...
...
...
return x;
}
-- Declaration:
It is just the prototype of the function.
int functionDef(int x);
The differences can seem subtle, but they are important. Not every language makes the same distinctions, but in C++ a variable declaration makes the type and name of the variable known to the compiler
int i;
A variable definition allocates storage and specifies an initial value for the variable.
i = 1;
You can combine a variable declaration and definition into one statement, as is commonly done.
int x = 1;
Declaring a variable inside a function will also set aside memory for the variable, so the following code implicitly defines variable a as a part of its declaration.
int main()
{
int a;
return 0;
}
Since variable a is automatically defined by the compiler, it will contain whatever value was in the memory location that was allocated for it. This is why it is not safe to use automatic variables until you've explicitly assigned a known value to them.
An assignment takes place any time you change the value of a variable in your program.
x = 2;
x++;
x += 4;
A function declaration, similar to the variable declaration, makes the function signature known to the compiler. This allows you to call a function in your source code before it is defined without causing a compiler error.
int doSomething(float x);
A function definition specifies the return type, name, parameter list, and instructions for a function. The first three of these elements must match the function declaration. A function must only be defined once in a given program.
int doSomething(float x)
{
if( x < 0 )
{
x = -x;
}
return static_cast<int>(x);
}
You can combine the function decalartion and definition into one, but you must do so before the function is called anywhere in your program.
It might depend on the language, as has been said. I think it really depends on whether the words are used for things like classes. For most of the data types discussed here, the question might not have much relevance. In C++ (see c++ - What is the difference between a definition and a declaration?), a class or struct always has precisely one definition but can be declared zero or more times. A class cannot be declared without a definition. So "declared" might be synonymous with "used".
In most languages, simple types such as integers do not need definitions in the manner that classes do.
The correct answer depends on which language you're talking about. Computer languages often have specific terminology, either because of the language specification or the community grown up around the language. COBOL, back when I used it, had a much different terminology than more mainstream languages (in the sense of languages closer to the mainstream of language development, not mainstream business). Forth developed some strange terminology.
If you know English, you can usually get a good idea as to what a word means from its normal meaning, but never count on it too much. The same is true with specific words across languages or language communities.

Difference between variable declared at the top of a function and one declared later

What is the difference in generated code when I have the definition of a variable at the top of a function and when I have it declared later. Example:
int f(int parameter) {
int a = parameter * 2;
if (a == 4)
return 1;
int b = parameter * 4;
if (b == 4)
return 2;
return 0;
}
Does output code have b variable initialization and allocation after if (a == 4) or will a and b variables be initialized at the same moment?.
To see what actually happens, look at the generated assembler.
In terms of allocating space, most compilers will allocate enough space on the stack for all the variables used in a function at the start of the function. (This doesn't have to happen like this, but I don't know of any compiler which don't work like this.)
In terms of initializations, the abstract machine (as defined by the C and C++ standards) treats the initializations (that is, setting the initial values) as happening at different times. b is initialized after the comparison of a with 4.
Of course, by the as-if rule, if the initialization doesn't have side-effects, the compiler can move the initialization round as it sees fit. This happens more often with C than with C++, because C++ initializers often involve constructors in other translation units, and the compiler can't see if there are side effects there.
In this simple case if you optimize, it is quite likely that both a and b will only ever be stored in a register, and this may well be the same register. (This is because you are using plain int variables, and because you don't overlap the use of a and b.)

Is initializing a garbage variable truly initializing or just an assignment?

I generally see examples of initialisation vs assignment like this:
int funct1(void)
{int a = 5; /*initialization*/
a = 6;} /*assignment*/
Obviously something left as garbage or undefined somehow is uninitialized.
But could some one please define if initialization is reserved for definition statements and/or whether assignments can be called initialisation?
int funct2(void)
{int b;
b = 5;} /*assignment, initialization or both??*/
Is there much of a technical reason why we can't say int b is initialised to garbage (from the compilers point of view)?
Also if possible could this be compared with initializing and assinging on non-primitive data types.
I'll resurrect this thread to add an important point of view, since the puzzlement about terminology by the OP is understandable. As #OliCharlesworth pointed out (and he's perfectly right about that) as far as the C language standard is concerned initialization and assignment are two completely different things. For example (assuming local scope):
int n = 1; // definition, declaration and **initialization**
int k; // just definition + declaration, but no initialization
n = 12; // assignment of a previously initialized variable
k = 42; // assignment of a previously UNinitialized variable
The problem is that many books that teach programming aren't so picky about terminology, so they call "initialization" any "operation" that gives a variable its first meaningful value. So, in the example above, n = 12 wouldn't be an initialization, whereas k = 42 would. Of course this terminology is vague, imprecise and may be misleading (although it is used too often, especially by teachers when introducing programming to newbies). As a simple example of such an ambiguity let's recast the previous example taking global scope into account:
// global scope
int n = 1; // definition, declaration and **initialization**
int k; // definition, declaration and **implicit initialization to 0**
int main(void)
{
n = 12; // assignment of a previously initialized variable
k = 42; // assignment of a previously initialized variable
// ... other code ...
}
What would you say about the assignments in main? The first is clearly only an assignment, but is it the second an initialization, according to the vague, generic terminology? Is the default value 0 given to k its first "meaningful" value or not?
Moreover a variable is commonly said to be uninitialized if no initialization or assignment has been applied to it. Given:
int x;
x = 42;
one would commonly say that x is uninitialized before the assignment, but not after it. The terms assignment and initializer are defined syntactically, but terms like "initialization" and "uninitialized" are often used to refer to the semantics (in somewhat informal usage). [Thanks to Keith Thompson for this last paragraph].
I dislike this vague terminology, but one should be aware that it is used and, alas, not too rare.
As far as the language standard is concerned, only statements of the form int a = 5; are initialisation. Everything of the form b = 5; is an assignment.
The same is true of non-primitive types.
And to "Is there much of a technical reason why we can't say int b is initialised to garbage", well, if you don't put any value into a memory location, it's not "initialisation". From the compiler's point of view, no machine language instruction is generated to write to the location, so nothing happens.

Why is the C++ variable declaration syntax inconsistent?

when I declare C++ variables, I do it like this:
int a,b,c,d;
or
string strA,strB,strC,strD;
I.e., first the type then a comma separated list of variable names.
However, I declare pointers like this:
int *a,*b,*c,*d;
and references like this:
int &a,&b,&c,&d;
To be consistent it should be
int* a,b,c,d;
and
int& a,b,c,d;
Why is it not consistent?
The best answer I've seen as to why things like * apply to variables and not to types is the idea that declaration should follow use.
Basically, how you declare a variable should look similar to how you use a variable.
For example,
int *a, b;
...
*a = 42;
b = 314159;
...the use of a and b looks similar to the declaration of a and b.
There's even a citation for this behavior from Dennis Ritchie, one of the creators of C:
Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear...In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.
Dennis Ritchie, The Development of the C Language. History of Programming Languages-II ed. Thomas J. Bergin, Jr. and Richard G. Gibson, Jr. ACM Press (New York) and Addison-Wesley (Reading, Mass), 1996; ISBN 0-201-89502-1.
It's because of the C heritage. The * modifier applies to the variable in C. So the C++ designers made & to apply to the variable as well by analogy, since they couldn't change the first without breaking C compatibility. Same is true for the array syntax too:
int anInt, *aPointerToInt, anArrayOfInt[100];
In The Design and Evolution of C++ Bjarne Stroustrup says he wasn't happy with this but had to accept it for C compatibility. He was unhappy with this in particular:
int *a[10];
It's not clear from the declaration if a is a pointer to an array or an array of pointers (it's an array of pointers, you need brackets to override).
Of course, you can always use a typedef to clean things up a little.
The reason is: in reality & and * in C and C++ applies to variable and no to type.
So the problem is that if you want to declare 4 pointer to integers you should write
int *a, *b, *c, *d;
Writing int* a, b; means
int *a;
int b;
For this reason a lot of people prefer to write int *a; than int* a;, just code style.
Of course int* is a type, but the C syntax states clearly that in a variable declaration * and & will apply to variable.
This happens for the same reason that arrays in C are declared in this way:
int a[10], b;
std::cout << typeid(a).name() << std::endl; // it will print int[10]
std::cout << typeid(b).name() << std::endl; // it will print int
In other languages like C# instead the syntax int[] array; is used.
Another thing is the pointer to function syntax:
// Now we declare a variable that is a pointer to function
int (*pt2Function)(char, char) = NULL;
We are applying the * to the variable name.
It seems to me that the use of * and & applied to the variable, also if 90% of us would prefer differently, is more consistent with the rest of the language.
In the same way, going back to arrays:
// Now we declare a variable that is a pointer to an array of 10 integers.
int (*arrayptr)[10];
C has a rule for its declarations: Declarations mimic use. What this means is that the declaration for a variable looks like the way the variable is used. For example:
int i;
Using this variable looks like i, and that expression results in an int.
int *i;
Using this variable looks like *i, and that expression results in an int. This also implies that an expression i results in a pointer to an int.
int i(void);
Using this variable looks like i(), and results in an int. This also implies i is a function that takes nothing and that returns an int.
int (*i[5])();
Using this variable looks like (*i[x])(), and results in an int. This also implies *i[x] is a function returning int, and i[x] is a pointer to a function returning int, and i is an array of pointers to functions returning int.
So:
int a, *b, c(void), (*d[5])(void);
declares several expressions which all have the type int, but the variables themselves are not all ints.
N.B. in declarations of function and arrays the sub declarations don't literally resemble the use of the variable. I.e. int i[5]; doesn't mean that you need to put a '5' inside the square brackets when you use i, and int i(int); doesn't mean you call the function by saying i(int);. Also declarations of variables of struct types don't match their use since you'd have to declare expressions for each member variable.
Related to the syntax for declaring variables is that of typedefs. To declare a typedef with a certain type, you use the same syntax as for declaring a variable of the desired type, but you stick typedef in front of the declaration and the variable name becomes the typedef name.
typedef int (*array_of_function_pointers[5])(void);
C++ adds references, templates, pointers to member, and a bunch of stuff. It tries to some extent to follow the old C convention, but that convention doesn't really work all that well for many of the things C++ adds, so you do start getting inconsistencies. You'll just have to learn the idiosyncrasies and chalk it up to an imperfect marriage between C and C++.
C++ has inherited this syntax from C. The K&R book (§5.1) says that the expression
int *ip, **ipp;
is intended to be mnemonic (i.e. you read “*ip and **ipp have type int”), they wanted it to mimic usage syntax.
I agree it is quite cryptic and counterintuitive for humans, and inconsistent with typedefs, e.g.
typedef int* intptr;
intptr a, b; // equivalent to: int *a, *b
but it never really was C++ author's decision, the choice to make the language compatible with C implied using this syntax, that's why.

using a static const int in a struct/class

struct A {
static const int a = 5;
struct B {
static const int b = a;
};
};
int main() {
return A::B::b;
}
The above code compiles. However if you go by Effective C++ book by Scott Myers(pg 14);
We need a definition for a in addition to the declaration.
Can anyone explain why this is an exception?
C++ compilers allow static const integers (and integers only) to have their value specified at the location they are declared. This is because the variable is essentially not needed, and lives only in the code (it is typically compiled out).
Other variable types (such as static const char*) cannot typically be defined where they are declared, and require a separate definition.
For a tiny bit more explanation, realize that accessing a global variable typically requires making an address reference in the lower-level code. But your global variable is an integer whose size is this typically around the size of an address, and the compiler realizes it will never change, so why bother adding the pointer abstraction?
By really pedantic rules, yes, your code needs a definition for that static integer.
But by practical rules, and what all compilers implement because that's how the rules of C++03 are intended - no, you don't need a definition.
The rules for such static constant integers are intended to allow you to omit the definition if the integer is used only in such situations where a value is immediately read, and if the static member can be used in constant expressions.
In your return statement, the value of the member is immediately read, so you can omit the definition of the static constant integer member if that's the only use of it. The following situation needs a definition, however:
struct A {
static const int a = 5;
struct B {
static const int b = a;
};
};
int main() {
int *p = &A::B::b;
}
No value is read here - but instead the address of it is taken. Therefore, the intent of the C++03 Standard is that you have to provide a definition for the member like the following in some implementation file.
const int A::B::b;
Note that the actual rules appearing in the C++03 Standard says that a definition is not required only where the variable is used where a constant expression is required. That rule, however, if strictly applied, is too strict. It would only allow you to omit a definition for situation like array-dimensions - but would require a definition in cases like a return statement. The corresponding defect report is here.
The wording of C++0x has been updated to include that defect report resolution, and to allow your code as written.
However, if you try the ternary operand without "defining" static consts, you get a linker error in GCC 4x:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795
So, although constructs like int k = A::CONSTVAL; are illegal in the current standard, they are supported. But the ternary operand is not. Some operators are more equal than others, if you get my drift :)
So much for "lax" rules. I suggest you write code conforming to the standard if you do not want surprises.
In general, most (and recent) C++ compilers allow static const ints
You just lucky, perhaps not. Try older compiler, such as gcc 2.0 and it will vehemently punish you with-less-than-pretty error message.