C Macros to create strings

2019-01-07 14:52发布

Alternative Titles (to aid search)

  • Convert a preprocessor token to a string
  • How to make a char string from a C macro's value?

Original Question

I would like to use C #define to build literal strings at compile time.

The string are domains that change for debug, release etc.

I would like to some some thing like this:

#ifdef __TESTING
    #define IV_DOMAIN domain.org            //in house testing
#elif __LIVE_TESTING
    #define IV_DOMAIN test.domain.com       //live testing servers
#else
    #define IV_DOMAIN domain.com            //production
#endif

// Sub-Domain
#define IV_SECURE "secure.IV_DOMAIN"             //secure.domain.org etc
#define IV_MOBILE "m.IV_DOMAIN"

But the preprocessor doesn't evaluate anything within ""

  1. Is there a way around this?
  2. Is this even a good idea?

7条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-07 15:02

What you need are the # and ## operators, and automatic string concatenation.

The # preprocessing operator turns the macro parameter into a string. The ## operator pastes two tokens (such as macro parameters) together.

The possibility that comes to mind to me is

#define IV_DOMAIN domain.org
#define IV_SECURE(DOMAIN) "secure." #DOMAIN

which should change IV_SECURE to

#define IV_SECURE "secure." "domain.org"

which will automatically concatenate to "secure.domain.org" (assuming the phases of translation are the same in C as C++).

ANOTHER EDIT: Please, please read the comments, which show how I've managed to get confused. Bear in mind that I am thoroughly experienced in C, although perhaps a touch rusty. I would delete this answer, but I thought I'd leave it as an example of how easy it is to get confused by the C preprocessor.

查看更多
再贱就再见
3楼-- · 2019-01-07 15:07

Strings that are next together are combined by the C compiler.

#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
const char *asCString = SUBDOMAIN;
NSString *asNSString = @SUBDOMAIN;
查看更多
混吃等死
4楼-- · 2019-01-07 15:09

As others have noted, use token pasting. You should also be aware that macro names like

__TESTING

are reserved in C (don't know about Objective C) for the implementation - you are not allowed to use them in your own code. The reserved names are anything containing double underscores and anything begining with an underscore and an uppercase letter.

查看更多
甜甜的少女心
5楼-- · 2019-01-07 15:20

I see lots of good and correct answers to your first question, but none to your second, so here's this: I think this is a terrible idea. Why should you have to rebuild your software (particularly the release version) just to change the server name? Also, how will you know which version of your software points at which server? You'll have to build in a mechanism to check at runtime. If it's at all practical on your platform, I recommend you load the domains/URLs from a config file. Only the smallest of embedded platforms may not be "practical" for that purpose :)

查看更多
聊天终结者
6楼-- · 2019-01-07 15:21

Try using the ## operator

#define IV_SECURE secure.##IV_DOMAIN
查看更多
你好瞎i
7楼-- · 2019-01-07 15:24

In C, string literals are concatenated automatically. For example,

const char * s1 = "foo" "bar";
const char * s2 = "foobar";

s1 and s2 are the same string.

So, for your problem, the answer (without token pasting) is

#ifdef __TESTING
    #define IV_DOMAIN "domain.org"
#elif __LIVE_TESTING
    #define IV_DOMAIN "test.domain.com"
#else
    #define IV_DOMAIN "domain.com"
#endif

#define IV_SECURE "secure." IV_DOMAIN
#define IV_MOBILE "m." IV_DOMAIN
查看更多
登录 后发表回答