I am trying to pass a structure by reference in C so that I can modify the values from within the function. This is the code I have so far, but it produces some warnings and one error.
main.c
#include <stdio.h>
#include "myfunctions.h"
#include "structures.h"
int main(int argc, char const *argv[] {
struct MyStruct data;
data.value = 6;
printf("Before change: %d\n", data.value);
changeData(data);
printf("After change: %d\n", data.value);
}
myfunctions.c
#include "structures.h"
void changeData(MyStruct data) {
data.value = 7;
}
myfunctions.h
#ifndef MyStruct
#define MyStruct
void changeData(MyStruct data);
#endif
structures.h
typedef struct {
int value;
} MyStruct;
Errors Produced
In file included from main.c:2:0:
myfunctions.h:4:1: warning: parameter names (without types) in function declaration
void changeData(MyStruct data);
^
In file included from main.c:3:0:
structures.h:5:1: warning: unnamed struct/union that defines no instances
} MyStruct;
^
main.c: In function ‘main’:
main.c:9:5: error: ‘data’ undeclared (first use in this function)
data.value = 6;
^
main.c:9:5: note: each undeclared identifier is reported only once for each function it appears in
That's all caused by
#define MyStruct
With this line, you've defined MyStruct as a macro that expands to nothing. I.e. you've effectively removed all occurrences of MyStruct in the following code, which is why the compiler is so confused about seeing things like
typedef struct {
int value;
} ;
or
void changeData( data);
To fix this, use
#ifndef MYFUNCTIONS_H_
#define MYFUNCTIONS_H_
instead. (This is the reason why we use ALL_UPPERCASE names for macros: To avoid accidental name clashes with normal identifiers.)
applying all my comments and elimination of the unnecessary 'typedef', and placing it all in one file ( Note: there is no problem with extracting the various files), results in the following code:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct MyStruct
{
int value;
};
#endif // STRUCTURES_H
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H
void changeData( struct MyStruct *data);
#endif // MYFUNCTIONS_H
#include <stdio.h>
//#include "myfunctions.h"
//#include "structures.h"
int main( void )
{
struct MyStruct data;
data.value = 6;
printf("Before change: %d\n", data.value);
changeData(&data);
printf("After change: %d\n", data.value);
} // end function: main
//#include "structures.h"
void changeData( struct MyStruct *data)
{
data->value = 7;
} // end function: changeData
which cleanly compiles and does do the desired operation
Related
I'm constructing an u-boot bootloader for my embedded system (cyclone V) using Buildroot and I get the following error :
error: 'dm_mmc_ops' undeclared (first use in this function)
After several unsuccessful attempts to understand/solve the error, I've manage to isolate the problem which looks like the simple code hereafter and generates the same error :
File1.h
#ifndef FILE1
#define FILE1
struct dm_mmc_ops {
int (*send_cmd)(int data);
int (*set_ios)(char* dev);
};
struct dev {
struct dm_mmc_ops* ops;
} *dev;
#define mmc_get_ops(dev) ((dm_mmc_ops *)(dev)->ops)
#endif
File2.h
#ifndef FILE2
#define FILE2
#include "file1.h"
extern const struct dm_mmc_ops dm_dwmci_ops;
#endif
File2.c
#include <stdio.h>
#include "file1.h"
#include "file2.h"
int return_int (int data)
{
return data;
}
int return_ptr (char* data)
{
return (int) data;
}
const struct dm_mmc_ops dm_dwmci_ops = {
.send_cmd = return_int,
.set_ios = return_ptr
};
void main (void)
{
struct dev my_dev = {.ops = &dm_dwmci_ops};
dev = &my_dev;
char text[] = "abcd";
struct dm_mmc_ops *test_mmc = mmc_get_ops(dev); // Error is here !!!
printf("%d\n",test_mmc->send_cmd(50));
printf("%d\n",text);
printf("%d\n",test_mmc->set_ios(text));
return;
}
Then the error generated is :
error: 'dm_mmc_ops' undeclared (first use in this function)
What is wrong in my code and what should I do to get rid of this error ?
Your problem is here
#define mmc_get_ops(dev) ((dm_mmc_ops *)(dev)->ops)
^^^^^^^^^^
You probably want
#define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->ops)
Besides that you have a number of other problems. Set you compiler to a high warning level (e.g. gcc -Wall ...) and then fix all warnings.
I'm trying to define a struct in a header file with function prototypes that take pointer to that struct as a parameter.
#ifndef _GETDATA
#define _GETDATA
struct PERSONDATA{
char name[20];
double age,mass;
};
typedef struct PERSONDATA person;
extern void getData(person *);
extern void getName(char *,int);
#endif
The getData.c file is defined as such;
#include <stdio.h>
void getData(person *ptr)
{
printf("Enter name: ");
getName(ptr->name,sizeof(ptr->name));
}
and the getName.c file is defined as:
#include <stdio.h>
void getName(char *ptrName, int varSize)
{
int i=0;
do
{
*(ptrName++) = getchar();
++i;
if(i==varSize) printf("array full, EXITING!\n");
}while(*(ptrName-1)!='\n' && i<varSize);
}
Lastly, the main function was:
#include <stdio.h>
#include "GETDATA.h"
int main(int argc, char **argv)
{
person human1;
printf("hello, world!\n\n");
getData(&human1);
return 0;
}
On compiling the program, I get the following error:
***C:/Users/Shoaib.Shoaib-PC/Google Drive/C workspace/C workspace codelite/StructPointerExample/getData.c:2:14: error: unknown type name 'person',
void getData(person *ptr)***
Could some one please help me out here, any help is greatly appreciated!
You should include the header file in ALL files using the declared types, not just in the main file.
I am trying to declare a struct and use it in multiple files and I am getting an error that I cannot figure out. Sample code is posted below.
in test.h
#ifndef TEST_H
#define TEST_H
struct mystruct;
struct mystruct *new_mystruct();
void myprint(struct mystruct*,int);
#endif
int test.c
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
struct mystruct {
int *myarray;
};
struct mystruct *new_mystruct(int length)
{
int i;
struct mystruct *s;
s = malloc(sizeof(struct mystruct));
s->myarray = malloc(length*sizeof(int));
for(i = 0; i < length; ++i)
s->myarray = 2*i;
return s;
}
in main.c
#include "test.h"
#include <stdio.h>
int main()
{
int len = 10;
struct mystruct *c = new_mystruct(len);
myprint(c, len);
printf("%f", c->myarray[3]); // error: dereferencing pointer to incomplete type
return 0;
myprint() prints out 0 2 4 6 8 10 12 14 16 18. why doesn't the myprint(function work but the printf statement doesn't? why is it ok to pass it into a function but not use it in main? Thanks.
Currently main() only knows that struct mystruct is a type, but it doesn't know anything about its internal structure, because you've hidden it in test.c.
So you need to move this definition:
struct mystruct {
int *myarray;
};
from test.c to test.h, so that it's visible to main().
Note: what you're doing here is a classic example of an opaque type. This can be a very useful technique when you want to hide implementation details from code that is going to be calling your API.
Main.c doesn't know the contents of the mystruct structure. Try moving these lines:
struct mystruct {
int *myarray;
};
from test.c to test.h.
While you're at it, I think you mean "int myarray" not "int *myarray".
I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Other way I thought as,
struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);
But still I'm getting seg-fault error.
ok here is the problem with void*....
e.g.
in core.c
void init_my_type(hidden_my_type a)
{
my_type *the_a = malloc(...);
a = the_a // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
pthread_cond_init(&the_a->...);
.. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
my_type *the_x = x;
pthread_detroy(&the_x-> ...);
}
in main.c
test()
{
my_hidden_type x;
init_my_type(x);
....
my_type_detroy(x);
}
this it self should fail. as in main.c test function, x is void* ... init will allocate but in destroy I'm again passing void* .. which can be anything!
EDIT (Solved for me)
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void init_hidden_type(hidden_my_type void_p_my_type)
{
struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
//--- Do init for your type ---
void_p_my_type = real_my_type;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
Version 0 — Critique of Question's Code
The posted code does not compile.
api.h
typedef void* hidden_my_type;
void do_something(my_type x);
This defines hidden_my_type but not the my_type that is passed to do_something(). Presumably, you intended:
typedef void *my_type;
void do_something(my_type x);
core.c
struct _my_type
{
int a;
}
As noted below too, there is a semi-colon missing after the structure definition.
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
You have the hidden_my_type vs my_type problem again. You have the * of the pointer where it cannot go; it must go after the struct _my_type. You probably intended something like:
void do_something(my_type void_x)
{
struct _my_type *x = void_x;
printf("Value: %d\n", x->a);
}
This is now syntactically correct (I think; I haven't actually run it past a compiler). You have not shown how it is used; indeed, since the user code has no way to generate a pointer to a valid structure, there is no way for this code to be used safely.
Your test code (unshown — why don't you show your test code) might look something like this:
#include "api.h"
int main(void)
{
my_type x = 0;
do_something(x);
return 0;
}
Alternatively, it might not have the = 0 initializer in place. Either way, your code is unable to function sanely, and a core dump is almost inevitable. When you hide the structure from the user, you have to provide them with a mechanism to get hold of a valid (pointer to) the structure, and you've not done that.
Version 1
This is a better way to do it, because it is more nearly type-safe:
api.h version 1
typedef struct _my_type *my_type;
void do_something(my_type x);
core.c version 1
#include "api.h"
struct _my_type
{
int a;
};
Note the added semi-colon, and the include of the api.h file.
void do_something(my_type x)
{
// Now you don't have to do casting here!
//struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Version 2
Actually, we can debate the wisdom of hiding the pointer; I would prefer not to do so:
api.h version 2
#ifndef API_H_INCLUDED
#define API_H_INCLUDED
typedef struct my_type my_type;
extern void do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void my_type_release(my_type *x);
#endif /* API_H_INCLUDED */
core.c version 2
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
struct my_type
{
int a;
};
void do_something(my_type *x)
{
printf("Value: %d\n", x->a);
}
my_type *my_type_initializer(void)
{
my_type *x = malloc(sizeof(*x));
x->a = 57; // More plausibly, this would be 0
return x;
}
void my_type_release(my_type *x)
{
free(x);
}
main.c
#include "api.h"
int main(void)
{
my_type *x = my_type_initializer();
do_something(x);
my_type_release(x);
return 0;
}
That's nice and clean. Of course, the user cannot allocate a struct my_type (only a pointer to it), so you need a function to allocate the structure for them. Think of the Standard C Library, and the FILE type, and fopen() to allocate and fclose() to release and fprintf() etc to manipulate the type. The my_type_initializer() is functioning as an analogue to fopen(), my_type_release() as an analogue to fclose(), and do_something() as an analogue to fprintf().
Jonathan, you beat me to an answer, but this may be helpful as well. Here, api.c contains the (private) implementation, and api.h provides the interface to be consumed by other code such as main.c.
// main.c: uses only the public interface to the private code
#include "api.h"
int main(int argc, char *argv[]) {
void *foo;
foo = create_foo("five", 5);
print_foo(foo);
delete_foo(foo);
}
// EOF main.c
// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_
// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The real structure is private to the implementation.
typedef struct {
char name[20];
int number;
} real_struct;
// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
real_struct *s = malloc(sizeof(real_struct));
strcpy(s->name, name);
s->number = number;
return (void *) s;
}
// Print the data.
void print_foo(void *foo) {
real_struct *s = (real_struct *) foo;
printf("name: %s, number: %d\n", s->name, s->number);
}
// Release the memory.
void delete_foo(void *foo) {
free(foo);
}
// EOF api.c
This code should compile and run:
$ gcc -o foo main.c api.c
$ ./foo
name: five, number: 5