I'm new to C and I had a couple questions about getting struct values into a function and the correct way to declare the function.
in my common.h I've defined
extern struct ddrautocal;
int get_eeprom_vals(uchar); // is this the correct declare the function?
in calibration.c I define my struct and change some set some values (not shown)
#include <common.h>
struct ddrautocal {
u32 wdtr;
u32 clkp;
u32 rdcc;
};
in proc.c
#include <common.h>
int get_eeprom_vals(struct ddrautocal *cal){
// I'd like to access cal.wdtr and cal.clkp
}
I'm a complete derp, I know but I'm trying to get better. I've been trying to get this working all day and would like to know if I am declaring the function correctly in common.h and what is the correct way to access the ddrautocal struct in my get_eeprom_vals function located in proc.c Any help would be greatly appreciated. Thanks!
int get_eeprom_vals(uchar); signature is wrong.. It should be:
int get_eeprom_vals(struct ddrautocal *cal); So the signature of the forward declaration and function definition matches.
To access the members, you need: cal->wdtr, cal->clkp or (*cal).wdtr (*cal).clkp
-> uses the pointer indirection operator.
* is the combination of the indirection operator and the period - the dot - to access the field.
I also think you need #include "common.h" instead of #include <common.h> as common.h isn't a system header.
First thing to know is that we have to make sure that the declaration of a function and its definition match each other. In your case, the definition has the signature:
int get_eeprom_vals(struct ddrautocal *cal)
(A signature of a function includes its name and the argument list).
You need to replace the declaration with:
int get_eeprom_vals(struct ddrautocal *cal);
Also if you want to use period dot to derefer to a structure's members, you can declare your function as follows, and then you can refer to its members as what you showd
int get_eeprom_vals(struct ddrautocal cal);
{
// you can use cal.wdtr etc
}
Related
Consider the following program:
#include <stdio.h>
typedef struct structType {
int someVal;
int otherVal;
// ...more members used for other purposes
} structType;
void myFunc(structType * theStruct, int theVal) {
// Do something
}
int main()
{
structType myStruct;
myStruct.someVal = 5;
myStruct.otherVal = 10;
myFunc(&myStruct, myStruct.someVal);
myFunc(&myStruct, myStruct.otherVal);
return 0;
}
When calling myFunc() I need to pass both a pointer to the struct itself, and one of the values contained withing the struct.
Can I somehow make a macro so that myFunc() could be called something like:
MY_FUNC_MACRO(myStruct, someVal);
MY_FUNC_MACRO(myStruct, otherVal);
So that the struct pointer only needs to be typed once, and then the name of the member variable without passing the struct name once again.
I know about the stringilize macros like # an ##, but afaik that only goes from literal name to string. I need to go the other way, to somehow concatenate multiple strings into one literal name.
You don't need anything fancy
#define MY_FUNC_MACRO(A,B) (myFunc(&(A), (A).B))
works.
It's a little bit fragile though because B could be anything.
If you've got more nested structs and the middle layer is known at compile time, you can do this:
#define MY_FUNC_MACRO(A,B) (myFunc(&(A), (A).memberStruct.B))
I think you can simply use typedef like:
typedef structTypePointer *structType;
and the caller to function turn into:
myFunc(structTypePointer, myStruct.someVal);
or
myFunc(structTypePointer, structTypePointer->someVal);
I'm a bit new to C and I'm having a bit of trouble with a project I'm currently working on. Essentially I have the following files: main.c, alarm.c, alarm.h
I have a struct declaration in alarm.c that looks like:
#define STRLEN 150;
struct alarmparams
{
char time[STRLEN];
char duration[STRLEN];
char snooze[STRLEN];
char port[STRLEN];
};
In main.c I have:
#include <stdio.h>
#include <string.h>
#include "alarm.h"
int main(int argc, char *argv[])
{
struct alarmparams params;
printf("%s, %s\n", params.time, params.duration);
}
And in alarm.h I have:
struct alarmparams;
Right now when I go to compile I get the following error:
error: storage size of ‘params’ isn’t known
I've looked through other posts regarding this error, so I have done a bit of research on this already. I've also tried some of the suggested solutions and it's either I get the exact same error or I got more on top of it. I'm at a lose as to how to fix this.
Is there something I'm missing? Did I declare something incorrectly?
In general should structs be declared in the header file or the c file? Or does it even matter? What's the different between:
struct foo {...};
and
typedef struct foo {...};
struct alarmparams;
is the declaration of an incomplete type. You can create a pointer to an object of this type but you cannot declare an object of this type or take its size until it has been completed. You have to make its complete declaration visible in main.c to declare an object of its type.
If you use the type in both alarm.c and main.c, just declare it in alarm.h and include alarm.h in main.c.
For you second question, the difference between:
struct foo {...};
and
typedef struct foo {...} foo_;
is in the latter case you also declare an alias foo_ for the type name struct foo.
You have to declare the structure in the header file alarm.h.
At the moment, when you include alarm.h, the code in main doesn't see the structure composition, all it sees is struct alarmparams;, so it doesn't know how long it is. How can you allocate space for something that you don't know how much space it takes?
typedef struct foo { ... }; is invalid: typedef expects you to provide an alias for a type. typedef struct foo { ... } foo_t; would be correct.
typedef is a storage class specifier, thus, you can think of it as any other regular declaration. Imagine you want an alias foo for the type bar: just declare a variable of type bar and call it foo. Now, prepend a typedef keyword behind, and you are done. Even complicated typedefs can be easily understood with this simple approach. Since struct foo { ... }; would be an invalid declaration for a variable (no name is provided), so is typedef struct foo { ... };.
In general, declare structures in the header file when you will reuse them in other source files. If you don't plan on doing so, declaring them on the .c file should be fine.
In addition to the other answers, the value of STRLEN must be known at compile time (it most likely is in this case, but just in case).
I have learned a decent amount of java and now I want to learn C, I've learned a little about structs and typedefs but I have errors when I place the typedef after the main() function and it is used from within the main() function.
Is there a way to declare types but not define them in C so I can keep my code after the main() function similar to functions? (I'm not sure if this is good practice but I like organizing my code this way)
Don't do that. C code is intended to be read by the compiler and it will learn about new definitions as it keeps reading the file. Moving things below main() serves no purpose. It will also confuse other humans.
As for the question itself: in some cases, yes, you can. If everything you need is a forward declaration, you can do so. But in most cases you will want the definition, so it won't help you.
For example, this will compile:
struct T;
int main(void)
{
struct T * p = 0;
return !!p;
}
// Later on you may define `struct T`
C requires a type to be declared before it's used. If the code is just using a pointer to the type then the code doesn't not need to declare the members, this is a forward declaration. Other usage, such as passing the type by value or using it as a local variable requires a full definition.
C projects generally use headers which will provide the definition of types. These are included into the C modules.
// header.h
#ifndef _header_h_
#define _header_h_
struct DescribedType {
int member;
char* variables;
};
#endif
// module.c
#include "header.h"
struct ForwardDeclaration;
ForwardDeclaration* allocForward();
int main(){
DescribedType someType;
ForwardDeclaration* someValue = allocForward();
return 0;
}
struct ForwardDeclaration {
int declaredLater;
};
I'm stuck with this error:
cities.c: In function ‘main’:
cities.c:7:48: error: dereferencing pointer to incomplete type ‘struct Graph’
printf("well, it got here. nodeCount: %d\n", x->nodeCount);
All other solutions point out that names are misspelled and thus undefined, however, if I move the struct Graph definition to the header, it works just fine.
I had previously used this mechanic in my other library and it still compiles just fine, I've spent hours trying to move things around to no avail.
graph.h:
#ifndef GRAPH_H
#define GRAPH_H
typedef struct Graph * Graph;
int graphCreate(Graph*, int);
int graphAddPath(Graph, int, int, unsigned int);
int graphRemovePath(Graph, int, int);
int graphDestroy(Graph*);
#endif /* GRAPH_H */
graph.c: https://pastebin.com/FzkaJJwP
cities.c:
#include "graph.h"
#include <stdio.h>
int main() {
Graph x;
graphCreate(&x, 5);
printf("well, it got here. nodeCount: %d\n", x->nodeCount);
}
Output is as expected in my library at https://git.mif.vu.lt/emiliskiskis/c_deck.
Thank you for you help.
The definition of the struct Graph is in the graph.c file. When you compile the cities.c file this definition is not visible. You need to move the definition to graph.h
struct Graph {
unsigned int **matrix;
int nodeCount;
};
As suggested by Blaze, the below definition is confusing. typedef struct Graph * Graph. A better solution would be to
typedef struct Graph Graph;
and then in the code you can use
int graphCreate(Graph **, int);
int graphAddPath(Graph *, int, int, unsigned int);
int graphRemovePath(Graph *, int, int);
int graphDestroy(Graph **);
The compiler message is pretty clear. The type is incomplete, which basically means that the compiler only knows that it exists a struct named Graph, but it does not know what it looks like. The consequence of this is that you cannot access the fields.
So, first you have to answer this question. Do you want the programmer that is using the library to be able to access the fields of Graph? If no, put the definition in the .c file. If yes, put the definition in the .h file.
One more thing to consider is typedef struct Graph * Graph. You're hiding an awful lot of information when typedefing a struct, and the same goes for when you are typedefing a pointer. Now you're doing both. My personal opinion is that you really should avoid doing this, unless the answer to the above question is "no".
My suggestion is, if you want the user of the library to be able to access the fields of struct Graph, remove the typedef completely. If you want to hide it from the user, code access functions, like this:
// cities.h
int getNodeCount(Graph g);
// cities.c
int getNodeCount(struct Graph * g) {
return g->nodeCount;
}
And use it like this:
Graph g;
int nodeCount = getNodeCount(g);
Do note that i did NOT use the typedef in the function definition. Only in it's prototype.
I'm a bit new to C and I'm having a bit of trouble with a project I'm currently working on. Essentially I have the following files: main.c, alarm.c, alarm.h
I have a struct declaration in alarm.c that looks like:
#define STRLEN 150;
struct alarmparams
{
char time[STRLEN];
char duration[STRLEN];
char snooze[STRLEN];
char port[STRLEN];
};
In main.c I have:
#include <stdio.h>
#include <string.h>
#include "alarm.h"
int main(int argc, char *argv[])
{
struct alarmparams params;
printf("%s, %s\n", params.time, params.duration);
}
And in alarm.h I have:
struct alarmparams;
Right now when I go to compile I get the following error:
error: storage size of ‘params’ isn’t known
I've looked through other posts regarding this error, so I have done a bit of research on this already. I've also tried some of the suggested solutions and it's either I get the exact same error or I got more on top of it. I'm at a lose as to how to fix this.
Is there something I'm missing? Did I declare something incorrectly?
In general should structs be declared in the header file or the c file? Or does it even matter? What's the different between:
struct foo {...};
and
typedef struct foo {...};
struct alarmparams;
is the declaration of an incomplete type. You can create a pointer to an object of this type but you cannot declare an object of this type or take its size until it has been completed. You have to make its complete declaration visible in main.c to declare an object of its type.
If you use the type in both alarm.c and main.c, just declare it in alarm.h and include alarm.h in main.c.
For you second question, the difference between:
struct foo {...};
and
typedef struct foo {...} foo_;
is in the latter case you also declare an alias foo_ for the type name struct foo.
You have to declare the structure in the header file alarm.h.
At the moment, when you include alarm.h, the code in main doesn't see the structure composition, all it sees is struct alarmparams;, so it doesn't know how long it is. How can you allocate space for something that you don't know how much space it takes?
typedef struct foo { ... }; is invalid: typedef expects you to provide an alias for a type. typedef struct foo { ... } foo_t; would be correct.
typedef is a storage class specifier, thus, you can think of it as any other regular declaration. Imagine you want an alias foo for the type bar: just declare a variable of type bar and call it foo. Now, prepend a typedef keyword behind, and you are done. Even complicated typedefs can be easily understood with this simple approach. Since struct foo { ... }; would be an invalid declaration for a variable (no name is provided), so is typedef struct foo { ... };.
In general, declare structures in the header file when you will reuse them in other source files. If you don't plan on doing so, declaring them on the .c file should be fine.
In addition to the other answers, the value of STRLEN must be known at compile time (it most likely is in this case, but just in case).