【问题标题】:is #define in C similar to a static variable in Java?C中的#define类似于Java中的静态变量吗?
【发布时间】:2013-10-02 21:05:14
【问题描述】:

在 C 中我们可以这样写:

#define LOWER 0

在Java中我们可以这样写:

static int lower = 0;

这些语句的目的不就是让其他方法使用变量lower吗?

【问题讨论】:

    标签: java c variables static


    【解决方案1】:

    它们完全不同。定义更像是 C 预处理器使用的复制粘贴。 Static 是 Java 类的属性修饰符。静态属性可以在运行时更改。

    【讨论】:

    • 需要注意的是,在使用static final(带有编译时常数)时会有类似的复制粘贴。
    • 这可能是真的,也可能不是。静态最终属性可以在静态块中分配,这些静态块在类加载器加载类时执行。对于这个简单的例子,它的功能是一样的。
    • 我指的是public static final int a = 42;这样的案例。
    【解决方案2】:

    #define 在 C 中导致文本替换。例如:

    #define PI 3.14
    
    ...
    a = PI * r * r;  // becomes: a = 3.14 * r * r
    

    现在,#define 的范围远不止于此;它不仅限于变量(Java 中没有直接等价的东西)。当您有一个static 变量时,无法保证该变量不会改变,因此无法制作类似的“文本变电站”。 然而,当你声明一个static final 变量并将它分配给一个compile-time constant 时,这样的保证。所以:

    public static final double PI = 3.14;
    
    ...
    a = PI * r * r;  // becomes: a = 3.14 * r * r, like in C
    

    #define 的情况非常相似,静态最终常量在编译时被它们的实际值替换。从这个意义上说,静态最终常量类似于#define 常量。

    【讨论】:

    • 最好说明为什么文本替换可能并不总是产生预期的结果。例如,#define PAGE_WIDTH 8.5#define PRINT_WIDTH PAGE_WIDTH-3double center = PRINT_WIDTH/2; 会将center 定义为8.5-3/2,即7.5
    【解决方案3】:

    静态,没有。

    最终,是的。

    final int LOWER = 0;
    

    final 变量只能初始化一次。

    static 变量属于类,而不是实例。

    然而

    它们可能功能相似,但操作方式完全不同。

    最终变量仍然只是一个变量。 C(++) 中的 #define 实际上在构建时被解释,并相应地修改二进制输出,导致 vales 在运行时成为常量。

    #define 效率更高。

    【讨论】:

    • 我通常同时看到 static 和 final,通常在单独的常量类中。 class Constants { public static final int Lower = 0; }
    • 你怎么知道define更有效?在 c++ 中不应该像变量一样使用 const 吗?
    【解决方案4】:

    #define 是一个预处理器指令 - 您定义的值会在编译之前交换到代码中提到的任何位置。虽然它有许多 pitfalls - 就像任何全局变量一样,它可能与其他地方(除其他外)类似命名的变量发生冲突。

    如果您想要一个常量,请改用const

    【讨论】:

    • 不幸的是,有很多地方(例如数组维度)可以使用编译时常量表达式,但 const-declared 全局变量不能。唯一在语义上表现为常量的 C 构造是常量文字表达式或 enum 值,后者仅限于可表达为 int 的事物。
    【解决方案5】:

    从 C 到 C++ 的第一个建议是:“不要使用 #define”,尝试使用常量变量。 '#define' 很难调试。

    【讨论】:

      【解决方案6】:

      Java final int LOWER=0; 定义的最大优点是 LOWER 始终是一个变量,并且对调试器是可见的。

      在C语言中,定义的值被代码中的预编译器替换,常量名不见了。

      【讨论】:

        【解决方案7】:

        #define lower 0 中,lower 不是变量。在编译时,lower 将被替换为 0,只要它在整个代码中使用。

        static int lower = 0; 定义了一个变量,实际内存引用将在运行时完成以访问变量的值。加值可以在您的代码中更改。

        为避免更改,您可以像这样定义它static final int lower = 0;

        现在编译器在优化方面做得非常好。所以在编译时只有这个lower会被0替换。

        所以你只能“说”C 中的#define lower 0 等价于static final int lower = 0; 但它们并不相同。因为后者在优化阶段被替换了。如果优化关闭,编译时不会被替换。

        我希望这会有所帮助。

        【讨论】:

          【解决方案8】:

          define 预处理器非常适合命名常量,但它不提供 Java(或 C++)常量声明所允许的相同类型检查。作为 C 和 C++ 开发人员多年,我非常喜欢 C++(和 Java)提供的类型检查。让人联想到合同设计等。

          但是 Perl、Python 和 Ruby 等提供“鸭子类型”的语言的灵活性以及对类型声明的不那么严格的方法也具有优点。严格的类型检查提供的哲学学科有其优点。但是当你只是试图声明一个(命名的)const(ant) 时,所有的严格性似乎都被夸大了。

          所以,是的,#define 是拼写“常量”的一种方式。

          #define PIE (3.142) //C preprocessor
          float PIE_() { return 3.142; } //C also
          const float PIE = 3.142; //C++ const
          public static final float PIE = 3.142; //Java
          PIE = 3.142 #Ruby makes variables with initial capital constant
          PIE = 3.142 #Python doesn't really have constants
          #Perl is harder, you really have a hard time defining constants
          sub PIE { 3.142; }
          

          但是请阅读有关在 Python 中将变量设为常量的难度。 http://code.activestate.com/recipes/65207-constants-in-python/?in=user-97991

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-19
            • 2015-02-05
            • 2021-10-20
            • 1970-01-01
            • 2016-08-30
            相关资源
            最近更新 更多