0

Question: Is it me, or do both GCC and Clang have not quite correct error messages when assessing particular global char declarations in C?

---And a particular note regarding a similar question is that I'm looking for clarification regarding why the char declaration is getting this reaction. There are related questions, yes, but all I saw there was int declarations.

$ gcc --version gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0

$ clang --version clang version 10.0.0-4ubuntu1

Consider the following C code, able.c:

#include <stdio.h>
char able;
able = 'X';
int main(void)
{
    printf("%c", able);
}

A first note is that yes, combining the declaration and the initialization of able is much more efficient. However, when run through GCC and Clang, the error messages that turn up seem to me to be, basically, incorrect messages:

$ clang -Weverything able.c 

able.c:5:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
able = 'X';

^
able.c:5:1: error: redefinition of 'able' with a different type: 'int' vs 'char'

able.c:3:6: note: previous definition is here

char able;

     ^

able.c:3:6: warning: no previous extern declaration for non-static variable 'able' [-Wmissing-variable-declarations]

char able;

     ^

able.c:3:1: note: declare 'static' if the variable is not intended to be used outside of this translation unit

char able;

^

2 warnings and 1 error generated.
$ gcc -Wall -Wextra -Wpedantic able.c 

able.c:5:1: warning: data definition has no type or storage class

    5 | able = 'X';

       | ^~~~

able.c:5:1: warning: type defaults to ‘int’ in declaration of ‘able’ [-Wimplicit-int]

able.c:5:1: error: conflicting types for ‘able’

able.c:3:6: note: previous declaration of ‘able’ was here

    3 | char able;

       |      ^~~~

Both sets of messages complain about a missing type specifier, except that the type specifier---char---is indeed right there. When the declaration and initialization messages are combined in that spot, above/before the main function, the program compiles. When the pair of messages are placed in the main function, even without being combined, the program also compiles.

So the char able; statement is perfectly fine, so why those error messages?

  • Please format your code properly – klutt Aug 06 '20 at 10:53
  • It's not odd behavior in C. Global variables i.e. any variables appearing outside the function can only be given initial value with initialization. It cannot be re-defined with other value outside the function, however, inside any function, we can change its value. – Sourabh Choure Aug 06 '20 at 11:00

4 Answers4

1

You can't do

char able;
able='X';

on file scope.

You can only do it in one line, not split, like you are used in functions. The C compiler thinks:

char able; //Declare a variable of type char with name able.
able = 'X'; //Assign the ASCII-value of 'X' to a variable called able of type `int`.

The int is implicit because of backwards compatibility with really old versions. (Because of this you will sometimes see main() instead of int main(void)).

Furthermore, you have now two variables of the same name. This leads to this error:

redefinition of 'able' with a different type: 'int' vs 'char'

Edit:

Here an excerpt from the C specification (Draft): Annex A, A.1 (Lexical grammar), A.2.4 (External Definition)

translation-unit: //Essentially a file
           external-declaration
           translation-unit external-declaration
external-declaration:
           function-definition
           declaration //The interesting one
declaration: //A 2.2 (Declarations)
     declaration-specifiers init-declarator-list[opt];//init-declarator-list is optional
     static_assert-declaration//Not interesting here

declaration-specifiers:
    storage-class-specifier declaration-specifiers[opt]
    type-specifier declaration-specifiers[opt]
    type-qualifier declaration-specifiersopt
    function-specifier declaration-specifiers[opt]
    alignment-specifier declaration-specifiers[opt]

As you can see here in the grammar, there is no place on translationunit-base for only an assignment.

JCWasmx86
  • 3,473
  • 2
  • 11
  • 29
0

As statements are not allowed in file scope the compiler tries to interpret this statement

able = 'X';

as a declaration. But it does not find a type specifier. So it issues the message

able.c:5:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
able = 'X';

After it inserted the default type specifier int it sees that the name able is declared twice like

char able;
int able = 'X';

where int is the type specifier inserted by the compiler by default.

So the compiler issues the message

able.c:5:1: error: redefinition of 'able' with a different type: 'int' vs 'char'

able.c:3:6: note: previous definition is here

char able;

     ^

Inside block scope you may place declarations and statements. So this code snippet

char able;
able = 'X';

placed in a function block scope will compile successfully.

From the C Standard (6.8 Statements and blocks)

3 A block allows a set of declarations and statements to be grouped into one syntactic unit.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

The compile gives error as able='X' is never executed by the program. (C program acts sequentially inside the functions only. For global variables only the declaration with/without initialization is considered.

#include <stdio.h>
char able;
able = 'X';    //This statement is never executed
int main(void)
{
    printf("%c", able);
}

A similar question can be found at: Why can't I assign values to global variables outside a function in C?

Sourabh Choure
  • 723
  • 4
  • 15
0
 able = 'X';

You cant have any code or assignments outside the functions. compiler treats it as new definitions with implicit int type. The assignment has to be in the function body as in the example.

#include <stdio.h>
char able;

void foo()
{
    able = 'X'; 
}

int main(void)
{
    foo();
    printf("%c", able);
}

https://godbolt.org/z/dea7q7

0___________
  • 60,014
  • 4
  • 34
  • 74