【问题标题】:array declared with static keyword: what is static, the pointer or the whole array?用 static 关键字声明的数组:什么是静态的,指针还是整个数组?
【发布时间】:2011-06-08 18:21:00
【问题描述】:

简单但棘手的问题:

void f() {
    static int a[3] = {1, 2, 3};
    ...

这里的静态是什么?指向数组还是整个数组的指针?

谁能指出 C 标准中的定义?

谢谢!

【问题讨论】:

  • 你指的是什么指针?
  • 我指的是“a”指针(&a[0])。
  • &a[0] 在几乎所有上下文中扩展为 &a[0] 的表达式不是左值。它是地址而不是指针。只定义了一个标识符,这就是数组。由于没有其他标识符,所以没有什么可以应用static
  • 似乎即使这里没有 static 关键字,数组 a 也不会因不同的调用而改变。是标准还是编译器特定?

标签: c arrays pointers static


【解决方案1】:

来自 ISO C99 标准(第 6.2.1 节,“标识符范围”):

3 如果声明一个文件范围 对象或函数的标识符 包含存储类 说明符静态,标识符有 内部链接.22)

在您的示例中,a 标识符变为静态(即目标文件中的符号未导出)。

编辑:

对于非文件范围的静态声明(第 6.2.4 节,“对象的存储持续时间”)

3 标识符为的对象 用外部或内部声明 链接,或与存储类 说明符 static 具有静态存储 期间。它的生命周期是整个 程序的执行及其 存储的值只初始化一次, 在程序启动之前。

我认为这意味着在这种情况下数组本身变为静态,这是有道理的,因为否则标识符将包含无效内容。

【讨论】:

  • 感谢您的回答,但我编辑了帖子以将其包围在一个函数中。它实际上不是文件范围标识符...
  • 是的 - 在这种情况下,“对象”是数组本身,因此它是具有静态存储持续时间的数组。
【解决方案2】:

在代码中:

static int a[3] = {1, 2, 3};

a 的类型不是指针,而是 int 数组。但是,它会自动转换为指针,例如在 C 标准中:

除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串字面量,否则类型为 ''array of type'' 的表达式将转换为类型为 ' 的表达式'pointer to type'' 指向数组对象的初始元素,不是左值。

所以如果 a 是数组,那么 = { 1, 2, 3 } 是它的初始化,而不是某种单独的数组。我不知道它是否在某个地方准确指定,但从这个意义上说,它在整个标准中都使用。

编辑以消除一些读者的困惑:根据引用的标准,如果你写:

int arr[4] = { };
arr[0] = 1; //arr here has here type int*
size_t sz = sizeof(arr); //here it is not type int*, sizeof is exception

【讨论】:

  • 我错过了您回答问题的地方吗?
  • 问题是:这里的静态是什么?指向数组或整个数组的指针?这意味着静态 int a[3] -> a 只是静态 int *,实际数据(3 个整数)不是静态的,问题是关于这个,静态存储对提问者来说似乎很清楚。
  • 啊……你太着迷于“a”是否是指针,以至于你忘了回答这个问题。
【解决方案3】:

它适用于数组。您的代码中没有指针。数组不是指针。

#include <stdlib.h>
#include <stdio.h>

void f() {
    static int a[3] = {1, 2, 3};
        a[1]++;
        printf("%d\n", a[1]);
}

main()
{
        int i;
        for (i = 0; i < 5; i++)
        {
                f();
        }
}

输出

3
4
5
6
7

【讨论】:

  • -1: 错误,堆分配数组是指针,非堆分配数组(具有恒定大小)不是指针,而是自动转换为 - 所以它几乎是指针(在大多数情况下它是像一个一样使用)
  • @peenut:堆分配数组是什么意思?为什么它更像是一个指针而不是以其他方式分配的数组?
  • @peenut 嗯...指针不是数组。即使按照你所说的,这个数组也不是指针。我也不明白什么是“堆分配数组”。
  • @peenut 1) 你刚刚从“它们是一样的”变成了“它们在某些情况下是一样的”。 2)你还是错了。它们在表达上是不一样的。声明一个数组 char a[10] 和指针 char *p;你可以做 p = a;但不能做 a = p;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多