2

I have a pointer to a struct of type Map defined in an external header file:

typedef struct {
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
} Map;

The pointer is initialised as follows:

    struct Map *map_ptr;    
    map_ptr = create_map(*w_ptr, *h_ptr);
    // create_map returns Map*, w_ptr and h_ptr are pointers to height and width fields for a map/maze.

How do I go about printing the values of width and height stored within the Map structure which is created in create_map? create_map is held in an external file and the only variable it passes back to main is the pointer to the map.

The following gives an error when compiling ("error: dereferencing pointer to incomplete type")

printf("Height = %d\n", map_ptr->height);

As far as I know, the pointer is valid as the code below prints a memory address:

printf("Pointer address for map = %p\n", map_ptr);
4
  • 5
    How does it not work? Does it not do anything? Does it crash? What happens? Commented Dec 30, 2012 at 22:19
  • See also this question. Commented Dec 30, 2012 at 22:51
  • C nit: %p args must be (cast to) ptr-to-void otherwise you invoke undefined behavior. Commented Dec 30, 2012 at 23:03
  • See also this link, or the sample code below: publib.boulder.ibm.com/infocenter/comphelp/v8v101/… Commented Dec 31, 2012 at 1:28

4 Answers 4

5

Just drop the struct keyword from:

struct Map *map_ptr;    

to:

Map *map_ptr;    

You have declared a nameless struct and typedef'ed it to Map. So when you declare struct Map *map_ptr;, compiler thinks this is another struct called Map.

Sign up to request clarification or add additional context in comments.

Comments

2

You tripped over what is called namespaces in C. There are separate namespaces for

  • typedef names, as you introduced with typedef struct { ... } Map;
  • struct tags, as you introduced with struct Map *map_ptr;
  • plus other namespaces for objects, macro names, ...

The same indentifier can be reused in different namespaces. I recommend to never bother with typedefs for structs. It only hides useful information, and all it does it saving you from writing struct every now and then. If something is a struct or pointer to a struct then I want to know it so I know whether to use -> or . to access the members. Using typedefs defeats this by hiding useful information.

One way to fix your problem is to get rid of the typedef and only use a struct tag with

struct Map {
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
};
struct Map *map_ptr = ...;

1 Comment

Very, very good point - thank you. I should emphasize that the C concept of "namespace" does not correspond to C++ "namespaces". The two are different. Here's a link: publib.boulder.ibm.com/infocenter/comphelp/v8v101/…
0

Here is a complete example that might help clarify a few points:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

typedef struct {
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
} Map;


Map *
create_map ()
{
  printf ("Allocating %d bytes for map_ptr, and %d bytes for map data...\n",
    sizeof (Map), 100);
  Map *tmp = (Map *)malloc(sizeof (Map));
  tmp->squares = (char *)malloc (100);
  strcpy (tmp->squares, "Map data...");
  tmp->width = 50;
  tmp->height = 100;
  return tmp;
}

int 
main(int argc, char *argv[])
{
  Map *map_ptr = create_map();
  printf ("map_ptr->height= %d, width=%d, squares=%s\n",
    map_ptr->height, map_ptr->width, map_ptr->squares);
  free (map_ptr->squares);
  free (map_ptr);
  return 0;
} 

EXAMPLE OUTPUT:

Allocating 12 bytes for map_ptr, and 100 bytes for map data...
map_ptr->height= 100, width=50, squares=Map data...

An alternative approach would be to use "struct Map {...}" instead of the typedef:

EXAMPLE:

struct Map {
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
} Map;


struct Map *
create_map ()
{
...
  struct Map *tmp = (struct Map *)malloc(sizeof (struct Map));
  ...
}
  ...
  struct Map *map_ptr = create_map();
  printf ("map_ptr->height= %d, width=%d, squares=%s\n",
    map_ptr->height, map_ptr->width, map_ptr->squares);
  free (map_ptr->squares);
  free (map_ptr);

Comments

0

Answer 1:

struct Map *map_ptr; 

to

Map *map_ptr; 

Answer 2:

typedef struct {
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
} Map;

to

struct Map{
    char *squares; //!< A pointer to a block of memory to hold the map.
    int   width;   //!< The width of the map pointed to by squares.
    int   height;  //!< The height of the map pointed to by squares.
} ;

Reason :

if typedef struct{...}  B; 

so

B == struct B{...}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.