【问题标题】:const pointer pointing to a const pointer指向 const 指针的 const 指针
【发布时间】:2012-08-31 14:13:55
【问题描述】:

我正在处理一些内存指针。我不想使用散列定义,请把讨论放在一边。我只是想知道为什么这不能编译:

#include <stdio.h>

static const unsigned long *const pMemAddrA = (unsigned long *) 0x00000200ul;
static const unsigned long *const pMemAddrB = pMemAddrA;

int main (void)
{
    printf("%x", (unsigned int) pMemAddrB);
    return 0;
}

编译器输出 gcc:

||=== TestConst, Debug ===|
 ...main.c|4|error: initializer element is not constant|
||=== Build finished: 1 errors, 0 warnings ===|

编辑:

阅读答案后,我很高兴知道如何解决这个问题。

但是我不明白为什么这是一个问题。据我所知,静态内存是在程序启动时分配的。我知道如果变量“活”在不同的文件中,并且编译器不能保证变量的分配顺序,就会出现问题。但是,如果两个变量都“存在”在同一个文件中 - 就像两个变量都存在于同一个函数中一样 - 我认为编译器可以确保按照文件中声明的变量的顺序分配内存,因此我不会不明白为什么声明和初始化指向另一个 const 指针的 const 指针是一个问题。如果有人能启发我,我会很高兴。

【问题讨论】:

  • 不工作是什么意思?如果它没有编译发布编译器错误,如果它显示意外输出发布输出。
  • 如果您要添加 what “不起作用”的意思,我们可以为您提供更好的帮助。
  • 很遗憾,声明一个变量 const 并不意味着它是一个常量,这可能会造成混淆。

标签: c pointers constants


【解决方案1】:

您的指针具有文件范围,因此初始化程序必须是常量表达式。 pMemAddrA 不是常量表达式,因此不能用于使用静态存储初始化变量。

它可用于在块范围内初始化变量,因此如果将声明移动到 main 内(并且至少使第二个非静态),它将编译:

#include <stdio.h>

int main (void)
{

    const unsigned long *const pMemAddrA = (unsigned long *) 0x00000200ul;
    const unsigned long *const pMemAddrB = pMemAddrA;

    printf("%x", (unsigned int) pMemAddrB);
    return 0;
}

如果必须在文件范围内声明两个指针,则无法防止重复初始化表达式,

static const unsigned long *const pMemAddrA = (unsigned long *) 0x00000200ul;
static const unsigned long *const pMemAddrB = (unsigned long *) 0x00000200ul;

#defineing。

【讨论】:

  • 我不使用静态得到相同的结果。
  • 声明在文件范围内,因此变量具有静态存储,无论您是否明确声明它们static
  • const 与此无关。在任何函数之外声明的东西都有文件范围(和静态存储持续时间)。此类变量只能使用“常量表达式”进行初始化。 const 变量不是常量表达式。常量表达式是整数文字,或使用文字的简单算术表达式 (3 + 5 * sizeof(int))。 const 变量只是一个您不能修改的变量(相反,您不能用来修改存储在那里的对象)。
  • @AudioDroid:从术语上讲,在 C 语言中,const 对象从不是一个常量。 C 和 C++ 在这方面差别很大。在 C 语言中,唯一的 constantsliteral valuesenum members。 C 中没有其他常量。因此,当语言需要 constant 时,这意味着它需要文字值或枚举成员。 const C 中的对象可以称为“常量变量”或其他方式,但它们不称为常量。后一个术语在 C 中保留用于不同的含义。
  • 简短回答:因为标准是这样说的。更长的答案:我不知道原因,但是由于具有静态存储的对象是在程序启动时初始化的,因此只允许常量表达式将初始化顺序留给实现,并且委员会喜欢将这些细节留给实现。如果允许非常量表达式,则初始化顺序将需要处理依赖关系,这将过多地束缚实现。
【解决方案2】:

你没有描述什么“不起作用”,但我猜你的意思是这条线

static const unsigned long *const pMemAddrB = pMemAddrA;

产生错误

error: initializer element is not constant

.

解决方案是这个初始化器确实不被视为常量。相反,为pMemAddrA 预留了一个内存区域,并将值0x00000200ul 写入其中。从那以后,它是一个位于内存某处的值,而不是一个常量表达式。

根据你想要做什么,你可以添加另一个指针间接,例如

static const unsigned long *const * const pMemAddrB = &pMemAddrA;

并使用*pMemAddrB 而不是pMemAddrB 访问它。

【讨论】:

  • 谢谢。我在某种程度上理解。这是否意味着除非为此使用哈希定义,否则我无法使其工作???你能详细说明一下吗?
  • @AudioDroid 您可以重复用于初始化pMemAddrA 的相同常量表达式,或者您可以在块范围内声明变量,并使用pMemAddrA 作为pMemAddrB 的初始化器。
  • @AudioDroid 我添加了一个解决方法,它可能对您计划做的事情有用,也可能没有。
猜你喜欢
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多