implicit int in c language - c

I am using orwell dev c++ IDE. I know that in the old C89 Standard & pre standard C++ supports default to int rule when return type of function isn't explicitly specified in function definition. But it has banned in C++. But recently i wrote following simple C program and it works fine.
#include <stdio.h>
void fun();
int main(void)
{
int a=9;
printf("%d",a);
printf("%d",a);
fun();
return 0;
}
a=1;
void fun()
{
printf("%d",a);
}
Is it true that default int rule is also applied to variables? My compiler shows me following warnings.
[Warning] data definition has no type or storage class [enabled by default]
[Warning] type defaults to 'int' in declaration of 'a' [enabled by default]
Why C99 standard still allows default to int? It fails in compilation in C++. Correct me if i am wrong? This C program also works on on line compilers like ideone.com

This is explained in the C99 rationale:
A new feature of C99:
In C89, all type specifiers could be omitted from the declaration
specifiers in a declaration. In such a case int was implied. The
Committee decided that the inherent danger of this feature outweighed
its convenience, and so it was removed. The effect is to guarantee the
production of a diagnostic that will catch an additional category of
programming errors. After issuing the diagnostic, an implementation
may choose to assume an implicit int and continue to translate the program in order to support existing source code that exploits this feature.
In other words, it's officially removed from the C99 standard, but compilers may still choose to follow this behavior and issue a diagnostic, as GCC does. For example, view their warning options page for -Wimplicit-int. To make these warnings compile as errors, use -pedantic-errors or -Werror.
As per #Anonymous's answer, c++98 contains a similar rule about type specifiers.
7.1.5/2
At least one type-specifier that is not a cv-qualifier is required
in a declaration unless it declares a constructor, destructor or
conversion function.80)
80) There is no special provision for a
decl-specifier-seq that lacks a type-specifier or that has a type-specifier that only specifies cv-qualifiers. The "implicit int" rule of C is no longer supported.
For example, GCC supports ISO/IEC 14882:1998 and above, so this would be an error no matter what.

The C99 standard does not allow types to be omitted.
Section 6.7.2.2 says:
At least one type specifier shall be given in the declaration
specifiers in each declaration, and in the specifier-qualifier list in
each struct declaration and type name.

Related

Does a constraint violation always result in a diagnostic?

I was wondering what would happen if I left out the parameter declarations in a K&R function definition, so I tried the following:
#include <stdio.h>
void f(a)
// int a; <--- omitting `declaration-list` causes warning in gcc, but nothing in clang
{
printf("%d", 9);
}
int main()
{
f(9);
return 0;
}
When I compile this with gcc 11, a diagnostic is issued in the form of a warning (i.e. warning: type of 'a' defaults to 'int'). However, when I compile it with clang 14, no diagnostic message is issued.
This confused me because in the Standard, omitting the declaration-list (which contains the parameter declarations) is a constraint violation (as per C11 6.9.1(6)), which requires a conforming implementation to issue a diagnostic (as per C11 5.1.1.3). So, why didn't clang issue a warning? Have I misinterpreted something?
EDIT: Must a diagnostic be issued if a constraint violation can be "fixed" by the compiler applying some other provision in the Standard?
For example, the empty declaration list in the code above has always been a constraint violation (since C89). However, prior to C99, the Standard also had an implicit int rule (see C90 6.5.2), which would have allowed the compiler to assume any undeclared parameters as being of type int and thereby recover from the no-empty-declaration-list constraint violation.
So, would a pre-1999 ANSI-conformant compiler have still issued a diagnostic in this case? My first impression was that it would have since the constraint would have taken precedence over the implicit int rule, but pg. 287 of Harbison and Steele says (emphasis added):
In the pre-Standard traditional form, the parameter names are listed in the declarator and the types are specified (in any order) in the declaration-list opt following the declarator. All parameters should be declared in the declaration-list, but prior to C99 omitted parameter declarations defaulted to type int.
The bit in bold makes it seem like empty declaration lists were allowed since the implicit int rule would have "fixed" any no-empty-declaration-list constraint violations.
clang will generate a warning if compiled with the -pedantic flag.
<source>:3:8: warning: parameter 'a' was not declared, defaulting to type 'int' [-Wpedantic]
void f(a)
^
1 warning generated.
ASM generation compiler returned: 0
<source>:3:8: warning: parameter 'a' was not declared, defaulting to type 'int' [-Wpedantic]
void f(a)
^
1 warning generated.
Execution build compiler returned: 0
Program returned: 0
9
https://godbolt.org/z/e73M1Eq8E
First of all, please do not assume conforming behavior from the "gcc like" compilers including clang, unless you explicitly compile with -std=c17 -pedantic-errors. clang 14 does give a diagnostic if you use these options. That name "pedantic" was very poorly chosen by gcc back in the days. A better name would have been -conforming or something like that, because that's the behavior that this option actually unlocks.
So, why didn't clang issue a warning? Have I misinterpreted something?
I believe you are reading the standard correctly. We can conclude that clang 14 is non-conforming without a -pedantic flag added.
However, when I compile it with clang 14, no diagnostic message is issued.
There was apparently a known bug which has been corrected in clang 15. See Clang 15.0.0 release notes:
The -Wimplicit-int warning diagnostic now defaults to an error in C99 and later. Prior to C2x, it may be downgraded to a warning with -Wno-error=implicit-int, or disabled entirely with -Wno-implicit-int. As of C2x, support for implicit int has been removed, and the warning options will have no effect. Specifying -Wimplicit-int in C89 mode will now issue warnings instead of being a noop.
Therefore clang 15.0.0 (x86) with default options (with or without -pedantic-errors) gives:
error: parameter 'a' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int]
void f(a)
clang -Wno-implicit-int disables the error, as per the bug fix above.
Must a diagnostic be issued if a constraint violation can be "fixed" by the compiler applying some other provision in the Standard?
Upon finding a constraint violation, a diagnostic must always be issued by a conforming implementation. This is normative behavior as per C17 5.1.1.3. See What must a C compiler do when it finds an error?
For example, the empty declaration list in the code above has always been a constraint violation (since C89)
I think so too. The C90 6.7.1 constraints say
If the declarator includes an identifier list, each declaration in the declaration list shall have at least one declarator, and those declarators shall declare only identifiers from the identifier list
In your example a is an identifier.
So, would a pre-1999 ANSI-conformant compiler have still issued a diagnostic in this case?
The difference between C90 and C99 is the syntax. C90 6.7.1 says declaration-specifiersopt and C99 6.9.1 says declaration-specifiers, no longer optional. Both standards has the declaration-listopt as optional, but as per the previously quoted constraints, there must be a declaration list in case a declaration with a named identifier is present.
I guess some compilers may have read the optional part in the syntax like "in C90 you could omit both the declaration specifiers and the declaration list", which agrees with the syntax but not the constraints. It's a bit ambiguous, particularly since C90 6.7.1 also explicitly states:
Any parameter that is not declared has type int.
This part was removed in C99.

