Passing Enumerations in a Function that's in a Struct (in C) - c

I have looked up how to pass an enumeration in a function, but that method doesn't work when both the function and enumeration are declared in a structure. Here is my code :
test_setup.h:
1 #ifndef TEST_SETUP_H_
2 #define TEST_SETUP_H_
3 #include <stdio.h>
4 #include <stdlib.h>
5
6
7 typedef struct _test_setup {
8
9 int *partner;
10 int *send_first;
11 double *results;
12
13 enum { CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE } SomeMatches;
14 void match_partners(SomeMatches match);
15
16 } test_setup;
17
18 #endif
test_setup.c :
1 #include "../includes/test_setup.h"
2
3 void match_partners(SomeMatches match) {
4 if (match == CHIP_WIDE) {
5
6 }
7 else if (match == NODE_WIDE) {
8
9 }
10 else if (match == SYSTEM_WIDE) {
11
12 }
13 else {
14
15 }
16 }`
Error:
In file included from src/test_setup.c:1:
src/../includes/test_setup.h:14: error: expected ‘)’ before ‘match’
src/../includes/test_setup.h:16: warning: no semicolon at end of struct or union
src/test_setup.c:3: error: expected ‘)’ before ‘match’
make: *** [setup.o] Error 1
I have tried every combination of declaring an enumeration and using it in the function parameters, but nothing has worked. Any ideas would be much appreciated. I am compiling with mpicc (because the rest of the program uses MPI functions) but I have tried with GNU GCC and I get the same warnings/errors.

For C
If you truly want C, then you simply can't do any of this.
You can't define a member function in a struct
You can't define a named enumeration nested in a struct
For C++
Use the scope-resolution operator ::
#include<iostream>
struct Test
{
enum SomeEnum { TEST1, TEST2, TEST3 };
void SomeFunction(SomeEnum e);
};
void Test::SomeFunction(Test::SomeEnum e)
{
std::cout << e << "\n";
}
int main(int argc, char* argv[])
{
Test t;
t.SomeFunction(Test::TEST1);
return 0;
}

If you want to do this in C, here are the workarounds:
// define the enumeration at file scope:
typedef enum {CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE} SomeMatches;
// declare a *pointer* to a function in the struct:
typedef struct {
int *partner;
int *send_first;
double *results;
void (*match_partners)(SomeMatches match);
} test_setup;
Define your function as normal:
void match_partners(SomeMatches match)
{
if (match == CHIP_WIDE) {}
else if (match == NODE_WIDE) {}
else if (match == SYSTEM_WIDE) {}
}
Then when you create an instance of the struct, assign the function pointer:
test_setup t;
t.match_partners = match_partners;
You don't need to explicitly dereference the function pointer to call it, so you can execute your function as
t.match_partners(CHIP_WIDE);
although if you want to dereference it explicitly, use
(*t.match_partners)(CHIP_WIDE);
Note that C doesn't have any equivalent to the this pointer; if match_partners depends on information contained in the struct instance, you'll have to explicitly pass that instance as a separate argument:
void match_parthers(SomeMatches matches, test_setup *instance)
{
}
...
typedef struct {
...
void (*match_partners)(SomeMatches matches, test_setup *instance);
...
} test_setup;
...
test_setup t;
t.match_partners = match_partners;
t.match_partners(CHIP_WIDE, &t);
Note that for the struct definition to be legal, we have to pass the instance as a pointer, since the test_setup type isn't complete at that point.
EDIT
That last sentence isn't terribly clear; let me try again. A struct definition cannot refer to an instance of itself, because the struct type isn't complete until the closing }. IOW, the following is not legal:
struct foo
{
...
struct foo bar;
...
};
However, a struct can refer to a pointer to another instance of the same type, so the following is legal:
struct foo
{
...
struct foo *bar;
...
};
The same logic applies to the function pointer declaration; the instance parameter needs to be declared as test_setup *, since the test_setup type definition isn't complete at that point. As Merlyn points out in the comments, you probably want the instance to be mutable anyway, but the language requires you to use a pointer in that circumstance.

Your enum does not have a proper name (it doesn't have a tag) and cannot be referenced from distinct points in the code. Try this:
enum SomeMatches { CHIP_WIDE, NODE_WIDE, SYSTEM_WIDE };
struct _test_setup {
/* ... */
enum SomeMatches SomeMatches;
void (*match_partners)(enum SomeMatches match);
/* ... */
};
Sprinkle typedefs at will, or leave things bare ...

First of all #define TEST_SETUP_H_ goes before #ifndef TEST_SETUP_H_. Otherwise your code will be completely commented out to the compiler.
You don't name a typedef struct like that it goes as such:
typedef struct struct_name{
/contents/
};
void match_partners(SomeMatches match) can be void match_partners(void) and use the variable inside the function because with that header file you've made it global and don't need to pass it.

Related

"‘return’ with a value, in function returning void" when returning a struct

I am getting compilation error:
warning: ‘return’ with a value, in function returning void
Here is my code:
#include <stdio.h>
typedef struct
{
int a;
char b;
}
values;
values keyword;
struct values get_keyword(void)
{
return keyword;
}
int main()
{
keyword.a = 10;
}
struct values is not a type. values is though, since you typedefined it:
Corrected:
values get_keyword(void) {
return keyword;
}
A more complete output from when compiling your program would include this first error:
<source>:10:15: error: return type is an incomplete type
10 | struct values get_keyword(void) {
| ^~~~~~~~~~~
<source>: In function 'get_keyword':
So, now get_keyword becomes void which triggers the secondary error you showed in the question:
<source>:11:12: warning: 'return' with a value, in function returning void
11 | return keyword;
| ^~~~~~~
<source>:10:15: note: declared here
10 | struct values get_keyword(void) {
| ^~~~~~~~~~~
ASM generation compiler returned: 1
Previous errors often explains later errors, which was the case here.
Your struct has no tag, only typedefed alias name values.
typedef struct
{
int a;
char b;
}values;
values keyword;
values get_keyword(void)
{
return keyword;
}
If you want to use it without using the alias (but still to use typedef) you need to add the tag:
typedef struct values
{
int a;
char b;
}values;
values keyword;
struct values get_keyword(void)
{
return keyword;
}

Alternative declarations of a variable depending on an if condition

I would like to have as, if i is 1 then a as int type otherwise as char type,but when i compile this code then it encounters below error:
> 1.c: In function ‘main’:
> 1.c:18:16: error: ‘a’ undeclared (first use in this function)
> if(a)
> ^
> 1.c:18:16: note: each undeclared identifier is reported only once for each function it appears in
#include <stdio.h>
#define macro
void main()
{
int i=1;
#ifdef macro
if (i==1)
{
int a;
}
else
#endif
{
char a;
}
if(a)
{
printf("INDOE ");
}
}
i would like to have as, if i is 1 then a as int type otherwise as char type
Stop right here, compiled C code doesn't know about types, so you can't set a type at runtime -- it's already "hardcoded" the time you compile your program.
Side note:
{
char a;
}
if(a)
The braces give the variable a scope, so after the closing brace, a doesn't exist any more.
There are many ways to solve this, they all involve that you store your own type information. Rough idea:
enum mytype { MT_INT, MT_CHAR };
struct myvalue {
enum mytype type;
union {
int a_int;
char a_char;
};
};
[...]
struct myvalue x;
// [...]
if (i==1) x.type = MT_INT;
else x.type = MT_CHAR;
// [...]
Then in each access of x.a_int or x.a_char, check x.type first to know which member to access.
Scope of a variable in C is limited to the block you have declared it. The int a is available only within the if. And the char a is available only within the else
Search about "scope" concept. A variable, in C, defined in a scope will not be accessible outside it or in a scope above, but is accessible on a scope below.
It looks like you want your condtional to be handled by the preprocessor. eg.
#include <stdio.h>
#define i 1
#if i
#define ATYPE int
#else
#define ATYPE char
#endif
int main(int argc, char* args)
{
ATYPE a;
printf("%d\n", sizeof(a));
}
I certainly wouldn't recommend #define'ing i, but this looks a bit like what you're trying to do.

In C, can a primitive be passed to a function, which is looking for a user-defined datatype as input, if a casting/promotion rule is defined?

Suppose we have a function like this:
void WonderfulFunction(float a)
Clearly, we can pass an int to wonderful_function and the C-compiler will promote the int to a float.
However, what about user-defined data types? Suppose we use a typedef statement to give a name/alias to a struct. Is there some way to define a promotion-rule, casting function, or constructor which will automatically convert a primitive to ADT (abstract data type)? I realize this can be done in C++, but this needs to be in C.
We want something like the following code to compile correctly:
// #include <niffty_promoter_castOperator_thing.h>
struct HappyStruct {
int happy_int;
};
typedef struct HappyStruct HappyStruct;
/* prototype */
void AnotherWonderfulFunction(HappyStruct hs)
int main( ) {
int a = 12345;
AnotherWonderfulFunction(a);
// A caster/promoter included in the
// header file specifies how to
// construct a HappyStruct from an int
return 0;
}
void AnotherWonderfulFunction(HappyStruct hs) {
// do stuff;
}
This is "possible" with generic selection (YMMV); this described here is the closest you can get in C11. (In C99, C89 this is not possible at all). Here, AnotherWonderfulFunction(X) is a macro that will expand to (AnotherWonderfulFunction)(AsHappy(X)); the parentheses ensure that the macro is not recursively expanded.
AsHappy(X) is a macro that uses generic selection to choose one from 2 utility functions - HappyAsIs takes a struct HappyStruct as a parameter and returns it as-is, whereas HappyFromInt expects an int argument, and will return it wrapped in a struct. It needs to be done using utility functions, because at least GCC does check the language constraints for other branches, even though they're not evaluated. The original X is then passed to the selected function as an argument.
#include <stdio.h>
struct HappyStruct {
int happy_int;
};
void AnotherWonderfulFunction(struct HappyStruct hs) {
printf("AnotherWonderfulFunction called with hs.happy_int = %d\n", hs.happy_int);
}
struct HappyStruct HappyAsIs(struct HappyStruct s) {
return s;
}
struct HappyStruct HappyFromInt(int val) {
return (struct HappyStruct){ val };
}
#define AsHappy(X) \
_Generic((X), \
struct HappyStruct: HappyAsIs, \
default: HappyFromInt \
)(X)
#define AnotherWonderfulFunction(X) (AnotherWonderfulFunction)(AsHappy(X))
int main(void) {
int a = 42;
float b = 65536.5;
struct HappyStruct c = { 123 };
AnotherWonderfulFunction(a);
AnotherWonderfulFunction(b);
AnotherWonderfulFunction(c);
}
and running the program produces:
% ./a.out
AnotherWonderfulFunction called with hs.happy_int = 42
AnotherWonderfulFunction called with hs.happy_int = 65536
AnotherWonderfulFunction called with hs.happy_int = 123
However, the magic disappears as soon as you take a pointer to a function;
void (*fp)(struct HappyStruct) = AnotherWonderfulFunction;
now of course fp cannot work that way because it is not a macro.
... until you make it one ...
#define fp(X) (fp)(AsHappy(X))
All this is somewhat useless, since C11 supports compound literals:
AnotherWonderfulFunction((struct HappyStruct){ 42 });
so it is of limited use - lots of black magic to save a few keystrokes.
For cases where you only care about the binary representation (i.e., not in the int-to-float case), you can use GCC's __attribute__((transparent_union))

GCC Casting Pointer to Incompatible Type

I have a working C code when compiled using GCC, but I am trying to find out if the code works because of pure luck or because GCC handles this code as I expect by design.
NOTE
I am not trying to "fix" it. I am trying to understand the compiler
Here is what I have:
iexample.h
#ifndef IEXAMPLE_H_
#define IEXAMPLE_H_
/* The interface */
struct MyIf
{
int (* init)(struct MyIf* obj);
int (* push)(struct MyIf* obj, int x);
void (* sort)(struct MyIf* obj);
};
/* The object, can be in different header */
struct Obj1
{
struct MyIf myinterface;
int val1;
int val2;
};
struct Obj1* newObj1();
#endif
iexample.c
#include <stdio.h>
#include <stdlib.h>
#include "iexample.h"
/* Functions here are "equivalent" to methods on the Obj1 struct */
int Obj1_init(struct Obj1* obj)
{
printf("Obj1_init()\n");
return 0;
}
int Obj1_push(struct Obj1* obj, int x)
{
printf("Obj1_push()\n");
return 0;
}
void Obj1_sort(struct Obj1* obj)
{
printf("Obj1_sort()\n");
}
struct Obj1* newObj1()
{
struct Obj1* obj = malloc(sizeof(struct Obj1));
obj->myinterface.init = Obj1_init;
obj->myinterface.push = Obj1_push;
obj->myinterface.sort = Obj1_sort;
return obj;
}
main.c
#include "iexample.h"
int main(int argc, char* argv[])
{
struct MyIf* myIf = (struct MyIf*) newObj1();
myIf->init(myIf);
myIf->push(myIf, 3);
myIf->sort(myIf);
/* ... free, return ... */
}
When I compile, as I expect, I get for assigning the pointers in newObj1(),
warning: assignment from incompatible pointer type
The code works as long as I have the "struct MyIf myinterface" to be the first member of the struct, which is by design (I like to shoot myself in the foot)
Now, although I am assigning incompatible pointer types, and the C spec says behavior is undefined, does GCC or other compilers make any design claim on how this case is handled? I can almost swear that this OUGHT TO WORK due to how struct memory is laid out, but I cannot find the proof.
Thanks
C11 standard 6.7.2.1 Structure and union specifiers:
Within a structure object, the non-bit-field members and the
units in which bit-fields reside have addresses that increase in
the order in which they are declared. A pointer to a structure
object, suitably converted, points to its initial member (or
if that member is a bit-field, then to the unit in which it
resides), and vice versa. There may be unnamed padding within
a structure object, but not at its beginning.
So it should work as long, as you access only first structure member. However, I believe you understand, that this is pretty bad idea. Should you port this code to C++ and make some Obj1 member virtual, this will immediately fail.

declaration does not declare anything : warning?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
};
struct address a1;
};
}
This code shows a warning:-
warning : declaration does not declare anything (enabled by default)
Where as the following code shows no warning
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
}a1;
};
}
Why 'warning' is displayed in the first code only?
The reason why the compiler is showing the warning is because it doesn't see a name for the variable of type address you defined for the emp struct, even though you do declare something using address on the next line, but I guess the compiler is not smart enough to figure that out.
As you showed, this produces a warning:
struct emp {
struct address {}; // This statement doesn't declare any variable for the emp struct.
struct address a1;
};
But not this:
struct emp {
struct address {} a1; // This statement defines the address struct and the a1 variable.
};
Or this:
struct address {};
struct emp {
struct address a1; //the only statement declare a variable of type struct address
};
The struct emp {} doesn't show any warnings since this statement is not inside a struct defintion block. If you did put it inside one of those then the compiler will show a warning for that as well. The following will show two warnings:
struct emp {
struct phone {};
struct name {};
};
The reason the warning is displayed is that the first excerpt is not proper C - it has a constraint violation that a standards-compliant C compiler must produce a diagnostisc message for. It violates the C11 6.7.2.1p2:
Constraints
A struct-declaration that does not declare an anonymous structure or anonymous union shall contain a struct-declarator-list.
Meaning that it is OK to write
struct foo {
struct {
int a;
};
};
since the inner struct declares an anonymous structure, i.e. it is not named.
But in your example the struct address has a name - address - and therefore it must have a declarator list after the closing brace - declarator list being for example a1 as in your example, or more complex foo, *bar, **baz[23][45].
The syntax of a structure definition is:
struct identifier {
type member_name;
// ...
};
If you add an identifier just after the closing curly brace, you're declaring a variable with that defined struct.
In your first example the compiler consider the address struct as member type. it's like if you writes:
struct identifier {
type ; // No member name is specified
type a1;
// ...
}
But in the second example you specified the member name:
struct identifier {
type a1; // Member name specified
// ...
}
And here is an example of the warning: http://ideone.com/KrnYiE.
Going to also throw this out there that this error may also show up if you don't properly forward declare types found in other namespaces.
https://stackoverflow.com/a/19001722/1330381
Example
namespace A {
// forward declarations
namespace X {
namespace Y {
class MyType;
}
}
namespace B {
class Foo() {
void methodBar(const X::Y::MyType& mt);
}
}
In my case, i had the same warning because the structure name was previously used and changing the structure name solved the problem.

Resources