C ++中的宏和常量有什么区别? [英] What is the difference between a macro and a const in C++?

查看:33
本文介绍了C ++中的宏和常量有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一次技术面试中被问到这个问题:

I was asked this question in a technical interview:

const 和 C++ 中的宏有什么区别?

What is the difference between a const and a macro in C++?

我的回答是宏是一个预处理器指令,如果使用宏可能很难调试应用程序,因为它在编译之前被常量表达式替换,而 const 可以类型标识符,易于调试.

My answer was that a macro is a preprocessor directive and it could be difficult to debug the application if you use a macro since it is replaced with the constant expression before compilation, whereas a const can have a type identifier and is easy to debug.

谁能指出任何其他区别,哪个应该是首选?

Could anyone point out any other difference and which should be preferred?

来自 IBM 的 C++ 文档:

From the IBM documentation for C++:

以下是#defineconst类型限定符的一些区别:

The following are some differences between #define and the const type qualifier:

  1. #define 指令可用于为数字、字符或字符串常量创建名称,而可以声明任何类型的 const 对象.

  1. The #define directive can be used to create a name for a numerical, character, or string constant, whereas a const object of any type can be declared.

一个 const 对象受制于变量的作用域规则,而使用 #define 创建的常量则不受.与 const 对象不同,宏的值不会出现在编译器使用的中间源代码中,因为它们是内联扩展的.内联扩展使宏值对调试器不可用.

A const object is subject to the scoping rules for variables, whereas a constant created using #define is not. Unlike a const object, the value of a macro does not appear in the intermediate source code used by the compiler because they are expanded inline. The inline expansion makes the macro value unavailable to the debugger.

宏可用于常量表达式,例如绑定数组,而 const 对象则不能.(我想我们肯定需要使用宏来定义array_size.

A macro can be used in a constant expression, such as an array bound, whereas a const object cannot. (I think we surely need to use macro to define array_size.

编译器不对宏进行类型检查,包括宏参数.

The compiler does not type-check a macro, including macro arguments.

推荐答案

宏和常量并不是一回事,有时每个都适合具体情况,而您的回答只是触及了差异的表面.此外,C++ 有两种不同的常量.

Macros and constants are not remotely the same thing, each is sometimes appropriate for the circumstances, and your answer only scratches at the surface of the difference. Also, C++ has two different kinds of constants.

const 限定符定义的常量最好被视为一个不可修改的变量.它具有变量的所有属性:它有一个类型,它有一个大小,它有链接,你可以获取它的地址.(编译器可能会优化掉其中的一些属性,如果它可以摆脱它:例如,从未使用过地址的常量可能不会被发送到可执行映像中.但这只是由于 as-if 规则的恩典.) 唯一不能对 const 数据做的事情就是改变它的值.用 enum 定义的常量有点不同.它有一个类型和一个大小,但它没有链接,你不能取它的地址,它的类型是唯一的.这两个都是在翻译阶段 7 处理的,所以它们只能是左值或右值.(我很抱歉前一句中的行话,但我不得不写几段.)

A constant defined with the const qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address. (The compiler might optimize away some of these properties if it can get away with it: for instance, constants whose address is never used may not get emitted into the executable image. But this is only by the grace of the as-if rule.) The only thing you can't do to a const datum is change its value. A constant defined with enum is a little different. It has a type and a size, but it doesn't have linkage, you can't take its address, and its type is unique. Both of these are processed during translation phase 7, so they can't be anything but an lvalue or rvalue. (I'm sorry about the jargon in the preceding sentence, but I would have to write several paragraphs otherwise.)

宏的约束要少得多:它可以扩展到任何标记序列,只要整个程序仍然是一个格式良好的程序.它没有任何变量的属性.将 sizeof& 应用于宏可能会或可能不会做一些有用的事情,具体取决于宏扩展的内容.宏有时被定义为扩展为数字文字,并且这些宏有时被认为为常量,但它们不是:编译器正确"(即翻译阶段 7)将它们视为 数字字面量.

A macro has far fewer constraints: it can expand to any sequence of tokens, as long as the overall program remains a well-formed program. It doesn't have any of the properties of a variable. Applying sizeof or & to a macro may or may not do something useful, depending on what the macro expands to. Macros are sometimes defined to expand to numeric literals, and such macros are sometimes thought of as constants, but they're not: "the compiler proper" (that is, translation phase 7) sees them as numeric literals.

现在通常认为是一种很好的做法,当常量可以使用时不要使用宏.宏不遵守与所有其他标识符相同的范围规则,这可能会造成混淆,如果您使用常量,您会为翻译阶段 7 提供更多信息,从而也提供给调试器.但是,宏允许您做任何其他方式无法完成的事情,如果您需要做其中一件事情,您应该毫不犹豫地使用它们.(从这个意义上说,正在发挥作用的宏通常只是扩展为数字文字,尽管我不会说永远不会.)

It is generally considered good practice, nowadays, not to use a macro when a constant will do. Macros don't obey the same scoping rules as all other identifiers, which can be confusing, and if you use a constant you give more information to translation phase 7 and thus also to the debugger. However, macros permit you to do things that cannot be done any other way, and if you need to do one of those things, you should not hesitate to use them. (Macros that are pulling their weight, in this sense, generally do not just expand to numeric literals, though I am not going to say never.)

这是一个宏做一些有趣事情的例子.它绝不是一个常数,形状或形式.很可能有一种方法可以在没有宏的情况下获得相同的效果(如果你知道一个不涉及字符串流的方法,我很想知道它!)但我认为它很好地说明了功能和宏的危险(对于后者,请考虑如果在一个非常特定的上下文之外使用它会做什么......)

Here's an example of a macro doing something interesting. It is in no way, shape or form a constant. There may well be a way to get the same effect without a macro (if you know one that doesn't involve stringstreams, I'd be curious to hear about it!) but I think it makes a good illustration of both the power and the danger of macros (for the latter, consider what it would do if it was used outside of one very specific context...)

static double elapsed()
{ ... }
#define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] "

// usage:
for (vector<string>::iterator f = files.begin(); f != files.end(); f++) {
    cout << ELAPSED << "reading file: " << *f << '
';
    process_file(*f);
}

这篇关于C ++中的宏和常量有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