What is the default type for C const?

I was writing some C code, and noticed what I thought to be an error, but was not. I had the following type declaration statement.
const fee;
However, it was uncaught initially because the compiler and I didn't catch it. So I was curious as to why C allows this and what is the default type.
Only the original version of C language standard (ANSI/ISO C89/90) allows this. Such variable declaration defaults to type int in accordance with "implicit int" rule. That rule was present in C since the beginning of time. That's just how the language was originally defined.
Note that the declaration-specifiers portion of a declaration cannot be omitted completely, e.g. a mere
fee;
does not declare an int variable. It is illegal even in the original C. But once you add some sort of declaration specifier or qualifier, the declaration becomes legal and defaults to int type, as in
static fee;
const fee;
register fee;
However, all this is illegal in C99 and in later versions of language, since these versions of language specification outlawed "implicit int".

What does it mean to declare a variable with a storage class specifier but no type specifier?

After reading through the ANSI C Yacc grammar specification I noticed the following are all valid:
register x;
auto y;
static z;
extern q;
This seems strange to me, as my understanding of type would suggest that none of these variables have a type. What do these mean? How are they type checked? How much memory is allocated?
Before C99 if a type was not specified it defaulted to int this was supposed to be removed in C99 but many compilers support it even in C99 mode. For example in clang even using -std=c99 I only receive the following warnings as opposed to errors:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
register x;
~~~~~~~~ ^
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
auto y;
~~~~ ^
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static z;
~~~~~~ ^
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
extern q;
~~~~~~ ^
gcc also only provides a warning in this case, although using the -pedantic-errors flag will cause gcc to produce errors which is usually the case for extensions in gcc and usually for clang to but not in this case.
If we look at the draft C99 standard the Forward section says:
[...]Major changes from the previous edition include:
and includes the following bullet:
— remove implicit int
Update
From the Rationale for International Standard—Programming Languages—C section 6.7.2 Type specifiers:
new feature of C99: In C89, all type specifiers could be omitted from the declaration
specifiers in a declaration. In such a case int was implied. The Committee decided that the
inherent danger of this feature outweighed its convenience, and so it was removed. The effect is to guarantee the production of a diagnostic that will catch an additional category of programming errors. After issuing the diagnostic, an implementation may choose to assume an implicit int and continue to translate the program in order to support existing source code that exploits this feature.
The grammar you are using does predate C99 but as far as I can tell a newer version which is updated to reflect C11 does not differ much with respect to type specifiers in a declaration. So the grammar in this situation is not sufficient to enforce this constraint. You would have to goto the standard section 6.7.2 Type specifiers and see that it says:
At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name.

Is implicit function declaration legal in C89?

