代码之家  ›  专栏  ›  技术社区  ›  matt

常数算术的编译时评估是怎样的?它能在预处理器中完成吗?

c c++
  •  3
  • matt  · 技术社区  · 15 年前
    template <int T>
    void aFunc(){}
    
    int main()
    {
    
        int anArray[45-32];
    
        switch(4)
        {
        case 4<45:
            break;
        }
        aFunc<4*3/7&8 == 45 - 5>();
    }
    

    所以这些都是用VC++2005编译的

    这是标准吗?如果是,条件运算符返回什么?0和1?有限制吗?

    我最感兴趣的事情,你能在宏中做吗?定义?

    编辑:

    要进一步详细说明预处理器位:

    #define STRINGAFY(n)     #n
    #define STRINGAFY_2(n)   STRINGAFY(n)
    
    #define SOME_RANDOM_MACRO(n)     n
    
    
    printf("%s", STRINGAFY(1));  //prints out "1"
    printf("%s", STRINGAFY(SOME_RANDOM_MACRO(1)));  //prints out "SOME_RANDOM_MACRO(1)"
    printf("%s", STRINGAFY_2(SOME_RANDOM_MACRO(1)));  //causes SOME_RANDOM_MACRO to be evaluated and prints out "1"
    printf("%s", STRINGAFY_2(1+1)); // doesn't evaluate and print "2", prints "1+1" :(
    
    5 回复  |  直到 15 年前
        1
  •  1
  •   Matthieu M.    15 年前

    我想你有点误解了。

    常量表达式的实际计算是由编译器完成的,而不是由预处理器完成的。预处理器只计算宏,这与文本替换有关。

    如果你退房 Boost.Preprocessor 您将认识到,即使是简单的操作(如加法或soutranctions)也不能使用公共表达式来表示,如果您希望由预处理器对它们进行评估的话。

    BOOST_PP_ADD(4, 3) // expands to 7
    BOOST_PP_SUB(4, 3) // expands to 1
    

    这是在幕后通过子条件实现的,例如,您可以这样定义它(尽管这会很麻烦):

    #define ADD_IMPL_4_3 7
    
    #define BOOST_PP_ADD(lhs, rhs) ADD_IMPL_##lhs##_##rhs
    

    所以这与编译器所做的不同;)

    至于测试编译器是否能够计算表达式,只需使用模板。

    template <int x> struct f {};
    
    typedef f< 3*4 / 5 > super_f_type;
    

    如果它编译,那么编译器就能够正确地计算表达式…否则它将无法实例化模板!

    注: 的实际定义 BOOST_PP_ADD 更复杂的是,这是一个玩具例子,可能无法正常工作> BOOST_PP_ADD(BOOST_PP_SUB(4,3),3) .

        2
  •  7
  •   kennytm    15 年前

    这是标准吗?

    对。这些叫做 "constant expressions" 。(参见C++标准中的5.19(Exp.const))。

    如果是,条件运算符返回什么?0和1?有限制吗?

    false true ,可以隐式转换为0和1。(当然,在您的情况下,返回0是因为 & 优先级低于 == )

    你能用宏指令吗?定义?

    我不明白这个问题。某些表达式在预处理时计算 #if ,但不影响。

        3
  •  1
  •   Kirill V. Lyadvinsky    15 年前

    这是C++标准5.19:

    在几个地方,C++需要将表达式计算为整型或枚举常量: 边界(8.3.4,5.3.4),作为case表达式(6.4.2),作为位字段长度(9.6),作为枚举器初始值设定项(7.2), 作为静态成员初始值设定项(9.4.2),以及作为整数或枚举的非类型模板参数(14.3)。

    constant-expression:  
                conditional-expression  
    

    整型常量表达式只能涉及文本(2.13)、枚举器、常量变量或静态 用常量表达式(8.5)初始化的整数或枚举类型的数据成员,非类型模板 整数或枚举类型的参数以及sizeof表达式。浮动文字(2.13.3)can 仅当它们强制转换为整数或枚举类型时才显示。仅类型转换为整数或枚举 可以使用类型。特别是,除sizeof表达式外,不应使用函数、类对象、指针或引用。

    其他表达式仅被视为非局部静态对象的常量表达式。 初始化(3.6.2)。

        4
  •  1
  •   MSalters    15 年前

    回答最后一点:有许多常量可以在模板中使用,但不能在宏中使用。

    例如, sizeof(int) 是常量表达式。但是 sizeof 表达式未在宏上下文中计算。你不会写字 #if sizeof(int)==4 .

    另外,预处理器根本无法处理浮点运算。

        5
  •  0
  •   Gabriel Ščerbák    15 年前

    对我来说,它看起来不太标准,我确信C++是用布尔类型工作的,所以必须返回布尔类型(因为代码是C++的,不是因为模板,所以是C++)。可能会发生一些自动转换。作为一般的经验法则,尽量避免C++中的宏。