The code:
int main(void)
{
auto a=1;
return 0;
}
gets compiled without errors by the MS Visual Studio 2012 compiler, when the file has the .c extension. I have always thought that when you use the .c extension, compilation should be according to the C syntax, and not C++. Moreover, as far as I know auto without a type is allowed only in C++ since C++11, where it means that the type is deduced from the initializer.
Does that mean that my compiler isn't sticking to C, or is the code actually correct in C-language?
auto is an old C keyword that means "local scope". auto a is the same as auto int a, and because local scope is the default for a variable declared inside a function, it's also the same as int a in this example.
This keyword is actually a leftover from C's predecessor B, where there were no base types: everything was int, pointer to int, array of int.(*) Declarations would be either auto or extrn [sic]. C inherited the "everything is int" as a default rule, so you could declare integers with
auto a;
extern b;
static c;
ISO C got rid of this, but many compilers still accept it for backward compatibility. If it seems unfamiliar, then you should realise that a related rule is at work in
unsigned d; // actually unsigned int
which is still common in modern code.
C++11 reused the keyword, which few if any C++ programmers were using with the original meaning, for its type inference. This is mostly safe because the "everything is int" rule from C had already been dropped in C++98; the only thing that breaks is auto T a, which no-one was using anyway. (Somewhere in his papers on the history of the language, Stroustrup comments on this, but I can't find the exact reference right now.)
(*) String handling in B was interesting: you'd use arrays of int and pack multiple characters in each member. B was actually BCPL with different syntax.
This is both an answer and an extended comment to No, this isn't legal C since 1999. No decent modern C compiler allows for this.
Yes, auto a=1; is illegal in C1999 (and also C2011). Just because this is now illegal does not mean that a modern C compiler should reject code that contains such constructs. I would argue exactly the opposite, that a decent modern C compiler must still allow for this.
Both clang and gcc do just that when compiling the sample code in the question against the 1999 or 2011 versions of the standard. Both compilers issue a diagnostic and then carry on as if the objectionable statement had been auto int a=1;.
In my opinion, this is what a decent compiler should do. By issuing a diagnostic, clang and gcc are full compliant with the standard. The standard does not say that a compiler must reject illegal code. The standard merely says that a conforming implementation must produce at least one diagnostic message if a translation unit contains a violation of any syntax rule or constraint (5.1.1.3).
Given code that contains illegal constructs, any decent compiler will try to make sense of the illegal code so that the compiler can find the next error in the code. A compiler that stops at the first error isn't a very good compiler. There is a way to make sense out of auto a=1, which is to apply the "implicit int" rule. This rule forces the compiler to interpret auto a=1 as if it were auto int a=1 when the compiler is used in C90 or K&R mode.
Most compilers typically do reject code (reject: refuse to generate an object file or an executable) that contains illegal syntax. This is a case where the compiler authors decided that failing to compile is not the best option. The best thing to do is to issue a diagnostic, fix the code, and carry on. There's just too much legacy code that is peppered with constructs such as register a=1;. The compiler should be able to compile that code in C99 or C11 mode (with a diagnostic, of course).
auto has a meaning in C and C++ prior to the 2011 Standard. It means that a variable has automatic lifetime, that is, lifetime determined by the scope. This is opposed to, e.g., static lifetime, where a variable lasts "forever", regardless of the scope. auto is the default lifetime, and is almost never spelled out explicitly. This is why it was safe to change the meaning in C++.
Now in C, prior to the 99 Standard, if you don't specify the type of a variable, it defaults to int.
So with auto a = 1; you are declaring (and defining) an int variable, with lifetime determined by the scope.
("lifetime" is more properly called "storage duration", but I think that is perhaps less clear).
In C, and historic dialects of C++, auto is a keyword meaning that a has automatic storage. Since it can only be applied to local variables, which are automatic by default, no-one uses it; which is why C++ has now repurposed the keyword.
Historically, C has allowed variable declarations with no type specifier; the type defaults to int. So this declaration is equivalent to
int a=1;
I think this is deprecated (and possibly forbidden) in modern C; but some popular compilers default to C90 (which, I think, does allow it), and, annoyingly, only enable warnings if you specifically ask for them. Compiling with GCC and either specifying C99 with -std=c99, or enabling the warning with -Wall or -Wimplicit-int, gives a warning:
warning: type defaults to ‘int’ in declaration of ‘a’
In C, auto means the same thing register does in C++11: it means that a variable has automatic storage duration.
And in C prior to C99 (and Microsoft's compiler does not support either C99 or C11, although it may support parts of it), the type can be omitted in many cases, where it will default to int.
It does not take the type from the initialiser at all. You just happened to pick an initialiser that's compatible.
Visual studio compilation type is available at right click on file -> Properties -> C/C++ -> Advanced -> Compile As. To make sure it is compiled as C force /TC option.Then in this case it is what larsmans said (old C auto keyword). It might be compiled as C++ without you knowing.
A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.
There are following storage classes which can be used in a C Program
auto
register
static
extern
auto is the default storage class for all local variables.
{
int Count;
auto int Month;
}
The example above defines two variables with the same storage class. auto can only be used within functions, i.e. local variables.
int is default type for auto in below code:
auto Month;
/* Equals to */
int Month;
Below code is legal too:
/* Default-int */
main()
{
reurn 0;
}
Related
If "a function" were compiled separately, the mismatch would not be detected, "the function" would return a double that main would treat as an int... In the light of what we have said about how declarations must match definitions this might seems surprising. The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as
sum += "the function"(line);
If a name that has not been previously declared occurs in an expression and is followed by a left parenthesis, it is declared by context to be a function name, the function is assumed to return an int, and nothing is assumed about its arguments.
I apologize beforehand for the ambiguous question, but what does this mean?
By the way this is page 73 chapter 4.3 from Brian W. Kernighan and Dennis M. Ritchie's C Programming Language book, 2nd edition.
K&R2 covers the 1989/1990 version of the language. The current ISO C standard, published in 1999 2011, drops the "implicit int" rule, and requires a visible declaration for any function you call. Compilers don't necessarily enforce this by default, but you should be able to request more stringent warnings -- and you definitely should. In well-written new code, the rule is irrelevant (but it is necessary to understand it).
An example: the standard sqrt() function is declared in <math.h>:
double sqrt(double);
If you write a call without the required #include <math.h>:
double x = 64.0;
double y = sqrt(x);
a C90 compiler will assume that sqrt returns int -- and it will generate code to convert the result from int to double. The result will be garbage, or perhaps a crash.
(You could manually declare sqrt yourself, but that's the wrong solution.)
So don't do that. Always include whatever header is required for any function you call. You might get away with calling an undeclared function if it does return int (and if your compiler doesn't enforce strict C99 or C11 semantics, and if a few other conditions are satisfied), but there's no good reason to do so.
Understanding the "implicit int" rule is still useful for understanding the behavior of old or poorly written code, but you should never depend on it in new code.
Function prototypes were introduced into the language late.
Before prototypes, the compiler would assume that every argument passed to every unknown function should be passed as an integer and would assume that the return value was also an integer.
This worked fine for the few cases where it was correct, but meant people had to write programs in an awkward order so that functions would never rely on unknown functions that did not match this expectation.
When prototypes were introduced into C89 (aka ANSI C or ISO C), the prototypes allow the compiler to know exactly what types of arguments are expected and what types of results will be returned.
It is strongly recommended that you use function prototypes for all new code; when working on an entirely old code base, the prototypes might be harmful. (Or, if the code must be compilable on a pre-ANSI C compiler, then you might wish to leave off the prototypes so it can be built on the ancient software. gcc is the only place I've seen this in a long time.)
It's just stating that if the compiler comes across code that calls an unknown function, then it implicitly treats it as if it had already seen a declared prototype of the form int unknown();
int main ()
{
hello();
return 0;
}
int hello()
{
printf("\n hello world");
return 0;
}
as per C rule every function which is defined below the main() must be declared above main() but why it's exception for function which has int as return type?
if you change return type of hello() to anything else (void, char * etc)
it will throw error for declaration . Why there is no error or warning for int return type ?
This is an old feature of C, which is now officially unsupported.
In earlier days (before C99, if I'm not wrong), in case of a missing return type for a function, or in case a function was missing a forward declaration, the function was assumed to return an int and accept any number of arguments. Your actual definition of the function also matches that assumption, so the linker also does not complain.
Your compiler still supports that old feature (mainly due to maintain the backward compatibility to the programs written using the older standards), hence you are successfully compiling and linking the program.
FYI, in the latest C standard, C11, it is officially mentioned
remove implicit function declaration
so, as per the strict checking, it is compulsory to forward declare a function (or, define before it's usage, so that compiler does not have to assume anything).
Due to its history of development and evolution, C has kept things that would have been deprecated in other languages. This is because there is a lot of older C code that would break if C compilers did not maintain backward compatibility.
The idea is that new C code should use new styles and conventions. However C compilers try their best to maintain compatibility with older source style and conventions.
Due to the reluctance of C compiler vendors to break existing, older source code, you will see C source code that compiles yet seems to break the rules of the newer C standards.
Working with older source myself, when I use Visual Studio 2015 the number of warnings are incredible because the same issues are repeatedly marked. The result is for this large body of code there are certain warnings I turn off.
The function declaration thing you mention is just one. There is also the new security types of string functions and I/O functions versus the old style that did not have the additional length arguments.
There was a convention in C that functions declared without return type have return type int by default.
Also the default type specifier of variables also was int. For example Borland C++ Builder 5.0 supported such declaration
const VALUE = 10;
Ever since C99, a declaration has been required in advance of use; once an implementation issues a diagnostic for a failure to include such a declaration, it may continue processing the source file or not as it sees fit.
In the earlier days of C, before void was added to the language, int was by far the most common return type. Argument types would be inferred at each call site, so the compiler didn't need to know anything about any function other than its return type. Further, text editors that could handle files larger than 32K were considered a luxury, and being able to skip the preprocessor could shave multiple seconds off compilation times. Put those facts together, and being able to omit the declarations for the majority of functions increased the amount of useful code that could be included within each source file.
So for example,
int aaa(unsigned int par1, unsigned int par2){
int array[par1*par2];
return 0;
}
I tried compiling the code that contains this, and it compiled well and had no run-time issue - the array was properly created.
But I know that this is basically declaring a dynamic array in static array declaration fashion. What may go wrong with this declaration? Will there be a compiler issue in a different compiler?
This is correct as per the 1999 C standard. The 2011 standard changed it to be an optional feature, which in practice means that all C11 compilers will support it except for MSVC.
Before 1999 some compilers offered this as a non-standard extension.
Here is a link to StackOverflow search for other questions on this topic.
But I know that this is basically declaring a dynamic array in static array declaration fashion.
This is called VLA (Variable-Length Array). This array is not static - it is placed in automatic memory (also known as "the stack").
What may go wrong with this declaration?
It may overflow the stack when the size of the array exceeds a certain limit specific to your system.
Will there be a compiler issue in a different compiler?
This is a C99 feature, so compiler that do not support C99 may fail to compile this code.
I believe this is a C99-only feature. It's called VLA (variable-length arrays).
The C++0x does't support VLA:
https://groups.google.com/forum/#!topic/comp.std.c++/K_4lgA1JYeg
But some compilers might not be strictly compliant with the standard.
If "a function" were compiled separately, the mismatch would not be detected, "the function" would return a double that main would treat as an int... In the light of what we have said about how declarations must match definitions this might seems surprising. The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as
sum += "the function"(line);
If a name that has not been previously declared occurs in an expression and is followed by a left parenthesis, it is declared by context to be a function name, the function is assumed to return an int, and nothing is assumed about its arguments.
I apologize beforehand for the ambiguous question, but what does this mean?
By the way this is page 73 chapter 4.3 from Brian W. Kernighan and Dennis M. Ritchie's C Programming Language book, 2nd edition.
K&R2 covers the 1989/1990 version of the language. The current ISO C standard, published in 1999 2011, drops the "implicit int" rule, and requires a visible declaration for any function you call. Compilers don't necessarily enforce this by default, but you should be able to request more stringent warnings -- and you definitely should. In well-written new code, the rule is irrelevant (but it is necessary to understand it).
An example: the standard sqrt() function is declared in <math.h>:
double sqrt(double);
If you write a call without the required #include <math.h>:
double x = 64.0;
double y = sqrt(x);
a C90 compiler will assume that sqrt returns int -- and it will generate code to convert the result from int to double. The result will be garbage, or perhaps a crash.
(You could manually declare sqrt yourself, but that's the wrong solution.)
So don't do that. Always include whatever header is required for any function you call. You might get away with calling an undeclared function if it does return int (and if your compiler doesn't enforce strict C99 or C11 semantics, and if a few other conditions are satisfied), but there's no good reason to do so.
Understanding the "implicit int" rule is still useful for understanding the behavior of old or poorly written code, but you should never depend on it in new code.
Function prototypes were introduced into the language late.
Before prototypes, the compiler would assume that every argument passed to every unknown function should be passed as an integer and would assume that the return value was also an integer.
This worked fine for the few cases where it was correct, but meant people had to write programs in an awkward order so that functions would never rely on unknown functions that did not match this expectation.
When prototypes were introduced into C89 (aka ANSI C or ISO C), the prototypes allow the compiler to know exactly what types of arguments are expected and what types of results will be returned.
It is strongly recommended that you use function prototypes for all new code; when working on an entirely old code base, the prototypes might be harmful. (Or, if the code must be compilable on a pre-ANSI C compiler, then you might wish to leave off the prototypes so it can be built on the ancient software. gcc is the only place I've seen this in a long time.)
It's just stating that if the compiler comes across code that calls an unknown function, then it implicitly treats it as if it had already seen a declared prototype of the form int unknown();
In my college days I read about the auto keyword and in the course of time I actually forgot what it is. It is defined as:
defines a local variable as having a
local lifetime
I never found it is being used anywhere, is it really used and if so then where is it used and in which cases?
If you'd read the IAQ (Infrequently Asked Questions) list, you'd know that auto is useful primarily to define or declare a vehicle:
auto my_car;
A vehicle that's consistently parked outdoors:
extern auto my_car;
For those who lack any sense of humor and want "just the facts Ma'am": the short answer is that there's never any reason to use auto at all. The only time you're allowed to use auto is with a variable that already has auto storage class, so you're just specifying something that would happen anyway. Attempting to use auto on any variable that doesn't have the auto storage class already will result in the compiler rejecting your code. I suppose if you want to get technical, your implementation doesn't have to be a compiler (but it is) and it can theoretically continue to compile the code after issuing a diagnostic (but it won't).
Small addendum by kaz:
There is also:
static auto my_car;
which requires a diagnostic according to ISO C. This is correct, because it declares that the car is broken down. The diagnostic is free of charge, but turning off the dashboard light will cost you eighty dollars. (Twenty or less, if you purchase your own USB dongle for on-board diagnostics from eBay).
The aforementioned extern auto my_car also requires a diagnostic, and for that reason it is never run through the compiler, other than by city staff tasked with parking enforcement.
If you see a lot of extern static auto ... in any code base, you're in a bad neighborhood; look for a better job immediately, before the whole place turns to Rust.
auto is a modifier like static. It defines the storage class of a variable. However, since the default for local variables is auto, you don't normally need to manually specify it.
This page lists different storage classes in C.
The auto keyword is useless in the C language. It is there because before the C language there existed a B language in which that keyword was necessary for declaring local variables. (B was developed into NB, which became C).
Here is the reference manual for B.
As you can see, the manual is rife with examples in which auto is used. This is so because there is no int keyword. Some kind of keyword is needed to say "this is a declaration of a variable", and that keyword also indicates whether it is a local or external (auto versus extrn). If you do not use one or the other, you have a syntax error. That is to say, x, y; is not a declaration by itself, but auto x, y; is.
Since code bases written in B had to be ported to NB and to C as the language was developed, the newer versions of the language carried some baggage for improved backward compatibility that translated to less work. In the case of auto, the programmers did not have to hunt down every occurrence of auto and remove it.
It's obvious from the manual that the now obsolescent "implicit int" cruft in C (being able to write main() { ... } without any int in front) also comes from B. That's another backward compatibility feature to support B code. Functions do not have a return type specified in B because there are no types. Everything is a word, like in many assembly languages.
Note how a function can just be declared extrn putchar and then the only thing that makes it a function that identifier's use: it is used in a function call expression like putchar(x), and that's what tells the compiler to treat that typeless word as a function pointer.
In C auto is a keyword that indicates a variable is local to a block. Since that's the default for block-scoped variables, it's unnecessary and very rarely used (I don't think I've ever seen it use outside of examples in texts that discuss the keyword). I'd be interested if someone could point out a case where the use of auto was required to get a correct parse or behavior.
However, in the C++11 standard the auto keyword has been 'hijacked' to support type inference, where the type of a variable can be taken from the type of its initializer:
auto someVariable = 1.5; // someVariable will have type double
Type inference is being added mainly to support declaring variables in templates or returned from template functions where types based on a template parameter (or deduced by the compiler when a template is instantiated) can often be quite painful to declare manually.
With the old Aztec C compiler, it was possible to turn all automatic variables to static variables (for increased addressing speed) using a command-line switch.
But variables explicitly declared with auto were left as-is in that case. (A must for recursive functions which would otherwise not work properly!)
The auto keyword is similar to the inclusion of semicolons in Python, it was required by a previous language (B) but developers realized it was redundant because most things were auto.
I suspect it was left in to help with the transition from B to C. In short, one use is for B language compatibility.
For example in B and 80s C:
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10. This routine uses the fact that
in the ASCII character set, the digits 0 to 9 have sequential
code values. */
printn(n, b) {
extern putchar;
auto a;
if (a = n / b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n % b + '0');
}
auto can only be used for block-scoped variables. extern auto int is rubbish because the compiler can't determine whether this uses an external definition or whether to override the extern with an auto definition (also auto and extern are entirely different storage durations, like static auto int, which is also rubbish obviously). It could always choose to interpret it one way but instead chooses to treat it as an error.
There is one feature that auto does provide and that's enabling the 'everything is an int' rule inside a function. Unlike outside of a function, where a=3 is interpreted as a definition int a =3 because assignments don't exist at file scope, a=3 is an error inside a function because apparently the compiler always interprets it as an assignment to an external variable rather than a definition (even if there are no extern int a forward declarations in the function or in the file scope), but a specifier like static, const, volatile or auto would imply that it is a definition and the compiler takes it as a definition, except auto doesn't have the side effects of the other specifiers. auto a=3 is therefore implicitly auto int a = 3. Admittedly, signed a = 3 has the same effect and unsigned a = 3 is always an unsigned int.
Also note 'auto has no effect on whether an object will be allocated to a register (unless some particular compiler pays attention to it, but that seems unlikely)'
Auto keyword is a storage class (some sort of techniques that decides lifetime of variable and storage place) example. It has a behavior by which variable made by the Help of that keyword have lifespan (lifetime ) reside only within the curly braces
{
auto int x=8;
printf("%d",x); // here x is 8
{
auto int x=3;
printf("%d",x); // here x is 3
}
printf("%d",x); // here x is 8
}
I am sure you are familiar with storage class specifiers in C which are "extern", "static", "register" and "auto".
The definition of "auto" is pretty much given in other answers but here is a possible usage of "auto" keyword that I am not sure, but I think it is compiler dependent.
You see, with respect to storage class specifiers, there is a rule. We cannot use multiple storage class specifiers for a variable. That is why static global variables cannot be externed. Therefore, they are known only to their file.
When you go to your compiler setting, you can enable optimization flag for speed. one of the ways that compiler optimizes is, it looks for variables without storage class specifiers and then makes an assessment based on availability of cache memory and some other factors to see whether it should treat that variable using register specifier or not. Now, what if we want to optimize our code for speed while knowing that a specific variable in our program is not very important and we dont want compiler to even consider it as register. I though by putting auto, compiler will be unable to add register specifier to a variable since typing "register auto int a;" OR "auto register int a;" raises the error of using multiple storage class specifiers.
To sum it up, I thought auto can prohibit compiler from treating a variable as register through optimization.
This theory did not work for GCC compiler however I have not tried other compilers.