Having trouble declaring and initializing a global structure - c

In h.c file:
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
extern YS y;
In m.c file:
#include "h.c"
int void main()
{
YS y = malloc(sizeof(YS));
y.x_array[0].x = 1;
free(y);
return 0;
}
This won't compile and I cannot figure out why. Could someone shed some light on this?

your main must look like this:
#include "h.h"
int main()
{
YS *y = malloc(sizeof(YS));
y->x_array[0].x = 1;
free(y);
return 0;
}
In h.h file:
#ifndef H_H
#define H_H
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
#endif

There are multiple issues with your code:
1. In h.c, you declare YS y as extern which means the compiler expects a external global declaration for y. But you've declared it as a local object in m.c
You are trying to malloc for a static object.
h.h
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
YS *y;
m.c:
#include <stdlib.h>
#include "h.h"
extern YS *y;
int void main()
{
y = malloc(sizeof(struct YS));
y->x_array[0].x = 1;
free(y);
return 0;
}

Related

Why can't I create an opaque data type?

I'm trying to experiment with opaque data types to get an understanding of them. The main problem is that I keep getting an 'incomplete' error.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}
fnarpishnoop.c
#include "blepz.h"
struct noobza {
int fnarp;
};
void setfnarp(struct noobza x, int i){
x.fnarp = i;
};
int getfnarp(struct noobza x){
return x.fnarp;
};
blepz.h
struct noobza;
void setfnarp(struct noobza x, int i);
int getfnarp(struct noobza x);
struct noobza GOO;
I clearly don't understand something here and I was hoping someone could help me figure out how opaque data types are implemented if the whole point of them is that you have a hard time finding actual code for them.
Using a struct that you haven't declared the contents of gives an "incomplete type" error, as you have already mentioned.
Instead, use a pointer to the struct and a function that returns a pointer to the struct, like this:
struct noobza;
struct noobza *create_noobza(void);
void setfnarp(struct noobza *x, int i);
int getfnarp(struct noobza *x);
struct noobza *GOO;
...
#include <stdlib.h>
#include "blepz.h"
struct noobza {
int fnarp;
};
struct noobza *create_noobza(void)
{
return calloc(1, sizeof(struct noobza));
}
void setfnarp(struct noobza *x, int i){
x->fnarp = i;
};
int getfnarp(struct noobza *x){
return x->fnarp;
};
...
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
GOO = create_noobza();
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}

Why do I keep getting "error: variable has incomplete type 'struct intVec'?

I'm doing an assignment for my data structures class and I have very little experience with C structures and C in general.
This is the .h file that I was given to do the assignment:
#ifndef C101IntVec
#define C101IntVec
typedef struct IntVecNode* IntVec;
static const int intInitCap = 4;
int intTop(IntVec myVec);
int intData(IntVec myVec, int i);
int intSize(IntVec myVec);
int intCapacity(IntVec myVec);
IntVec intMakeEmptyVec(void);
void intVecPush(IntVec myVec, int newE);
void intVecPop(IntVec myVec);
#endif
This is the .c implementation that I've made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intVec.h"
typedef struct IntVecNode {
int* data;
int sz; // Number of elements that contain data
int capacity; // How much is allocated to the array
} IntVecNode;
typedef struct IntVecNode* IntVec;
//static const int intInitCap = 4;
int intTop(IntVec myVec) {
return *myVec->data;
}
int intData(IntVec myVec, int i) {
return *(myVec->data + i);
}
int intSize(IntVec myVec) {
return myVec->sz;
}
int intCapacity(IntVec myVec) {
return myVec->capacity;
}
IntVec intMakeEmptyVec(void) {
IntVec newVec = malloc(sizeof(struct IntVecNode));
newVec->data = malloc(intInitCap * sizeof(int));
newVec->sz = 0;
newVec->capacity = intInitCap;
return newVec;
}
void intVecPush(IntVec myVec, int newE) {
if (myVec->sz >= myVec->capacity) {
int newCap = myVec->capacity * 2;
myVec->data = realloc(myVec->data, newCap * sizeof(int));
} else {
for (int i = 0; i < myVec->capacity; i++) {
*(myVec->data + i) = *(myVec->data + i + 1);
}
myVec->data = &newE;
}
myVec->sz++;
}
void intVecPop(IntVec myVec) {
for (int i = 0; i < myVec->capacity; i++) {
*(myVec->data - i) = *(myVec->data - i + 1);
}
myVec->sz--;
}
This is the test file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intVec.c"
int main() {
struct IntVec v;
v.intVecPush(v,0);
return 0;
}
Every time I run the test file, I get the error:
test.c:7:16: error: variable has incomplete type 'struct IntVec'
struct IntVec v;
^
test.c:7:9: note: forward declaration of 'struct IntVec'
struct IntVec v;
^
1 error generated.
I've tried changing the #include "intVec.c" to "intVec.h" in the test file, however that produces the same error. What would I need to change in order to not get this error?
There is no structure definition struct IntVec.
So the compiler is unable to define the object v
struct IntVec v;
I think you mean
IntVec v;
And this call
v.intVecPush(v,0);
is invalid and does not make sense. I think there should be something like
IntVec v = intMakeEmptyVec();
intVecPush(v,0);
instead of
struct IntVec v;
v.intVecPush(v,0);
Also it is a bad idea to include the whole module in another module. You should place the structure definition in the header and include this header in the compilation unit with main.
That is move these definitions
typedef struct IntVecNode {
int* data;
int sz; // Number of elements that contain data
int capacity; // How much is allocated to the array
} IntVecNode;
typedef struct IntVecNode* IntVec;
in the header.

