-1

Is it possible to have a macro expand in the file it was originally defined in? What I mean by this is that if I do something like:

    #define DEFINE_SAMPLE_CLASS(name) \
    typedef struct{ \
        int example_int; \
    } name; \

I want it to expand in the original file I defined this macro in. Is this possible? The reason I want to do this is because I want users to be able to define a bunch of template-like classes, however once they define them I want them to be able to be used from other files, without having to include a bunch of other header files to get the types they want. If this isn't possible or practical, is there a better approach to this?

edit: clarification

What I'm basically wanting to do is allow users to "add onto" a header file, so that they can declare something like the sample above:

DEFINE_SAMPLE_CLASS(Sample1)

which would expand into:

    typedef struct{
        int example_int;
    } Sample1;

then other files could use these "global" definitions, without having to include all the files that defined them. I want users to be able to define their own versions of these classes, while keeping them "global" and without having to edit the original header.

Shokwav
  • 654
  • 8
  • 19
  • 1
    I suppose you need to provide more details with samples, as currently it looks like you don't understand how .h files work – Iłya Bursov Oct 19 '13 at 00:53
  • 1
    I don't understand the question at all. Could you give an example of how it might be used and what you would like that usage to do? – aschepler Oct 19 '13 at 00:56
  • If I put `#define DEFINE_SAMPLE_CLASS(name) typedef struct name name;` (note the `;` at the end) into a .h file, then call it with `DEFINE_SAMPLE_CLASS(c)` in my .c, it does build. – ryyker Oct 19 '13 at 00:57
  • @llya bursov: clarified – Shokwav Oct 19 '13 at 00:58
  • don't forget the `;` at the end – ryyker Oct 19 '13 at 00:59
  • @ryyker no need for ; as that is added when you type actual code. – this Oct 19 '13 at 01:00
  • So you put `DEFINE_SAMPLE_CLASS(Sample1);` in a header file, right? – aschepler Oct 19 '13 at 01:02
  • Is it not just as easy to do something like `typedef struct {...} A;` `extern A a, *pA;` in your header file, then `A a, *pA;` in each .c module you need to use them? More readable for people who have to maintain the code later I would think. – ryyker Oct 19 '13 at 01:02
  • @aschepler: yes, and i want it to expand in the header file where that macro is defined, that way users could just include that header instead of having to define it themselves or have to edit the original header. is this making sense? – Shokwav Oct 19 '13 at 01:03
  • So you're basically trying to achieve inheritance with structs? – tangrs Oct 19 '13 at 01:04
  • Yes, the #define in a header file, then used it in my .c, but have you considered my other comment?, That suggestion I think would be easier for people to read, and maintain over time. :) – ryyker Oct 19 '13 at 01:05
  • 1
    @Shokwav: The only way to make it work the way you want is if people placed all the `DEFINE_SAMPLE_CLASS(...)` calls into that header file itself. Then it works in an obvious and clear way. – jxh Oct 19 '13 at 01:06
  • But clearly, considering how a #define works, the answer to your question "Can it be defined, then used within the same file?", (phrased with some literary license) the answer is yes. The question then becomes, is this the best way? Popular opinion would most likely say no, but then we are highly opposed to discussing opinion here. :) – ryyker Oct 19 '13 at 01:10
  • @ryyker: can you clarify that extern example you posted? it's confusing me because structs don't have linkage in c, but all variables and functions do. – Shokwav Oct 19 '13 at 01:12
  • @self - Oh, but the thrust of the post is to 'simplify' things for the user, no? Would you then require the user to place their _own_ `;`? Seems like a cruel trick to me. – ryyker Oct 19 '13 at 01:13
  • A macro is expanded wherever you put the macro name, so of course it can be expanded in the file you defined it in by placing the macro name there. If you mean something else, then say it ... preferably with an actual example of what you want the code to look like. – Jim Balter Oct 19 '13 at 01:14
  • @Shokwav "structs don't have linkage in c, but all variables and functions do" -- Eh?? `a` and `pA` are variables. ryyker's example doesn't declare the *type* `A` as extern, just the variables. – Jim Balter Oct 19 '13 at 01:16
  • @ryyker So you end up with code missing ; that gets added when preprocessor does its work? – this Oct 19 '13 at 01:17
  • @jim balter: they are variables of type struct A. guys this isn't about semicolons. I just want a macro to expand in its ORIGINAL HEADER instead of expanding in place like usual. Basically I want a struct definition to be visible to the rest of the program, even if it is defined in a .c file. Is there some way to achieve this – Shokwav Oct 19 '13 at 01:19
  • " they are variables of type struct A" -- No, actually, they aren't ... there is no struct A, just A, which is a struct type with no tag. But what makes you think you can't extern such variables? "I just want a macro to expand in its ORIGINAL HEADER" -- then put the macro name into the header, as rykker and I both said, and it will expand there. As others have said, you don't seem to understand how macros or header files work. – Jim Balter Oct 19 '13 at 01:23
  • Hmmm - evidently this question has enough interesting qualities to engage several resondants. And OP is responsive to all of our inquiires for clarification. WHY the downvote? – ryyker Oct 19 '13 at 01:26
  • @jim balter: yes, i worded that poorly, I realize that literally "struct A" is not a type. ryyker answered the bulk of my question – Shokwav Oct 19 '13 at 01:27
  • @self - If in a #defined macro, if is written to expand syntax (code) that would normally require a `;` statement terminator, but the macro does not include it, then the compiler will complain, just like it would with regular in-line code. – ryyker Oct 19 '13 at 01:29
  • 1
    I've re-read this question a dozen times and it's still hopelessly confused. Again, an actual source example of the desired usage would help tremendously and would be far clearer than the mangled explanation. – Jim Balter Oct 19 '13 at 02:09

