<p>and places the cursor inside the tag, indented once, in insert mode.</p> #ifdef vs #if - which is better/safer as a method for enabling/disabling compilation of particular sections of code?

...which of those methods sounds better to you and why? My feeling is that the first is safer because there is always something defined and there's no danger it could destroy other defines elsewhere.

errer">surround.

111060 次浏览

#if gives you the option of setting it to 0 to turn off the functionality, while still detecting that the switch is there.

I find it more convinient to make vim write both opening and closing tag for me, instead of just the closing one. You can use excellent ragtag plugin by Tim Pope. Usage looks like this (let | mark cursor position) Personally I always #define DEBUG 1 so I can catch it with either an #if or #ifdef

you type:

span|

press CTRL+x SPACE

and you get

<span>|</span>

I myself prefer:

#if defined(DEBUG_ENABLED)

You can also use CTRL+x ENTER instead of CTRL+x SPACE, and you get

<span>
|
</span>

Since it makes it easier to create code that looks for the opposite condition much easier to spot:

#if !defined(DEBUG_ENABLED)

vs.

#ifndef(DEBUG_ENABLED)

The first seems clearer to me. It seems more natural make it a flag as compared to defined/not defined.

Here is what C++ Gotchas by Stephen C. Dewhurst says about using #if's.

allml (now Ragtag ) and Omni-completion ( <C-X><C-O> ) doesn't work in a file like .py or .java.

if you want to close tag automatically in those file,

I've always used #ifdef and compiler flags to define it...

you can map like this.

imap <C-j> <ESC>F<lyt>$a</^R">

I think it's entirely a question of style. Neither really has an obvious advantage over the other.

( ^R is Contrl+R : you can type like this Control+v and then Control+r )

Consistency is more important than either particular choice, so I'd recommend that you get together with your team and pick one style, and stick to it.

(| is cursor position )

Both are exactly equivalent. In idiomatic use, #ifdef is used just to check for definedness (and what I'd use in your example), whereas #if is used in more complex expressions, such as #if defined(A) && !defined(B).

Conclusion

I'd rather live without macros in my code, but for multiple reasons (defining header guards, or debug macros), I can't.

Check out vim-closetag

It's a really simple script (also available as a vundle plugin) that closes (X)HTML tags for you. From it's README:

But at least, I like to make them the least interactive possible with my legitimate C++ code. Which means using #define without value, using #ifdef and #ifndef (or even #if defined as suggested by Jim Buck), and most of all, giving them names so long and so alien no one in his/her right mind will use it "by chance", and that in no way it will affect legitimate C++ code.

If this is the current content:

<table|

Post Scriptum

Now you press >, the content will be:

<table>|</table>

Now, as I'm re-reading my post, I wonder if I should not try to find some value that won't ever ever be correct C++ to add to my define. Something like

#define MY_MACRO @@@@@@@@@@@@@@@@@@

that could be used with #ifdef and #ifndef, but not let code compile if used inside a function... I tried this successfully on g++, and it gave the error:

main.cpp|410|error: stray ‘@’ in program|

Interesting. :-)

A little OT, but turning on/off logging with the preprocessor is definitely sub-optimal in C++. There are nice logging tools like Apache's log4cxx which are open-source and don't restrict how you distribute your application. They also allow you to change logging levels without recompilation, have very low overhead if you turn logging off, and give you the chance to turn logging off completely in production.

Oh, and a minor readability point. You should be able to use true/false rather than 0/1 in your #define, and because the value is a single lexical token, it's the one time you don't need parentheses around it.

#define DEBUG_ENABLED true

I'm working on a project with a rather large Oracle database (although my question applies equally well to other databases). We have a web interface which allows users to search on almost any possible combination of fields.

To make these searches go fast, we're adding indexes to the fields and combinations of fields on which we believe users will commonly search. However, since we don't really know how our customers will use this software, it's hard to tell which indexes to create.

instead of

#define DEBUG_ENABLED (1)

You do this once, then always use debug_print() to either print or do nothing. (Yes, this will compile in both cases.) This way, your code won't be garbled with preprocessor directives.

It depends on the operations that occur on the table.

If you get the warning "expression has no effect" and want to get rid of it, here's an alternative:

void dummy(const char*, ...)
{}


#ifdef USE_DEBUG
#define debug_print printf
#else
#define debug_print dummy
#endif


debug_print("i=%d\n", i);

If there's lots of SELECTs and very few changes, index all you like.... these will (potentially) speed the SELECT statements up.

more it will benefit from an index.

Ultimately how many indexes you need depend on the behavior of your applications that ride on top of your database server.

I work on code that uses conditional compilation extensively and we have a mixture of #if & #ifdef. We tend to use #ifdef/#ifndef for the simple case and #if whenever two or more symbols are being evaluation.