function pointer not working for int

Im trying to use the power of function pointers, it all went fine until i tried to make the function pointer use a 2nd argument as type int.
The code below generates an error, which is displayed below
In an header file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
Error:
error: expected ‘)’ before ‘int’
void (*move)(Unit, int);
^
void (*move)(Unit); works all fine, which surprises me how adding an argument can cause an error.
I call my struct in a C file, by including header and then doing:
Unit units[UNITCOUNT];
units[0].move(&units[0], 1);
Update:
adding:
typedef struct UnitTag Unit
Causes the error to dissapear, however I can no longer use the function as before.
error: incompatible type for argument 1 of ‘units[i].move’
units[0].move(&units[0], 0);
^
note: expected ‘Unit’ but argument is of type ‘struct UnitTag *’
If I'm getting you, you can simply use struct keyword:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag, int);
} Unit;
void Test (struct UnitTag test1, int test2)
{
printf("Test1.x: %d\n", test1.x);
printf("Test1.y: %d\n", test1.y);
printf("Test2 : %d\n", test2);
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(units[0], 3);
}
Output:
Test1.x: 1
Test1.y: 2
Test2 : 3
If you want to pass struct by referebce, simply:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag*, int);
} Unit;
void Test (struct UnitTag *test1, int test2)
{
test1->x = 4;
test1->y = 5;
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(&units[0], 3);
printf("units[0].x: %d\n", units[0].x);
printf("units[0].y: %d\n", units[0].y);
}
Output is:
units[0].x: 4
units[0].y: 5
You need the prototype for Unit before using it.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
int main(void)
{
return 0;
}
After the clarification what you wanted to do. It probably makes more sense to give a pointer to Unit, so that the move command which returns void can change something about your object.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit *, int);
} Unit;
Unit test;
/* some function that corresponds to the interface */
void myMove(Unit *u, int i)
{
u->x = u->x + i;
}
int main(void)
{
/* initialize test struct */
test.x = 0;
test.y = 0;
test.move = myMove;
test.move(&test, 5);
printf("Values after move are (x, y) = (%i, %i).\n", test.x, test.y);
return 0;
}

How to use in main.c a structure defined in another .c file?

I declared a struct on a header file, let's take this as example:
//file.h
#ifndef FILE_H_INCLUDED
#define FILE_H_INCLUDED
typedef struct {
int x;
int y;
} Point;
#endif // FILE_H_INCLUDED
Then I defined that struct on another file, that contains prototypes of function that I will use on main.c:
//functions.c
#include "file.h"
Point p = {{1},{2}};
Now my question is, how can I use that struct on main.c? Would like to do something like:
//main.c
#include "file.h"
printf("Point x: %d", p.x);
Now, my real struct got 8 fields and it's an array of 40 elements, so it's 40 rows of code, and I would like to not put it in main.c, as I want it as clear as possible. I can't use global vars tho.
Try this:
// file.h
typedef struct {
int x;
int y;
} Point;
void setup_point(Point *);
// functions.c
#include "file.h"
void setup_point(Point * p) {
p->x = 1;
p->y = 2;
}
// main.c
#include "file.h"
int main() {
Point p;
setup_point(&p);
printf("Point x: %d", p.x);
}
This is ideal as the logic for your struct is contained in a separate file and it does not use global variables.
Create a function the returns the address of p.
//file.h
Point *Point_p(void);
//functions.c
#include "file.h"
static Point p = {{1},{2}};
Point *Point_p(void) { return &p; }
//main.c
#include "file.h"
printf("Point x: %d", Point_p()->x);

How can I properly define a structure which is returned by a function?

I am trying to create a function which allocates memory for a structure array defined in "main". The problem seems to be that my function does not recognize the structure. What is wrong with the following code?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n);
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}
... and in another file...
struct complex *myfunction(int n) {
complex *result = (complex *)malloc(n*sizeof(*complex));
if(result==NULL) return(NULL);
else return(result);
}
Building on fvdalcin's answer:
myprog.c:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "mycomplex.h"
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}
mycomplex.h:
#ifndef __MYCOMPLEX_H__
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n);
#define __MYCOMPLEX_H__
#endif
(The #ifdef's are a good idea to keep it from being included more than once.)
mycomplex.c:
#include <stdlib.h>
#include "mycomplex.h"
complex *myfunction(int n) {
complex *result = malloc(n*sizeof(complex));
if(result==NULL) return(NULL);
else return(result);
}
Note subtle but important fixes here--sizeof(complex) instead of sizeof(complex*), declaration of myfunction() doesn't include the keyword "struct", and no cast on malloc()--it doesn't need one and can hide the fact that you may be missing the include file with its prototype (see Do I cast the result of malloc?). myfunction() could actually by simplified down to one line:
return malloc(n*sizeof(complex));
Move this declaration typedef struct _complex { float r; float i; } complex; to the "other" file. This other file has to be your foo.h file, which has an foo.c equivalent which implements the methods declared in the foo.h. Then you can simply add the foo.h to your main.c file and everything will work fine.
Here is a code with corrections that compiles well:
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n) {
complex *result = (complex *)malloc(n*sizeof(complex)); //removed * from sizeof(*complex)
if(result==NULL) return(NULL);
else return(result);
}
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}

Resources