16

I want to assign a particular value to a (user defined) global variable in C programming language. When I am doing this from within any other function or main it is fine. But when I am doing it from global space (outside of any function) it is giving the following compilation error:

[expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token]

Following is a code snippet which causing issue:

#include <stdio.h>
#define MAX_SIZE 5

typedef struct
{
    int val[MAX_SIZE];
    int top;
}stack_t;

stack_t s;
s.top = -1;  // <== Initialization from here is causing compilation error

main()
{
    //s.top = -1; < === Initialization from here is fine  
    printf("s.top =%d\n", s.top);
    return 0;
}

But same kind of assignment for integer variables is not giving only warning

#include <stdio.h>

int i,j,k,l;
k=10;
main()
{
        printf("i= %d, j=%d k=%d l=%d\n", i, j, k, l);
        return 0;
}

Can anyone please tell the reason for this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
sudhir
  • 179
  • 1
  • 6
  • these lines: stack_t s; s.top = -1; are not initialization. Initialization would be: stack_t s = { "", -1}; actual executable code, such as the second line (s.top = -1;) is executable assignment, not initialization. – user3629249 Dec 27 '14 at 08:57
  • Related, about tentative definitions: http://stackoverflow.com/questions/3095861/about-tentative-definition – Thomas Padron-McCarthy Dec 27 '14 at 08:57

5 Answers5

15

The error from the assignment of s.top is not surprising. It is not an initialization but an assignment, and those are different concepts in C. You can't have assignments outside of functions.

The interesting part here is that it looks like you can do an assignment of the integer variable k. But that is an illusion, since in that case it's not an assignment but an initialization!

The line

k = 10;

is interpreted not as an assignment but as a variable definition. A hint to this is that GCC gives the warnings "data definition has no type or storage class" and "type defaults to 'int' in declaration of 'k'". So the line could be written as

int k = 10;

As Matt wrote in a comment below, leaving out the data type like this seems to be a GCC extension, and not something that the standard allows.

(By the way, do turn on warnings in your compiler, and pay attention to them!)

But wait, wasn't there already a definition of k on the line above, and you can't have more than one definition, can you?

First, remember that C makes a distinction between definitions and declarations. A definition of a variable is when you "create" the variable, and optionally give it an initial value. A declaration is when you just tell the compiler that the variable exists, and its name and data type, but the definition is elsewhere. You can have both a definition and one or more declarations of the same variable. For example:

int xxx = 10; // This is the definition of xxx
int xxx; // This is a declaration of xxx
int xxx; // Another delaration of xxx

But sometimes the compiler can't determine if what it sees is a declaration or a definition, and then it is interpreted as a "tentative definition", or in other words "perhaps a definition, perhaps just a declaration, we'll decide later". For example:

int yyy;

Is that a definition of the variable yyy (without an initial value), or is it just a declaration, where the definition will be found elsewhere? The compiler doesn't know, so it waits to decide, and calls this a tentative definition.

When the compiler sees your first declaration of k (along with the other variables i, j and l) it is interpreted as a tentative definition, and when the later definition is found, that tentative definition of k will be decided to be a declaration, not a definition.

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
  • 1
    Treating `k=10;` as a definition is a GCC extension; it's not permitted in Standard C. See 6.7.2/2 "At least one type specifier shall be given in the declaration specifiers in each declaration". – M.M Dec 27 '14 at 11:54
  • 1
    I think it was legal in C89 actually - certainly not in C99 and C11 however – M.M Dec 27 '14 at 12:03
  • @ThomasPadron-McCarthy : Thanks for your crystal clear explanation – sudhir Dec 28 '14 at 14:00
8

Initializing the outside the main is reason for that error. You can do that using like this.

stack_t s={.top=-1};

It will allow you to do the initialization while declaring. Refer this link. or this It can be useful.

Community
  • 1
  • 1
Karthikeyan.R.S
  • 3,991
  • 1
  • 19
  • 31
  • :thanks for your response, i know that we can initialization while declaring is possible. But in case of integer variables compiler is not throwing error – sudhir Dec 27 '14 at 05:18
  • 1
    @sudhi A normal variable you do like this `int a; a=10;` It will give the warning `data definition has no type or storage class [enabled by default]`. – Karthikeyan.R.S Dec 27 '14 at 05:25
  • I'm also very curious as to why initializing outside main() is causing that compilation error. – Andy J Dec 27 '14 at 05:28
8

C code has to be inside a function. You can declare a global outside of a function but you can't write an assignment statement outside of a function. That is you can set the initial value as part of declaring the struct but you can't then change it. Here your declaration is only the "stack_t s;" line.

Everything in C ends up compiling to symbols in a binary format (an example would be the ELF format). Symbols have names, so functions are named chunks of code, and globals are named chunks of data. There are no "free floating" chunks in the compiled binary, everything has to go under a name.

In the C model, code floating around outside of a function doesn't make sense because C doesn't have a place where it would run that code. C never runs a file in the way that bash or Python or javascript does; it only runs binaries. So it only runs named functions. The files are only known at compile time not runtime.

Havoc P
  • 8,365
  • 1
  • 31
  • 46
1

There are differences between assignment and initialization. You should note that, assignment can't be done outside of a function. The statement

s.top = -1;  

is an assignment not an initialization.

C99 and latter provides designated initialization of structs and arrays. So, you can initialize only the top member of struct s as

stack_t s = { .top = -1 };   

and other members will be initialized to 0 by the compiler.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
0

In the global space you can only initialize and declare the variables but cannot assign the value to variables. In your code you are assigning the value to member of struct so its throwing error and same holds true for integers for your below code.

Try the below code in the global space and it works fine:

typedef struct 
{
     int val[MAX_SIZE];
     int top;
}stack_t;

stack_t s={{},-1};

main()
{
    printf("s.top=%d",s.top);
    return 0;
}
Shivakumar
  • 427
  • 2
  • 15