Reputation: 3
In a simple example, I have two source files...one using a particular string, like this:
main.c
#include <stdio.h>
#include "stringdata.h"
int main(int argc, char *argv[])
{
print_somestring(thestring, (enum strsizes)stringlen);
return 0;
}
Then this:
stringdata.c
const unsigned char thestring[] = "This is a string\n";
enum strsizes
{
stringlen = sizeof(thestring) - 1 //to account for the null byte
};
The header for main:
stringdata.h
extern const unsigned char thestring[];
extern enum strsizes; //<-- how?
Now, I've tried to compile that and I got what I expected...it doesn't like it. The major issue is being able to have the enum "see" the actual defined strings so that sizeof evaluates properly; the extern symbol alone doesn't give sizeof enough information, thus I'd have to declare and initialize the strings in every compilation unit, which would obviously break.
I understand that normally, you'd define the enum type in the header, and then use the constants where you need them. In this case, the value of the constants depend on compile time conditions (the evaluated "byte" size of the string).
In order to use those constants in other compilation units, I'd need the enum type definition to "stick", if you will. Obviously, an extern won't do it. Making the constants take up actual storage by using a real type i. e. const int is what I want to avoid.
I've tried for quite a while to look up examples, but none of them seem to be what I'm looking for. The solutions I have found involve C++ Template Meta Programming, but I'm strictly using C.
If anyone could help me out, thanks well in advance (this will have other very beneficial effects on my project).
Upvotes: 0
Views: 338
Reputation: 40397
You can actually do this.
First, define all of the strings you need to do this with as macros in a header file, for example:
#define THE_STRING "This is a string\n"
Then create a typedef for your enum in the header file, or one that includes it:
typedef enum {
stringlen = sizeof(THE_STRING) -1
} the_enum_t;
Now in some C source file allocate an instance of the enum
#include "headerfile.h"
the_enum_t strsizes = stringlen;
And finally in some other file, use it:
#include <stdio.h>
#include "headerfile.h"
extern the_enum_t strsizes;
int main (int argc, char ** argv) {
printf("length is %d\n", strsizes);
return 0;
}
Compile and link and run it. You'll see that you are able to access the value of the enum. If you objdump the binary you will see space allocated for the enum variable. But you will not see the string itself occur anywhere in the binary, as it's length has been evaluated at compile time, and the actual contents of the string are (so far) unused anywhere in the program.
The key points are that
1) If you want to share a custom data type between files, create a typedef and then share an instance of it.
2) If you don't intend to use the contents of the string, don't define a string variable, instead just use the string constant at compile time to evaluate it's length. If you intend to do both, use the string constant for both purposes by defining it as a macro.
Upvotes: 2