【问题标题】:Constants in C: declaration separate from definitionC 中的常量:声明与定义分开
【发布时间】:2015-06-06 22:12:08
【问题描述】:

所有C代码:

为什么允许这样做:

int main()
{
    const int *i;
    int j=2;

    i=&j;
}

但不是这个:

int main()
{
    const int i;
    int j=2;

    i=j;
}

有没有办法声明一个局部常量变量,然后在范围内的其他地方定义它?第一种使用指针的情况是不可靠的,因为我可以多次定义它,首先破坏了常量关键字的目的。

【问题讨论】:

    标签: c gcc constants


    【解决方案1】:

    在语义上,第一个示例的意思是“指向 const int 的指针”而不是“指向 int 的 const 指针”。

    因此,当您将 i 设置为指向 j(非 const int)时。 i 现在指向一个 const,因此不能通过指针 i 改变 j 的值,例如:

    int main()
    {
        const int *i;
        int j=2;
    
        i=&j;
    
        *i = 4;
    }
    

    无法编译,给出错误“assignment of read-only location ‘*i’”。所以指针限制了你对所指向的值的访问。但是指针本身还是可以改变的。

    C 作为它的语言,并没有真正提供太多保护,您通常可以丢弃 const 并为变量分配一个新值,例如:

    #include <stdio.h>
    
    void assign(int *a) {
      *a=5;
    }
    
    int main()
    {
        int const i=1;
        int j=2;
        assign((int *) &i);
        printf("i: %d\n",i);
    }
    

    但我不确定我是否会推荐它。虽然这在某些版本的 gcc 中有效,但这种行为可能在 C 标准中未定义。

    【讨论】:

    • 谢谢,您的第一句话说明了一切。但是有没有办法声明一个 const 变量,然后再定义它?没有办法做到这一点似乎很愚蠢。
    • @Sanfer 好吧,我不相信您可以完全按照自己的意愿行事。但是 C 中的 const 通常不会提供太多保护,您通常可以将 const 变量重新转换为非常量并对其进行修改。我已经用一个例子更新了上面的内容。
    • 很好,这是我需要的答案,谢谢。无论如何我都会这样做,因为 1) 样式,因为它很高兴首先声明所有变量,然后再定义/操作 2) 需要使用函数进行常量赋值可以防止意外 i=4;各种事情,这是我最初的打算。
    • 您的第二个示例导致未定义的行为,我不确定它应该说明什么。您似乎欺骗了 OP 认为这是可接受的代码
    • @Sanfer 在需要变量之前不要声明变量是一种很好的风格。也许你被早期的 C 代码在代码块开头声明变量误导了;这是因为历史上的编译器无法处理在任何地方声明的变量——这不是风格决定
    【解决方案2】:

    const int *i表示i指向的int是const,所以不能做*i = j。但是const int i 表示i 本身就是const,所以你必须像const int i = 2; 一样声明它,然后它仍然是const,并且不能被触摸。

    不同之处在于你改变了什么。如果你有一个 const 整数 - 它不能被更改,如果你有一个指向 const 整数的指针 - 并且指针不是 const,那么,那个指针可以被分配指向任何 int你愿意。

    回答您的问题:不,您不能定义 const int 然后重新定义它。这否定了const 的含义。

    【讨论】:

    • 不开玩笑。但我的问题是我是否可以“声明”然后定义,而不是定义然后定义。就像先分配一个类型,然后再分配一个值。
    • 将“you”拼成“u”会使您的答案更难阅读。
    • @Sanfer 范围内的所有变量声明也是定义,范围内没有“变量的前向声明”之类的东西。 (全局变量有这种东西)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多