Consider this C program:
int main()
{
puts("Hello world!");
return 0;
}
This compiles and runs fine and as far as I understand, is legal C89. However, I'm not 100% sure about that. Compiling in C99 mode with clang informs me that implicit declaration of function 'puts' is invalid in C99 (which makes me think that the C standard must have changed in C99 to make implicit function declaration illegal, which is what I'm trying to confirm).
Is implicit function declaration legal in C89? (even if it's a bad idea to do it (unless your in an obfuscated C code challenge))
Is implicit function declaration legal in C89?
Yes. From section 3.3.2.2:
If the expression that precedes the parenthesized argument list in
a function call consists solely of an identifier, and if no
declaration is visible for this identifier, the identifier is
implicitly declared exactly as if, in the innermost block containing
the function call, the declaration
extern int identifier();
appeared.
Implicit declaration of function is legal in C89, but is removed in C99. This can be confirmed in C11(ISO/IEC 9899:201x) standard.
In the C11 Forward section, it lists all the major changes in the third edition(i.e, C11) and the second edition(i.e, C99), one of which is:
Major changes in the second edition included:
...
— remove implicit function declaration
Also in Rationale for International Standard Programming Languages C §6.5.2.2 Function calls
A new feature of C99: The rule for implicit declaration of functions has been removed in C99. The effect is to guarantee the production of a diagnostic that will catch an additional category of programming errors. After issuing the diagnostic, an implementation may choose to assume an implicit declaration and continue translation in order to support existing programs that exploited this feature.

Anybody knows why is this compiling successfully?

Anybody knows why is this compiling successfully in C?
int main(){
display();
return 0;
}
void display(){
printf("Why am I compiling successfully?");
}
I thought when declaration is not provided C assume extern int Function_name(arg1,arg2,...){}. Thus this should give an error but however it's working! I know that Ideone is supressing the warnings but my question is why is it just not giving a straight error? (however in C++ it's straight error)
Turn up the warning level in your compiler and you should get 2 warnings,
display not declared, int assumed
and
display redeclared
Edit:
Older versions of C (pre C99) aren't really that bothered about return types or argument types. You could say it's part of the K&R legacy. For instance, if you don't explicitly specify the argument types, the compiler won't check them at all.
C++ is stricter, which IMO is a good thing. I always provide declarations and always specify the argument lists when I code in C.
It's compiling because C uses a lot of defaults to be backwards compatible. In K&R C, you couldn't specify function prototypes, so the compiler would just assume that you know what you're doing when you call a function.
Later (at least ANSI C, but maybe even in C99), C didn't really have a way to distinguish
void display(void);
void display();
so the empty declaration must be accepted as well.
That's why you can call display() without defining it first.
printf() is similar. You will get a linker error if you forget -lc but from the compiler's point of view, the code is "good enough".
That will change as soon as you enable all warnings that your compiler has to offer and it will fail with an error when you disable K&C compatibility or enable strict ANSI checks.
Which is why "C" is often listed as "you shoot yourself into the foot" in "How to Shoot Yourself In the Foot Using Any Programming Language" kind of lists.
it depends of your Cx (C89, C90, C99,...)
for function return values, prior to C99 it was explicitly specified that if no function declaration was visible the translator provided one. These implicit declarations defaulted to a return type of int
Justification from C Standard (6.2.5 page 506)
Prior to C90 there were no function prototypes. Developers expected to
be able to interchange argu-ments that had signed and unsigned
versions of the same integer type. Having to cast an argument, if the
parameter type in the function definition had a different signedness,
was seen as counter to C’s easy-going type-checking system and a
little intrusive. The introduction of prototypes did not completely do
away with the issue of interchangeability of arguments. The ellipsis
notation specifies that nothing is known about the 1590 ellipsis
supplies no information expected type of arguments. Similarly, for
function return values, prior to C99 it was explicitly specified that
if no function declaration was visible the translator provided one.
These implicit declarations defaulted to a return type of int . If the
actual function happened to return the type unsigned int , such a
default declaration might have returned an unexpected result. A lot of
developers had a casual attitude toward function declarations. The
rest of us have to live with the consequences of the Committee not
wanting to break all the source code they wrote. The
interchangeability of function return values is now a moot point,
because C99 requires that a function declaration be visible at the
point of call (a default declaration is no longer provided)
It probably does (assume such declaration as you wrote), but as you are not passing parameters, it just works fine. It's the same like if you declare int main() where it should actually be int main(int argc, char *argv[]).
So probably if you tried to pass some parameters (different from default ones) from main then use them in display it would fail.
BTW, for me it compiles, but generates warning:
$ gcc z.c
z.c:8:6: warning: conflicting types for ‘display’ [enabled by default]
z.c:4:5: note: previous implicit declaration of ‘display’ was here
When I compile with gcc, I get warnings about redeclaration of display, as you would expect.
Did you get warnings?
It might "run" because C doesn't mangle function names (like C++). So the linker looks for a symbol 'display' and finds one. The linker uses this address to run display. I would expect results to not be what you expect all the time.

Resources