【问题标题】:Using malloc with static pointers将 malloc 与静态指针一起使用
【发布时间】:2015-04-01 10:18:08
【问题描述】:

我知道声明一个ststic变量并以这种方式初始化它static int *st_ptr = malloc(sizeof(int));会产生一个编译错误消息(类型初始化元素不是常量),并通过这种方式使用单独的语句来解决这个问题static int *st_ptr; st_ptr = malloc(5*sizeof(int));


在这种情况下我需要了解初始化运算符和赋值运算符之间的区别?以及为什么这种方式解决了问题?

【问题讨论】:

  • 两者都非常危险,除了学习之外,应该避免。
  • 您的第二个示例将编译,但它仍然是错误的:它会在每次调用函数时分配新的存储,泄漏旧的。将变量初始化为 NULL,并在调用 malloc 之前检查是否为 NULL,以便只调用一次。
  • @DavidHaim:你到底在说什么?
  • @DavidHaim:无论如何,您都应该在此处添加您所指的内容。因为 OP 甚至不包含真正的 sn-p,而且您的评论听起来确实像“两种情况都应该避免”(所以听起来您建议完全避免使用 malloc)因为他只是输入了一些代码我没想到,他可能已经忘记了什么。因此,要获得您所警告的内容并没有很好地说明;)
  • @Wyzard 你向我添加了新概念,谢谢

标签: c pointers static initialization malloc


【解决方案1】:

首先,让我们简要介绍一下initialization 与assignment。

  • 初始化:

这用于指定对象的初始值。通常,这意味着只有在定义变量时才会进行初始化。用于初始化对象的 value 称为 initializer。来自C11,章节6.7.9,

初始化器指定存储在对象中的初始值。

  • 作业:

赋值是在任何(有效的)给定执行时间点分配(或设置)变量的值。引用标准,章节6.5.16,

赋值运算符将值存储在左操作数指定的对象中。

如果是简单赋值(= 运算符),

在简单赋值(=)中,右操作数的值被转换为 赋值表达式并替换左边指定的对象中存储的值 操作数。


也就是说,我认为您的查询与 static 对象的初始化有关。

对于第一种情况,

static int *st_ptr = malloc(sizeof(int)); 

引自C11标准文档,章节§6.7.9,初始化,第4段,

具有静态或线程存储持续时间的对象的初始化程序中的所有表达式 应该是常量表达式或字符串文字。

关于常量表达式,来自同一文档的第 6.6 章,(强调我的)

常量表达式不得包含赋值、递增、递减、函数调用、 或逗号运算符,除非它们包含在不属于 评估。

很明显,malloc(sizeof(int)); 不是一个常量表达式,所以我们不能用它来初始化static 对象。

对于第二种情况,

static int *st_ptr;
st_ptr = malloc(5*sizeof(int));

您没有初始化static 对象。你让它未初始化。下一条指令,您将 分配 malloc() 的返回值给它。所以你的编译器不会产生任何抱怨。

【讨论】:

  • 我开始觉得你是我的竞争对手......无论如何为内容+1(如果你愿意,你可以标记这个^^)
  • @Zaibis 别担心,下一次,也许我会成为发布此评论的人。 :-)
【解决方案2】:

当一个变量在函数内声明为静态时,它是在“数据段”或“bss 段”中创建的,取决于它是否被初始化。
这个变量是在二进制文件中创建的,并且必须有一个常量值 - 记住 - 函数内部的静态变量是在程序运行时甚至在 main() 开始之前创建的,它不能用任何函数初始化,因为程序还没有“运行”(没有种类评估或函数调用)
所以初始化器必须是常量或不首先初始化。

static int *st_ptr = malloc(sizeof(int));

在这里,您将 st_ptr 的创建与 malloc 绑定,但由于 malloc 是一个需要运行的函数,并且必须在任何其他函数运行之前创建 st_ptr - 这会创建不可能的状态

static int *st_ptr;
 st_ptr = malloc(5*sizeof(int));

在这里,st_ptr 被创建并且未初始化,它的创建不绑定到任何函数。 每次函数运行时 - malloc 都会发生。因此不依赖于 malloc 的激活和创建 st_ptr。

但正如我在评论中所说 - 这是非常危险的做法。您在同一个变量上分配越来越多的内存。避免它的唯一方法是在每个函数的末尾free(st_ptr)。这就是说 - 你不需要它首先是静态的

【讨论】:

    【解决方案3】:

    粗略地说,C 中的初始化是编译器将二进制数据输出到可执行文件时;赋值是实际可执行代码执行的操作。

    所以,static int i = 5 使编译器将数据字5 输出到可执行文件的数据部分;而int i = func()让编译器生成几条CPU指令,call调用子程序,mov存储结果。

    因此,表达式 static int i = func() 要求 1) 比 main() 更早计算(因为这是一个初始化),2) 要执行的一段用户代码(这可能只在新的上下文中才有意义)程序实例)。可以通过创建一些在main() 之前执行的隐藏初始化子程序来解决这个问题。实际上,C++ 就是这样做的。但是C没有这个特性,所以静态变量只能用常量初始化。

    【讨论】:

    • int i = func() 可以,而 OP 说明的情况无效。所以 -1 与 OP 的问题没有真正的关系。 (如果我错了,请纠正我)
    • @Zaibis 从上面所说的,很明显(我希望)为什么static int i = func() 是无效的 - 它需要执行代码,而它应该在其他任何事情之前计算(因为初始化需要)。 C++ 通过使用隐藏的初始化子程序解决了这个问题,而纯 C 没有这样的功能 - 用户代码不能在 main() 之前执行。这就是C 只允许常量作为初始化的原因。
    • 啊,好的。无论如何,你应该改写它。
    猜你喜欢
    • 2013-05-18
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 2022-11-11
    相关资源
    最近更新 更多