3 Answers3

1

I want it to expand in the original file I defined this macro in. Is this possible?

Yes. In your header file, put

#define DEFINE_SAMPLE_CLASS(name) typedef struct name name
DEFINE_SAMPLE_CLASS(Sample1);

Done ... now Sample1 can be used as a type in any source file that includes your header file.

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
1

As an alternative to Jim Balter's answer, you can do something like this:

/* header file */
#pragma once

#define DEFINE_SAMPLE_CLASS(name) \
typedef struct{ \
    int example_int; \
} name

#include "sample_class_definitions.h"

Then, the file sample_class_definitions.h can be a script generated file where people simply add the name of the class they want to define to some make script. Or, the users can just add the appropriate DEFINE_SAMPLE_CLASS(...) code line to that header file.

Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
0

Response to your question in comment: (also read HERE for great discussion on extern usage.)

Declaring struct like this, then extern'ing a copy of it (or any variable for that matter) allows it to contain the same value, and be seen with the same value in all files that use it.

In .h

typedef struct {
    int a;
    char *b;
}A: 
//A has just been created as a new type, i.e. struct A, so it now conforms to the same rules other variable conform to with regards to the use of extern.  So...  

extern A a, *pA;//create a global copy of A with extern modifier  

Then in file1.c

A a, *pA;  //copy of externed variable 
int main(void)
{
    pA = &a;//initialize pA here, use everywhere in file;
    return 0;
}  

Then in file2.c

A a, *pA;

[EDIT] My original answer is untouched, and does answer a very specific question by OP: in clarification of my comment:

Is it not just as easy to do something like typedef struct {...} A; extern A a, *pA; in your header file, then A a, *pA; in each .c module you need to use them? More readable for people who have to maintain the code later I would think

OP asked:

@ryyker: can you clarify that extern example you posted? it's confusing me because structs don't have linkage in c, but all variables and functions do.

The above request is answered above. OP accepted the answer. This edit is in response to @Jim Balter's aggressive complaints/claims about my answers validity. The new code has been cleaned up and tested to illustrate the use of creating and using a project visible variable, using the extern modifier. The following code example will demonstrate:

header.h

int somefunc(void);
typedef struct {
    int num;
    char *b;
}A; 
//A has just been created as a new type, i.e. struct A, so it now 
//conforms to the same rules other variable conform to with 
//regards to the use of extern.  So...  

extern A a, *pA;//create a global copy of A with extern modifier    

file1.c

#include <ansi_c.h>
#include "header.h"

A a, *pA;
int main(void)
{
    pA = &a;//initialize pA here, use everywhere in file;
    pA->num = 45;
    pA->b = malloc(strlen("value of pA->b")+1);
    somefunc();
    printf("value of pA->b is: %s\n", pA->b);
    getchar();
    free(pA->b);
    return 0;
}  

file2.c

#include <ansi_c.h>
#include "header.h"

A a, *pA; //Note: optional presence of A in this file.  
          //It is not Not necessary to place this line, 
          //but for readability (future maintainers of code
          //I always include it in each module in which it is used. 
int somefunc(void)
{
    printf("%d\n", pA->num);//value of pN->num same as in file1.c 
    strcpy(pA->b, "value of pA->b");
    return 0;
}

Building and running these files will demonstrate the project visibility of the A struct created
header.h, and used in both file1.c and file2.c (and as many .c files as are needed)
It also substantiates the claims I made in my original answer.

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • "struct A" -- No, you have not defined such a type. If you want that, then do `typedef struct A { ... } A;` "create a global copy of A with extern modifier" -- no, there's no extern of A, which is a type and it's meaningless to extern it ... `a` and `pA` are extern. And they aren't "copies", they're declarations. "//copy of externed variable" -- no, these aren't "copies" of anything, they are definitions of the variables that were declared in the header file ... definitions allocate memory, declarations do not. – Jim Balter Oct 19 '13 at 01:29
  • @Jim - would you not use `extern int whatever, *pWhaterver;`. Synonymous with `extern A a, *pA;`, no? – ryyker Oct 19 '13 at 01:32
  • 1
    `extern int ...` does not create a global copy of int with extern modifier, now does it. What you should say is that `extern A a, *pA;` declares `a` and `pA` with extern linkage ... it doesn't do anything at all to `A` ... A is a type with file scope. – Jim Balter Oct 19 '13 at 01:36
  • The OP seems to want to avoid including the header file in the source files, but that isn't possible, so this answer should mention that file1.c and file2.c must include the .h file. BTW, file1.c and file2.c should not both define `a` and `pA` ... that's non-conforming. – Jim Balter Oct 19 '13 at 01:45
  • @Jim - Agreed,... simply by using extern modifier, a global is not necessarily _created_. But, as a nice side effect, if it is desired to have a project global, then doing what I described above will accomplish that. On your other point, by naming a .h, file1.c and file2.c in the example, I was answering a very specific question by OP (see earlier comments), and so assumed in that context it would be understood that file1.c and file2.c would #include the .h. – ryyker Oct 19 '13 at 02:29