mber, but you'll notice when things start to slow down. Make sure your clustered index is the one that makes the most sense based on the data.

How many columns are there?

We have had this same problem across multiple files and there is always the problem with people forgetting to include a "features flag" file (With a codebase of > 41,000 files it is easy to do).

I have always been told to make single-column indexes, not multi-column indexes. So no more indexes than the amount of columns, IMHO.

If you had feature.h:

#ifndef FEATURE_H
#define FEATURE_H


// turn on cool new feature
#define COOL_FEATURE 1


#endif // FEATURE_H
00 files it is easy to do).

If you had feature.h:

#ifndef FEATURE_H
#define FEATURE_H


// turn on cool new feature
#define COOL_FEATURE 1


#endif // FEATURE_H

But then You forgot to include the header file in file.cpp:

#if COOL_FEATURE
// definitely awesome stuff here...
#endif

Then you have a problem, the compiler interprets COOL_FEATURE being undefined as a "false" in this case and fails to include the code. Yes gcc does support a flag that causes a error for undefined macros... but most 3rd party code either defines or does not define features so this would not be that portable.

But then You forgot to include the header file in file.cpp:

#if COOL_FEATURE
// definitely awesome stuff here...
#endif

We have adopted a portable way of correcting for this case as well as testing for a feature's state: function macros.

Then you have a problem, the compiler interprets COOL_FEATURE being undefined as a "false" in this case and fails to include the code. Yes gcc does support a flag that causes a error for undefined macros... but most 3rd party code either defines or does not define features so this would not be that portable.

if you changed the above feature.h to:

#ifndef FEATURE_H
#define FEATURE_H


// turn on cool new feature
#define COOL_FEATURE() 1


#endif // FEATURE_H

We have adopted a portable way of correcting for this case as well as testing for a feature's state: function macros.

But then you again forgot to include the header file in file.cpp:

#if COOL_FEATURE()
// definitely awseome stuff here...
#endif

if you changed the above feature.h to:

#ifndef FEATURE_H
#define FEATURE_H


// turn on cool new feature
#define COOL_FEATURE() 1


#endif // FEATURE_H

The preprocessor would have errored out because of the use of an undefined function macro.

three circumstances, though it is only one index that has to be maintained.

example for the usage of #if

#if CFLAG_EDITION == 0
return EDITION_FREE;
#elif CFLAG_EDITION == 1
return EDITION_BASIC;
#else
return EDITION_PRO;
#endif

This really is a more theoretical questions than practical. Indexes impact on your performance depends on the hardware you have, the version of Oracle, index types, etc. Yesterday I heard Oracle announced a dedicated storage, made by HP, which is supposed to perform 10 times faster with 11g database.

you now can either put the definition of CFLAG_EDITION either in your code

#define CFLAG_EDITION 1
As for your case, there can be several solutions: 1. Have a large amount of indexes (>20) and rebuild them daily (nightly). This would be especially useful if the table gets thousands of updates/deletes daily.

or you can set the macro as compiler flag. Also see here.

2. Partition your table (if that applies your data model). g against it.

Therefore, in this case, it is better to always define the macros and use #if.

I usually proceed like this.

    There is a difference in case of different way to specify a conditional define to the driver:

    diff <( echo | g++ -DA= -dM -E - ) <( echo | g++ -DA -dM -E - )
    

    output:

    344c344
    < #define A
    ---
    > #define A 1
    

    This means, that -DA is synonym for -DA=1 and if value is omitted, then it may lead to problems in case of #if A usage.

I like #define DEBUG_ENABLED (0) when you might want multiple levels of debug. For example:

#define DEBUG_RELEASE (0)
#define DEBUG_ERROR (1)
#define DEBUG_WARN (2)
#define DEBUG_MEM (3)
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL (DEBUG_RELEASE)
#endif
//...


//now not only
#if (DEBUG_LEVEL)
//...
#endif


//but also
#if (DEBUG_LEVEL >= DEBUG_MEM)
LOG("malloc'd %d bytes at %s:%d\n", size, __FILE__, __LINE__);
#endif

Makes it easier to debug memory leaks, without having all those log lines in your way of debugging other things.

Also the #ifndef around the define makes it easier to pick a specific debug level at the commandline:

make -DDEBUG_LEVEL=2
cmake -DDEBUG_LEVEL=2
etc

If not for this, I would give advantage to #ifdef because the compiler/make flag would be overridden by the one in the file. So you don't have to worry about changing back the header before doing the commit.

Using just an #ifdef could allow for a subtle error where something is switched in (or out) unexpectedly because someone or some team has a convention of defining unused things to 0. In some ways, I like this #if approach because it means the programmer actively made a decision. Leaving something undefined is passive and from an external point of view, it can sometimes be unclear whether that was intentional or an oversight.