Consider this piece of code
int main(void)
{
typedef struct {
int i;
} s;
struct {
s s;
} t;
return 0;
}
It compiles fine. Now take a look at this one
int main(void)
{
typedef struct {
int i;
} s;
s s;
return 0;
}
This code will not compile -
‘s’ redeclared as different kind of symbol.
Question: Why is it correct to have "s s;" as a declaration inside a structure, but not correct to have this definition inside a function?
In upper example member s is a local to struct. You cannot use it without using t.s syntax, so there is no conflict with structure type s.
In lower example structure type s, and variable s are in the same scope, so it is unclear which you are referring to.
As a struct member, the identifier s is unambiguous, because you'll always address it as somestruct.s or someptr->s.
Related
I've tried a lot of simple examples of this and haven't gotten any to work.
My goal is to have a function which declares a struct internally, sets the values of the struct, and then returns the struct.
struct getData(void){
typedef struct{
int count1;
int count2;
} MyStruct;
MyStruct myData;
myData.count1 = 5;
myData.count2 = 6;
return myData;
};
int main(void) {
struct myData = getData()
printf("count1: %i", myData.count1);
printf("count2: %i", myData.count2);
}
Every example I've found does something similar to this, but for some reason it's not finding my struct called MyStruct. Exact error is:
error: expected identifier or ‘(’ before ‘void’
struct getData(void){
^~~~
The error I keep getting makes me think it doesn't like the struct inside the function.
Your problem seems to be a confusion regarding the usage of the struct keyword. You don't do struct myData to declare a variable named myData that is of struct type, because there isn't really a struct type. What you do is struct myData <SOMETHING> to define <SOMETHING> as being a new data type named struct myData. You can then say struct myData dat;, thereby declaring that dat is a variable of type struct myData.
You're also demonstrating the same confusion at the top, where you have struct getData(void)... you're attempting to declare getData as a function returning a struct, but you'd really have to do something like struct myData getData(void) to declare a function returning type struct myData.
I think the more standard way to write what you're after is this, using an independent definition of the struct, and then using a pointer for the function call. As written your code seems to have some scope issues (declaring a struct typedef inside a function, hmmm...) [Incorrect->] plus I don't believe structs can be passed around that way in C, I'm pretty sure you have to use pointers. [Edit oops this is incorrect! See comments]
#include<stdio.h>
typedef struct {
int count1;
int count2;
} MyStruct;
void getData (MyStruct* myDataPtr) {
myDataPtr->count1 = 5; //note pointer access notation ->
myDataPtr->count2 = 6;
};
int main(void) {
MyStruct myData;
MyStruct* sPtr = &myData; //create pointer to struct, assign to myDaya
getData(sPtr); //pass pointer to function
printf("count1: %i \n", myData.count1);
printf("count2: %i \n", myData.count2);
}
Outputs:
count1: 5
count2: 6
The following link says that structs defined in main don't have the scope to be called by functions because they are local so you should define your structs globally. However with variables, it's preferred to declare variables locally and pass to functions with pointers instead of declaring global variables.
Is there a way in pure C using pointers etc to pass a struct defined in main to a function? If you don't mind, please use the example program to demonstrate the method. Thanks.
where to declare structures, inside main() or outside main()?
This code works but is not what I want. I want to define the structure within main. Is this possible?
#include <stdio.h>
#include <SDL2/SDL.h>
void function();
struct hexColour
{
Uint32 red;
}hc;
int main(void)
{
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
void function(struct hexColour hc)
{
printf("red is %x\n", hc.red);
}
What I want is:
int main(void)
{
struct hexColour
{
Uint32 red;
}hc;
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
First of all you should really use proper prototypes that matched the function definitions.
Secondly, your example do pass a structure into the local variable hc in the function.
When function is running there are two distinct and separate structures in memory: The one in the main function, and the local in the function function.
To cover my bases, here are two answers for two other question that maybe is asked:
You want to define the structure itself inside the main function, and then be able to use it in other functions.
Something like
int main(void)
{
struct hexColor
{
uint32_t white;
// Other members omitted
};
struct hexColour hc;
hc.white = 0xff;
func(hc); // Assume declaration exist
}
void func(struct hexColour my_colour)
{
printf("White is %u\n", my_colour.white);
}
This is not possible. The structure hexColour is defined inside the main function only. No other function can use that structure. It doesn't matter if you pass a pointer or not, the structure hexColour still will only exist inside the main function only.
Emulate pass-by-reference by passing a pointer to a structure object. Like
struct hexColor
{
uint32_t white;
// Other members omitted
};
int main(void)
{
struct hexColour hc;
hc.white = 0xff;
// Assume declaration of function exists
func(&hc); // Emulate pass-by-reference by passing a pointer to a variable
}
void func(struct hexColour *colourPointer)
{
colourPointer->white = 0x00;
}
This is possible, because then the structure hexColour exists outside the main function, in the global scope. All functions declared and defined after the structure definition may use the structure and its members.
If you pass by value a copy is made (expensive, modifications are not reflected outside). If you want to pass a pointer to a struct just go with, but this doesn't mean you are passing a struct by reference (C doesn't have references), you are passing a pointer to a struct by value instead.
void function(struct hexColour* hc) {
printf("red is %x", hc->red);
}
int main() {
...
functon(&hc);
...
}
See:
Signature of the function changes from struct hexColor to struct hexColor* so that you are passing a pointer (by value)
To access field of the struct when dealing with pointers you use -> instead that .
You need to take the address to the struct when invoking the function, function(hc) becomes function(&hc)
Now since you are passing the address the the struct any modification is done to the real value.
You seem to have understood your linked question and its answers incompletely. You write,
The following link says that structs defined in main don't have the
scope to be called by functions because they are local so you should
define your structs globally.
The ambiguity here is between struct types, such as your struct hexColour, and objects having those types, such as your hc. Both struct types and struct objects should be declared so that they are in scope at all the places where they are needed, but that plays out differently for these two different kinds of entities and in various different situations.
However with variables, it's preferred to declare variables locally
and pass by reference instead of declaring global variables.
It is usually best to use block-scope variables instead of file-scope variables, yes, but C has only pass by value, not pass by reference. There are plenty of circumstances where it is advantageous to pass pointers (by value) instead of the objects to which they point, and this is close to pass by reference, but there is certainly no rule or general practice that passing pointers is universally better than passing the objects to which they point.
Is there
a way in pure C using pointers etc to pass a local struct to a
function?
Both the caller and the callee have to agree about the type of each argument, and there are many ways to achieve this. But there are some conventions that have grown up along with C for how to approach problems such as these in an effective way. Large among them is this:
Any function and any non-builtin type that is to be used in multiple translation units should be declared in a header file, and that header included in every translation unit that needs it.
That's a generalization of the rule you couched in terms of "global" definitions. Example:
colour.h
#ifndef COLOUR_H
#define COLOUR_H
struct hexColour {
Uint32 white;
Uint32 black;
Uint32 red;
Uint32 pink;
Uint32 grey;
}; // Note that only the type is declared here, not any objects
void function(struct hexColour hc);
#endif
Note that the declaration of type struct hexColour appears before the declaration of function function that has a parameter of that type.
You can then use those types and functions with appropriate locality, for example:
main.c:
#include "colour.h"
int main(void) {
struct hexColour hc = {
.white = 0xFFFFFFFF, .black = 0xFF000000, .red = 0xFFFF0000,
.pink = 0xFFFF9999, .grey = 0xFFA0A0A0 };
function(hc);
return 0;
}
void function(struct hexColour hc) {
printf("red is %x\n", hc.red);
}
Note that the declaration of function that forms part of its definition here matches the declaration in the header. That definition function() could as easily be defined in a different source file, instead, as long as the caller has the header file to tell it how that function is declared. You can #include coulour.h into as many different source files as needed.
Do note, however, that in this case, the struct is passed by value. That's well-defined and perfectly acceptable, but inasmuch as the function receives only a copy, it cannot effect changes to the caller's original copy. If you wanted the function to be able to do that, then you would need to pass a pointer to the struct (by value) instead of the struct itself:
void function(struct hexColour *hc) {
// ...
}
int main(void) {
// ...
function(&hc);
// ...
}
You can take a locally-defined struct and pass it to another function:
void f1(struct s);
int main()
{
struct s s1;
f1(s1);
}
You can take a locally-defined struct and pass a pointer to it to another function:
void f2(struct s *);
int main()
{
struct s s2;
f2(&s2);
}
You can return a locally-defined struct:
struct s f3()
{
struct s ret;
/* ... */
return ret;
}
You can not return a pointer to a locally-defined struct:
struct s *f4()
{
struct s ret;
/* ... */
return &ret; /* WRONG */
}
If you declare a struct within a function, it is not a global variable, so you can not refer to it in another function to which you did not pass the structure or a pointer:
void f5();
int main()
{
struct s s1;
f5();
}
void f5()
{
int x = s1.field; /* WRONG */
}
Finally, if you declare the struct type itself inside a function, you end up with a struct which you can't properly refer to elsewhere:
void f1(struct s);
int main()
{
struct s { int a, b; } s1;
f1(s1);
}
void f1(struct s arg) /* error: this struct s might not be the same as the previous one */
{
int x = arg.b; /* error: compiler might not know that struct s contains a and b */
}
Looked at the previous answers. Suggest you wrap your mind around the 'C' difference between a declaration and a definition. Note that earlier versions of 'C' would NOT allow passing a copy of a structure on the stack, only a pointer to a struct..
#include <stdio.h>
struct virus
{
char signature[25];
int size;
}v[2];
int main(void) {
static v[0] = {"Yankee",1813};
static v[1] = {"Doodle",2813};
int i;
for(i=0;i<=1;i++)
{
printf("%s %d\n",v[i].signature,v[i].size);
}
return 0;
}
I am getting the compiler error in this C code.
Error: Declaration syntax in function main()
I am guessing that there is some error in v[2], as it is associated with extern class whereas, v[0] and v[1] are associated with static class.
But, I am not sure that is this the only reason or some other ?
Edit : I have edited the code by removing the wrong syntax.
There is no error in declaration of v[2], the problem is later.
You've written
static struct v[0] = {"Yankee",1813};
which attempts to define a 0-sized array, which is not allowed by default C standard.
That said, the syntax is also horribly wrong. You don't have a proper type there, remember, struct itself is not a type, it's a keyword. struct <something> is actually a type.
Then, from the logical point of view, you probably don't want a new variable altogether. In case you want to use the array elements from the v, just use the variable name, that's all. Something like
#include <stdio.h>
struct virus
{
char signature[25];
int size;
}v[2] = { {"Yankee",1813}, {"Doodle",2813}}; //get it initialized, job done
int main(void) {
int i;
for(i=0;i<=1;i++)
{
printf("%s %d\n",v[i].signature,v[i].size);
}
return 0;
}
will do the job in much better way, IMHO.
EDIT:
In case, you're interested in assigning individual elements (not initialization), well, you cannot use a brace-enclosed initializer for that purpose, it's not meant to be RHS operand for an assignment. You need to use a compound literal for that purpose, something like
v[0] = (struct virus){"Yankee",1813};
v[1] = (struct virus){"Doodle",2813};
will also do the job.
Don't mix up struct definitions with variable declarations, that's sloppy practice.
Instead, use a typedef:
typedef struct
{
char signature[25];
int size;
} virus_t;
Then you can declare variables of this type as you please:
static virus_t v[2] =
{
{"Yankee",1813},
{"Doodle",2813}
};
Or with designated initializers:
static virus_t v[2] =
{
[0] = {"Yankee",1813},
[1] = {"Doodle",2813}
};
In one of my applications written in C I have a struct declared as a member of another struct:
struct _test
{
int varA;
//...
struct _small
{
int varB;
//...
} small;
} test;
Now I want to create a function that access varB above, but I don't want it to access the entire structure test, that is, I don't want to do:
#include <relevant_header>
void myFunction()
{
test.small.varB = 0;
}
instead, I want to pass only the small structure as a parameter to that function; something like this:
#include <relevant_header>
void myFunction(struct _test::_small* poSmall)
{
poSmall->varB = 0;
}
The problem is I don't know how to do this, that is, the above code doesn't compile right (I suppose it's C++ syntax only). So how may I do this in a C code - pass a pointer to a struct that was declared inside another struct? I wasn't able to find anything about this both in SO as well as in Google in general.
Just do:
void myFunction(struct _small *poSmall)
{
poSmall->varB = 0;
}
The scope of struct _small is not limited to its outer structure.
Can we have functions in structures in C language?
Could someone please give an example of how to implement it and explain?
No, structures contain data only. However, you can define a pointer to a function inside of a struct as below:
struct myStruct {
int x;
void (*anotherFunction)(struct foo *);
}
The answer is no, but there is away to get the same effect.
Functions can only be found at the outermost level of a C program. This improves run-time speed by reducing the housekeeping associated with function calls.
As such, you cannot have a function inside of a struct (or inside of another function) but it is very common to have function pointers inside structures. For example:
#include <stdio.h>
int get_int_global (void)
{
return 10;
}
double get_double_global (void)
{
return 3.14;
}
struct test {
int a;
double b;
};
struct test_func {
int (*get_int) (void);
double (*get_double)(void);
};
int main (void)
{
struct test_func t1 = {get_int_global, get_double_global};
struct test t2 = {10, 3.14};
printf("Using function pointers: %d, %f\n", t1.get_int(), t1.get_double());
printf("Using built-in types: %d, %f\n", t2.a, t2.b);
return 0;
}
A lot of people will also use a naming convention for function pointers inside structures and will typedef their function pointers. For example you could declare the structure containing pointers like this:
typedef int (*get_int_fptr) (void);
typedef double (*get_double_fptr)(void);
struct test_func {
get_int_fptr get_int;
get_double_fptr get_double;
};
Everything else in the code above will work as it is. Now, get_int_fptr is a special type for a function returning int and if you assume that *_fptr are all function pointers then you can find what the function signature is by simply looking at the typedef.
No, it has to be implemented like this :
typedef struct S_House {
char* name;
int opened;
} House;
void openHouse(House* theHouse);
void openHouse(House* theHouse) {
theHouse->opened = 1;
}
int main() {
House myHouse;
openHouse(&myHouse);
return 0;
}