I am attempting to create a type in C that can accept most primitive types. I am new to C and don't understand structs very well. My error occurs on line 10 (of main.c) and it will also occur on line 11 if line 10 is removed (also of main.c). If anyone has an ideas/pointers I would really appreciate it! Many thanks!
main.c:
#include <stdio.h>
#include "modularType.h"
int main()
{
int data = 1;
PyType object = createPyObjectInt(data);
printf("Type of data: %d\n", object->typeOfData);
printf("Value of data: %d\n", object->intData);
return 0;
}
modularType.h:
typedef struct pytype *PyType;
PyType createPyObjectEmpty(void);
PyType createPyObjectInt(int data);
void setDataInt(PyType, int data);
void setDataIntStar(PyType, int* data);
void freeMyType(PyType);
void freeCharStar(PyType);
void freeIntStar(PyType);
void freeFloatStar(PyType);
modularType.c:
#include <stdlib.h>
#include <stdio.h>
#ifndef NEW_TYPE
#define NEW_TYPE
#include "modularType.h"
typedef enum
{
NO_DATA,
REG_CHAR,
CHAR_STAR,
REG_INT,
INT_STAR,
REG_FLOAT,
FLOAT_STAR,
}types;
struct pytype
{
//The number of data types i can hold here
unsigned char typeOfData: 3;
union
{
char charData;
char* charStarData;
int intData;
int* intStarData;
float floatData;
float* floatStarData;
}
};
PyType createPyObjectEmpty(void)
{
PyType object;
object = malloc(sizeof(*object));
object->typeOfData = NO_DATA;
return object;
}
PyType createPyObjectInt(int data)
{
PyType object;
object = malloc(sizeof(*object));
object->intData = data;
object->typeOfData = REG_INT;
return object;
}
void setDataInt(PyType object, int data)
{
object->intData = data;
object->typeOfData = REG_INT;
}
void setDataIntStar(PyType object, int* data)
{
object->intStarData = data;
object->typeOfData = INT_STAR;
}
#endif
As a side note my compilation command (gcc -Wall -std=c99 -o modType main.c modularType.c) produces the following warning: modularType.c:35:1: warning: no semicolon at end of struct or union. I thought that I had formatted my struct correctly but I have also seen people define structs as following:
typedef struct pytype
{
//code here
}PyType;
Is this a better way or is the way I am doing it fine?
The problem you have is one of scope. That is an intentional and inherent part of C. The approach you are trying to take is one of data encapsulation or data hiding. You intentionally declare the
struct
inmodularType.c
which provides file scope for the struct.struct pytype
is never exposed inmain.c
making it impossible to directly reference the members of the struct (e.g.object->foo
) inmain.c
. That is by design. That is how you intentionally hide the members ofpytype
from being directly accessed inmain
.To do what you are attempting, you need to expose functions through
modularType.h
that retrieve the information you want from yourstruct pytype object
. For example, you want retrieve the value forobject->typeOfData
andobject->intData
. To do that inmain
, you simply need functions that provide access to that data. InmodularType.c
you could add:Then in
modularType.h
you could provide the function prototypes that will expose the functions tomain
, e.g.Since both functions are in
modularType.c
, they have access to the members ofstruct pytype
while anything else inmain
does not. After making the following modifications tomain.c
You will be able to return the values you desire, e.g.:
Example Use/Output
Footnote 1: While not an error, the standard coding style for C avoids the use of
caMelCase
orMixedCase
variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you, but failing to follow it can lead to the wrong first impression in some circles.You 2 problems:
This part from
modularType.c
belongs to the beginning ofmodularType.h
and you are missing an;
(see comment int the snippet right below).The header guard belongs into
modularType.h
and not intomodularType.c
This is however not a problem right now. It doesn't prevent your files from compiling, it's just completely useless to put a header guard into a .c file.
The way you've done it is fine, except for 2 things.
1) You really shouldn't make it a typedef to a pointer of a struct unless you make it clear from the name that is what it is. Change it to
typedef struct pytype PyType;
2) Your header should also include the definitions of
struct pytype
and the enum as well so that any file that includes it knows what they are.The structure definition is incomplete in the header file, so you cannot refer to any struct members in your code. The compiler complains that it does not know about any struct members at all.
An incomplete structure definition is one where you do not provide the list of members for the implementation. Such a definition allows you to manipulate pointers to such structures, but not access any members since they are not explicitly defined and the compiler needs to know their type and offset from the beginning of the structure to generate the corresponding code.
Also not that the typedef
PyType
hides a pointer to astruct pytype
. It is error prone to hide pointers behind typedefs, leading to confusing code for both the programmer and the reader.