Why does this macro not work like I think it would? - c

I'm a little new to C still, so bear with me.
I am attempting to be able to refer to the elements of a structure via an index. I figured a macro would do the trick, but evidently not. Can anyone explain why the following does not work?
#include <stdio.h>
#define E(Structure, Index) Structure.var_Index
typedef struct test{
int var_0;
}TEST;
int main(){
TEST Test;
E(Test, 0) = 0;
return(0);
}
My IDE says "No member named 'var_Index' in 'struct test'," but I have no # in front of the word Index in the macro.

Merging tokens is done with ##
The following change should work:
#define E(Structure, Index) Structure.var_##Index

var_Index is one token and the compiler (preprocessor) won't see as Index.
You can use ## operator to have it concatenate tokens in macros.
#include <stdio.h>
#define E(Structure, Index) Structure.var_##Index
typedef struct test{
int var_0;
}TEST;
int main(){
TEST Test;
E(Test, 0) = 0;
return(0);
}

Related

Substring macro parameter

It is possible to substring somehow a macro parameter?
I am facing the following problem. I have something like
#define READ(Name) structure.##Name.value
This macro will be called with something like PREFIX_Name and in the structure there are names without the PREFIX. So I need to take care of that prefix. How should I do that?
The best option is obviously not to call the macro like that. The second best option is to rename the struct members.
Failing the good options, the least bad option I can come up with is to write a macro per structure member:
#include <stdio.h>
typedef struct { int x; int y;} foo;
#define PREFIX_x_FIXER structure.x
#define PREFIX_y_FIXER structure.y
#define READ(Name) Name##_FIXER
int main (void)
{
foo structure;
READ(PREFIX_x) = 5;
printf("%d\n", READ(PREFIX_x));
}

Defining struct containing array in C51 not allowed?

Structs containing arrays in C51 are not allowed? After defining a simple structure in my C51 program,
struct RingBuffer
{
int zero;
int size;
int capacity;
char data[10];
};
I got error:..\SOURCE\MYRINGBUFFER.H(25): error C141: syntax error near '['. It is clear that error is on the line with a char array defined in the struct(no errors after commenting).
Am I doing something wrong here? If not, is there anyway I can achieve what I'm attempting to do?
EDIT: All the code.
#ifndef __MY_RING_BUFFER_H__
#define __MY_RING_BUFFER_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct RingBuffer
{
int zero;
int size;
int capacity;
char data[10];
};
#endif
I figured out what's wrong. data is a keyword in C51.

Typedef struct returning different value than stored in C

Maybe I am using a typedef struct completely wrong and am about to ask a stupid question, so please excuse me if that is the case. I have Monster.h.
#ifndef MONSTER_H_
#define MONSTER_H_
typedef struct EnemyStats
{
int EnemyHP;
}EnemyStats;
int Monster(int Selection);
EnemyStats MonsterStats(int Selection);
#endif
I then have Monster.c
#include <stdio.h>
#include "Monster.h"
EnemyStats MonsterStats(int Selection)
{
EnemyStats value;
value.EnemyHP = 60;
return value;
}
Now please understand that at the moment I have simplified my code for the purpose of testing this problem, originally I had 3 integers in my typedef struct and was returning value after storing different numbers in each int. Last I have my Test.c file containing the main function.
#include <stdio.h>
#include "Monster.h"
int main()
{
MonsterStats(1);
EnemyStats value;
printf("%d\n", value.EnemyHP);
}
On three seperate runs of the program, I get the values:
5226069
12000853
11939413
I really cannot find anywhere of this occurring and I don't know exactly what I am doing wrong or if I am misusing the struct. All help is appreciated.
The problem is in your main function. The EnemyStats value struct never get initialised, so it is just random memory from the stack. Correct me if I'm wrong but I believe what you want is:
int main()
{
EnemyStats value = MonsterStats(1);
printf("%d\n", value.EnemyHP);
}

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.

Is something like "typedef int arrChoice[5];" a global variable?

#include <stdio.h>
#include <conio.h>
typedef arrChoice[10] /*is this a global variable?*/
int main() {};
getch();
return 0;
}
its not done yet, but this is what i meant.
typedef is not a global variable, it's simply an alias for another type. I usually use them for function pointers when I'm passing those around because writing them out every time is annoying.
typedef int (*function)(int, int);
I also use them to define a structure, union, or enumeration as a type
typedef struct {
int x;
int y;
int z;
} Point;
typedef declares the new type not variable.
This might help you. In the code you posted here, there is a error. There are no statements in side main function. getch and return statements should be inside main function. I feel your code should be like this.
#include <stdio.h>
typedef int arrChoice; /* arrChoice is alias to int */
arrChoice a[10] ;/* array a is a global variable of integers*/
int main()
{
getch();
return 0;
}
please note that the purpose of typedef is to assign alternative names to existing types(int,float,double,etc.). The following statements are similar.
typedef arrChoice[10] is similar to typedef int[10];
When you try to refer arrChoice, then you get an error message
expected expression before 'arrChoice'.

Resources