Smiley
Smiley

Reputation: 75

Typedef is declared in other header, is included in necessary files, however produced: Error[Pe020]: identifier "" is undefined. Why?

Let's say I have the project in C in IAR, and I'm working with these 4 files. I have a header for defines, and another header for extern functions. I also have two .c files, one for main, and one for functions, as shown below.

First header file: header1.h

#ifndef __HEADER1_H
#define __HEADER1_H

#include "header2.h"
#include "otherheader.h"

// bunch of 'define' here
typedef uint8_t   macAddr[8];
#endif

Another header file: header2.h

#ifndef __HEADER2_H
#define __HEADER2_H

//other extern functions here
extern void getMAC(macAddr deviceAddr);
#endif

main.c file here:

#include "header1.h"
void main ()
{
    macAddr dev1Address = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    getMAC(dev1Address);
}

function.c file here:

#include "header1.h"
void getMAC(macAddr deviceAddr)
{ 
  uint8_t transmit[8];
  for (int i = 0; i<8; i++)
      transmit[i] = deviceAddr[i];
}

The error reported is this:

Error[Pe020]: identifier "macAddr" is undefined 

I'm having a little trouble understanding why this does not work. The first header (where macAddr is defined) includes the second header (where getMac() function is declared), and the first header is included in main.c as well as function.c. As far as I understand, there is no circular includes (as other questions suggested... correct me if I'm wrong, and show me how)

Upvotes: 1

Views: 1119

Answers (1)

user694733
user694733

Reputation: 16043

Problem is that header1.h includes header2.h, but header2.h requires macAddr which is not yet defined.


Rule of thumb is that each file should include only the files it needs. Thus:

  • header1.h has a single typedef. It should only include stdint.h.
  • header2.h needs macAddr to work, thus it should include header1.h.
  • main.c uses getMAC, so it should include header2.h. header1.h is already included, so no need to include it.
  • function.c strictly only needs header1.h, but it's good practice to make sure that function declaration and definition match, so it should include header2.h instead.

It seems like header1.h is used as a monolith header that is used to include everything (It's hard to be sure because your example has so few files). This is a very bad practice. It can increase compilation times, and makes refactoring hard since dependencies are difficult to track.

Ideally each header should only have single well defined responsibility. It's not always possible, but it's a good goal.

Circular includes are not a huge issue as long as you use header guards as you have, and not include everything everywhere unless it's needed. Sometimes you might need to add extra forward declarations, but that's about it.


Here's some additional notes:

  • As user3629249 and others noted, you really shouldn't declare symbols starting with _ underscore. These are reserved for C standard or compiler use.

  • I don't recommend using typedef on arrays (or pointers). Arrays decay to pointer in some cases without telling you, so when using typedef this is hidden from user and can cause bugs with careless use. I would wrap it struct instead:
    typedef struct { uint8_t address[8]; } MAC_T;

Upvotes: 1

Related Questions