Hey I'm new to programming (learning through cs50x in C) and when they mentioned structures I decided to try to fool around and just write a quick program that would swap some values in a structure using a function. I'm running until several error messages, the first of which is "incompatible pointer types passing 'struct numbers*' to parameter of type 'struct numbers*'. Another issue seems to come up in the function definition where the compiler says "incomplete definition of type 'struct number'" I was just hoping for some help cause I'm stumped.
Heres the code (I know its rough but I'm learning lol)
#include <stdio.h>
struct numbers;
void swap(struct numbers* s);
int main(void)
{
struct numbers
{
int a;
int b;
int c;
};
struct numbers x = {1, 5 , 9};
swap(&x);
printf("%i, %i, %i\n", x.a, x.b, x.c);
return 0;
}
void swap(struct numbers* s)
{
int temp = s -> a;
int temp2 = s -> b;
s -> a = s -> c;
s -> b = temp;
s -> c = temp2;
}
You're expecting the code in swap() to be able to access the fields of struct numbers, but the full declaration of that type is inside main(), so it's not visible.
Break out the declaration, it must be visible to all who need it. Putting it first will also remove the need to pre-declare the structure.
The same with swap() itself, putting it before main() will remove the need to have a prototype for it in the same file.
It should be:
struct numbers
{
.
.
.
}
static void swap(struct numbers *s)
{
.
.
.
}
int main(void)
{
.
.
.
}
The problem is that the struct numbers declaration is global, but the definition is local in main, To use the members of a structure, the swap function must know what members the structure have, and as it can't see the definition it doesn't know that. Remove the declaration and put the definition in the global scope.
Function swap can't see the definition of struct numbers. Put it globally outside main.
Extra Tip - Use typedef with structs, it gives you flexibility in declaration:
typedef struct typeNumbers
{
int a;
int b;
int c;
} numbers;
Note that typeNumbers is optional. Declare it like:
numbers x = {1, 2, 3};
The problem was that the structure was in main, I did some fixes also to the code and comment them.
#include <stdio.h>
//By defining the struct at the beginning you can avoid the forward declaration
//and it make more sense to know what "numbers" is before continuing reading the code.
struct numbers {
int a;
int b;
int c;
};
void swap(struct numbers* s)
{
//Small change to use only one temp variable...
int temp2 = s -> b;
s -> b = s -> a;
s -> a = s -> c;
s -> c = temp2;
}
int main(void)
{
struct numbers x = {1, 5 , 9};
swap(&x);
printf("%i, %i, %i\n", x.a, x.b, x.c);
return 0;
}
Related
Code 1
#include <stdio.h>
int T;
int main()
{
struct T{ double x;};
printf("%d", sizeof(T));
return 0;
}
Output: 4
Code 2
#include <stdio.h>
struct T{ double x;};
int main()
{
int T;
printf("%d", sizeof(T));
return 0;
}
Output: 4
For the code 1, I think that the output is the size of the global variable(int T) that's why it gives 4.
But for the code 2, it gives output 4, according to the global variable logic, it should be output 8 for struct T{ double x;};.
Here, the global variable concept is not correct - I think.
Can anyone please explain this why the output looks like?
The problem here isn't the scope but how structures tags live in a different namespace than other symbols.
Because of this when you do sizeof(T) you always get the variable T.
To get a structure tag in C you need the struct keyword. As in sizeof(struct T).
Things would be different if you used typedef:
struct T
{
double x;
} T;
Then you would have a type named T in the "normal" namespace. On the other hand that type would conflict with the variable with the same name so you would get a compiler error instead.
I have a complex structure which looks like this.
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
I use a function, that takes address of "struct c" as an argument. Now I want this function to copy the values of "struct c" to "struct b". The function call that I make in the main function may look like this.
copy_val(&z.y);
Now, how do I define copy_val? Any suggestions?
If i define a pointer of type struct c, like below it isn't working.
void copy_val(struct c *addr)
{
struct c *tmp=addr;
int tmp_int=tmp->c_inner_int;
int tmp_char=tmp->c_inner_char;
tmp=tmp-1; /** assuming that b and c are of same type and decrementing pointer by 1 takes to beginning of b **/
tmp->b_inner_int=tmp_int;
tmp->b_inner_char=tmp_char;
}
#include <stdio.h>
#include <stddef.h>
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
void copy_val(struct c *addr){
size_t offset_c = offsetof(struct a, y);
size_t offset_b = offsetof(struct a, x);
struct b *bp = (struct b*)((char*)addr - offset_c + offset_b);
bp->b_inner_int = addr->c_inner_int;
bp->b_inner_char = addr->c_inner_char;
}
int main(void){
z.y.c_inner_int = 1;
z.y.c_inner_char = '1';
copy_val(&z.y);
printf("%d, %c\n", z.x.b_inner_int, z.x.b_inner_char);
return 0;
}
You say that you want to take the address of a structure member, and reference other members based on that.
That's a bit iffy; the natural thing to do would be to take the address of the top-level structure whose members you want to work with, i.e. a struct a.
Also, it can be simplified:
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
} x, y;
} z;
With that done, you can do just:
z.x = z.y;
to copy the entire value of type struct b.
If you pass like this copy_val(&z.y); you can't catch it in proper way because you have structure inside structure. so try to pass whole structure and copy it-
copy_val(&z);
Try the following code-
void copy_val(struct z *addr)
{
addr->x.b_inner_int= addr->y.c_inner_int;
addr->x.b_inner_char= addr->y.c_inner_char;
}
Your assumption that b and c are the same type is invalid, according to the C standard section 6.2.7 p.1 (emphasis mine):
...if one member of the pair is declared with a name, the other is declared
with the same name.
Because the structs use different member names, they are not considered compatible, thus your assumption is invalid.
Further, even if they are the exact same type, the tmp=tmp-1; statement is not valid: while sizeof(struct b) may report something like 8, this does not mean there's zero padding between the two structures.
Instead, you should use the offsetof macro to get the address of z, given the address of z.y:
struct a *z = (struct a *)((char *)addr - offsetof(struct a, y));
Note, however, that this may break aliasing assumptions, as part of the object pointing to z is also pointed to by y, but the pointers are not compatible.
include <stdio.h>
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
void copy_val(struct c *c_pointer)
{
struct b *tmp = (struct b *) (c_pointer-1);
tmp->b_inner_int = c_pointer->c_inner_int;
tmp->b_inner_char = c_pointer->c_inner_char;
}
int main(int argc, char **argv)
{
struct a test;
test.y.c_inner_int = 32;
test.y.c_inner_char = 'A';
copy_val(&test.y);
printf("b inner int : %d\n", test.x.b_inner_int);
printf("b inner char %c\n", test.x.b_inner_char);
return 0;
}
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;
}
Is there a way to design a macro that could ensure an element is at the start of a struct during it's definition? For example:
typedef struct {
START(int a);
} b;
// Becomes
typedef struct {
int a;
} b;
But generate a compiletime error when it isn't the first element?
typedef struct {
int c;
START(int a);
} b;
// Generate an error
I was thinking you could use a combo of the OFFSETOF and BUILD_BUG_ON_ZERO macros but this would require knowing the struct layout while initializing it, and produces an error because the variable is undeclared.
Is this possible in C?
Use a compile time assertion at the locations you actually assume that layout, instead of at the definition site. Of course you will need to actually define it at the start in order to pass the assertion.
Perhaps something like this would work for you:
#define typedef_header(x) typedef struct { x
typedef_header(int a);
int c;
} b;
int main()
{
b x;
}
I am trying to port some old code over from a 20 year old DOS system to a GNU Linux system. In several of their header files, (which are included all over the place), they have structs of structs that they declare and initialize. I am getting warnings when I compile with the way the legacy code was written. Any tips on how I can get this to work with staying inside the same header file?
The following is a simplified example I made of what they are doing.
struct A
{
struct B temp1;
struct C temp2;
};
struct B
{
int temp3;
int temp4;
int temp5;
};
struct C
{
int temp6;
int temp7;
int temp8;
};
//These are the variables in how they are related to the initialization below
//struct A test_one = {{temp3,temp4,temp5},{temp6,temp7,temp8}};
struct A test_one = {{1,2,3},{4,5,6}};
You shouldn't instantiate any structures in header files. If you do a different instance will be created in each C file you include the header in which is usually not the desired effect.
In a C file to do this you would have to do the following.
void foo(){
struct A parent;
struct B child_b;
struct C child_c;
child_b.temp3 = 3;
child_b.temp4 = 4;
child_b.temp5 = 5;
child_c.temp6 = 6;
child_c.temp7 = 7;
child_c.temp8 = 8;
parent.temp1 = child_b;
parent.temp2 = child_c;
}
I would strong consider making helper functions similar to this
void initB(struct B* s, int x, int y, int z){
s->temp3 = x;
s->temp4 = y;
s->temp5 = z;
}
If you would like the keep the array initialization syntax then consider using a union.
Declare struct B and C before A, i.e. :
struct B { int temp3; int temp4; int temp5; };
struct C { int temp6; int temp7; int temp8; };
struct A { struct B temp1; struct C temp2; };
The code you posted is not compilable, since it is illegal to use incomplete type to declare struct members. I assume that you simply misarranged your struct definitions: the definitions for B and C should go first.
Having said that, the only warning this code can generate is the "warning" from linker that might complain about multiple definitions of the same object test_one, if the header file is included in multiple translation units. In C this is technically illegal, although many compilers allow it as a popular compiler extension.
So, what "warnings" are you getting?