0

It was long time since I coded in C and now I can't even create linked list :( What might be wrong with NodeType structure ? I even tried this example and still I get error similar to this.

I need to create linked list that would run on linux and windows (without huge modification).

I compile using: cl myFile.c command.

Error message:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved.

unlock.c unlock.c(46) : error C2275: 'Node' : illegal use of this type as an expression unlock.c(17) : see declaration of 'Node' unlock.c(46) : error C2146: syntax error : missing ';' before identifier 'a' unlock.c(46) : error C2065: 'a' : undeclared identifier

Source code:

#include <stdio.h>
#include <windows.h>
#include<stdlib.h>


typedef enum {STABLE, RPUSH, LPUSH} STATUS_TYPE;


typedef struct NodeType
{
    struct NodeType* _left;
    struct NodeType* _right;
    int _value;
}Node;

typedef struct AnchorType
{
    struct Node* _mostLeft;
    struct Node* _mostRight;
    STATUS_TYPE _status;
} Anchor;

Node CreateNode(int data)
{
    Node newNode;
    newNode._value = data;
    newNode._left = NULL;
    newNode._right = NULL;

    return newNode;
}


int main()
{
    Anchor anchor;
    anchor._mostLeft = NULL;
    anchor._mostRight = NULL;
    anchor._status = STABLE;


    Node a; //<-- What might be wrong ?

    return 0;
}

Thanks for help.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Full_Int
  • 319
  • 4
  • 13
  • 1
    note that `_mostLeft` and `mostRight` members in the definition of `struct AnchorType` should be declared as just `Node*` or `struct NodeType *`. – pb2q Sep 26 '12 at 18:36
  • Possibly some garbage from `windows.h` messes up things. If you remove that include, does it compile then? (It ought to, since it's legal C, though pb2q points out a mistake you made.) – Daniel Fischer Sep 26 '12 at 18:36
  • @DanielFischer: It's legal C99, but his compiler doesn't support C99. The program is NOT legal C89/C90. – Ben Voigt Sep 26 '12 at 18:43
  • @BenVoigt Ah, always forget about the Microsoft compiler being C89. – Daniel Fischer Sep 26 '12 at 18:47

2 Answers2

3

Microsoft focuses on C++ compilers, and their C support is decades out of date.

One of the features of the newer C standards that isn't supported in Microsoft's compiler is the ability to declare variables in the middle of a function.

Move the declaration to the top, and everything will be ok:

int main()
{
    Anchor anchor;
    Node a; // ok here
    anchor._mostLeft = NULL;
    anchor._mostRight = NULL;
    anchor._status = STABLE;


    //Node a; but not here

    return 0;
}
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • How could I forget about variable declaration in C ... Thanks. – Full_Int Sep 26 '12 at 18:47
  • it's not really a flaw; any portable c program should declare before assigning, it's only common sense and makes it easier to reason about local stack organization. also, they do support declaring in middle of scopes using anonymous scopes; `{ declare; assign; use; }` – Dmytro Dec 14 '17 at 20:46
  • @Dmitry: Regardless of your preference, both the C++ and C standards committee thought that allowing variable declarations to be intermixed with statements was important enough to make it legal. Deeply-nested statement blocks harm readability, so adding them whenever it is desired to introduce new variables is not ideal. – Ben Voigt Dec 14 '17 at 20:54
  • @ben that's preference; I find adding anonymous scopes to add readability because you limit the lifetime of your variables explicitly, thus letting the reader know when a variable is no longer relevant to the scope. In many scopes, variables defined half way in are immediately used and are never referenced for over 300 lines; a small anonymous scope would let the reader know when the variable is no longer relevent. Especially when calling windows api functions that require an out variable, that you create a dummy for, and never use it after. – Dmytro Dec 15 '17 at 03:01
  • @Dmitry: Yes, and I preserve to save nested scopes for short-lived variables, which means not using them for every variable introduced mid-function. – Ben Voigt Dec 15 '17 at 16:45
0

The problem is that you have the structure tag as NodeType, but the typedef tag as Node. Both should refer to the same thing. Such as:

typedef struct Node
{ 
    struct Node* _left; 
    struct Node* _right; 
    int _value; 
} Node;

This creates a typedef named Node that is a struct Node.

In Microsoft compiler targeted code, you usually see this:

typedef struct Node
{ 
    struct Node* _left; 
    struct Node* _right; 
    int _value; 
} tagNode;

typedef struct Anchor
{ 
    struct Node* _mostLeft; 
    struct Node* _mostRight; 
    STATUS_TYPE _status; 
} tagAnchor; 

tagNode will never be used in Microsoft compiler code, just Node. The Microsoft compiler will be very happy with this, and people reading your code will know you are referring to the structure.

For more detailed information including the history of C and C++ naming of typedefs and tags, see the anwser posted at: Difference between 'struct' and 'typedef struct' in C++?

StarPilot
  • 2,246
  • 1
  • 16
  • 18