Alternative declarations of a variable depending on an if condition - c

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.

Related

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))

How can I properly assign a value to an array (of structure type) element?

#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}
};

C macro to ensure element is at start of struct

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;
}

use c Token-Pasting to access field in struct

I'm trying to use c token pasting (##) to access to struct field as below:
typedef struct
{
int a;
int b;
} TMP_T;
#define BUILD_FIELD(field) my_struct.##field
int main()
{
TMP_T my_struct;
BUILD_FIELD(a) = 5;
return 0;
}
But got the following error during compilation:
error: pasting "." and "a" does not give a valid preprocessing token
I would like to add additional case to that:
typedef struct {
int a;
int b;
}TMP_T;
#define BUILD_FIELD(my_struct,field) my_struct.##field
void func(char* name)
{
TMP_T tmp_str;
if((name == "a") || (name == "b"))
{
BUILD_FIELD(tmp_str, name) = 7;
printf("%d \n", BUILD_FIELD(a) );
}
}
int main()
{
func("a");
return 1;
}
How should I use the macro to access the specific struct and field. Is it possible? or because its a pre compiled then it couldn't be defined for various fields (a,b)
Thanks
Moti
You don't need token pasting at all:
#define BUILD_FIELD(field) my_struct.field
According to the gcc manual token pasting should result in an identifier or a number after the concatenation. The error is due to the .a not being either.
All that is required is to use the macro replacement string field. Try this:
#define BUILD_FIELD(field) my_struct.field.
So the following code will work:
#include <ansi_c.h>
typedef struct {
int a;
int b;
}TMP_T;
#define BUILD_FIELD(field) my_struct.field
int main(void)
{
TMP_T my_struct;
BUILD_FIELD(a) = 5;
printf("my_struct.a is %d\n",my_struct.a);
BUILD_FIELD(b) = 10;
printf("my_struct.b is %d\n",my_struct.b);
return 0;
}
By the way, I also ran the above code with the line: (after having read Krister Andersson's link)
#define BUILD_FIELD(field) my_struct.##field
It ran identical to the code without using ## stringification. So, there is obviously something different between our compilers.
In any case, I hope my original assertions did not add too much confusion. Your question taught me a few lessons today. Thanks! (+1)
Addressing your latest post edit:
First of all this modification will result in a compile error for an unknown field name within TMP_T here:
BUILD_FIELD(tmp_str, name) = 7;
Here is a good link that discusses Preprocessing, Compiling and Linking (of greatest interest for this discussion will be the preprocessing and compile parts). Among other things, it discusses when to use macros.
Also, regarding the line:
if((name == "a") || (name == "b"))
When doing string compares, the == is not used. strcmp(), or even strstr() are used for string comparisons.
You would need pasting if you create your struct with some "structure". For example:
typedef struct
{
int tmp_a;
int tmp_b;
} TMP_T;
#define BUILD_FIELD(field) my_struct.tmp_##field
It's used for tokenization. Your use case is the "typical" macro variable replacement.

Passing Enumerations in a Function that's in a Struct (in 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.

Resources