【问题标题】:Is accessing the static value using a global pointer variable is valid?使用全局指针变量访问静态值是否有效?
【发布时间】:2019-06-07 10:06:16
【问题描述】:

我可以使用全局指针访问静态变量吗?

//In main.c file
static int c = 20; #Static vairble 
int *ptr = &c; #Global pointer variable
int main(){
  fun();
  printf("%d\n", c);
}

//In sub.c file
extern int *ptr;
void fun(){
  ++*ptr;
}

当我尝试在另一个文件中使用 extern 关键字访问 *ptr 全局变量时,我能够访问静态变量 c,甚至对 *ptr 所做的更改也反映在 main.c 文件中的 c 上

  1. 为什么“ptr”即使在被静态变量地址赋值后也不会丢失其全局属性?

  2. 是静态和全局存储在两个不同的内存段中,还是它们都共享同一个内存数据段?

  3. 全局变量可以存储非常量值吗?

【问题讨论】:

  • ++*ptr 实际上是做什么的?发生了什么间接性?

标签: c static global-variables


【解决方案1】:

static 不是将对象放入无法从其他翻译单元更改/寻址的内存部分。它只是定义对象具有内部链接,因此不能通过此(内部)名称被其他翻译单元抓取。

但是,如果您以某种方式在另一个翻译单元中获得了声明为static 的对象的内存地址,则您可以合法地访问该对象。

所以你的构造是有效的。

当其他翻译单元复制您的ptr(可能在此之前指向c)时,您可能只是遵守“静态初始化顺序惨败”。 例如,考虑当另一个翻译单元包含在文件范围内时可能会发生什么......

extern int *ptr;
int *myPtr = ptr;
...
int main() {
   int x = *myPtr;
}

【讨论】:

    【解决方案2】:

    你混淆了指针变量的链接和它指向的链接。

    无论它指向什么,指针的链接不会改变。

    这里ptr链接global(又名external),c 的链接是static(又名内部)。两者都不改变彼此的联系。

    static 表示c在另一个(例如).c 文件中可见(即可用于直接链接)。也就是说,另一个.c不会这样做:

    int *ptr2 = &c;
    

    但是,它可以做到:

    int **ptr3 = &ptr;
    

    你可以反过来:

    int c = 20;
    static int ptr = &c;
    

    这是一个static/内部链接ptr,指向一个全局/外部链接c

    一个程序有几个内存区域:.text 用于代码。 .data 用于已初始化 变量(例如c),.bss 用于未初始化 区域。

    由于您初始化ptrc,它们都以.data 结束

    如果你这样做了:

    #include <stdio.h>
    
    static int c = 20; // Static vairble
    int *ptr;
    
    int main(){
        ptr = &c;
        return 0;
    }
    

    然后,c初始化并进入.data,但ptr没有初始化而是分配并进入.bss

    所有变量[全局或非全局]都可以有非常量值。通过初始化或赋值。

    以上所有变量都有全局/文件范围

    这是另一种范围:

    #include <stdio.h>
    
    static int c = 20; // Static vairble
    
    int main(){
        int *ptr = &c;
        return 0;
    }
    

    这里,ptr 具有 function 范围。它被放置在main 的堆栈帧上。它没有链接可言(即它永远不会出现在可执行文件的符号表中)。

    【讨论】:

    • 范围不是问题。 cptr 都具有 file 范围(这是 C 标准使用的术语,不是全局或静态的)。问题是链接,这是可以使不同范围内的相同标识符引用同一对象的过程。 c 具有内部链接。 ptr 具有外部链接。
    【解决方案3】:

    为什么“ptr”即使在分配后也不会丢失其全局属性 通过静态变量地址?

    变量不能“松开”它的作用域或存储类,static 链接类说明符决定符号的可见性,而不是它的存储位置或存储方式。它防止通过该符号引用数据,它不会防止指针引用到同一位置。 C 是一种系统级语言 - 因此它不会阻止您做几乎可以在架构级别完成的任何事情。

    静态和全局是否存储在两个不同的内存段中 还是它们共享相同的内存数据段?

    没有。在这种情况下,static 关键字用于指定静态或或内部链接,它也用作(用于函数局部变量)作为存储类说明符,但是函数外的所有变量都具有静态存储类,无论内部或外部链接如何。

    也就是说,初始化的静态存储数据放置在与零或未初始化数据不同的链接器部分。这是为了便于运行时启动初始化。

    全局变量可以存储非常量值吗?

    也许这值得一个单独的问题来解释为什么您可能会不这么认为 - 它似乎与您的其他问题无关,而且是一个左字段。在您自己的示例中,ptr 正在存储 &amp;c,但可以在运行时对其进行修改以指向其他位置。

    【讨论】:

      【解决方案4】:

      为什么“ptr”即使在分配后也不会丢失其全局属性 通过静态变量地址?

      ptr 保持全局,无论它指向何处,因为它被声明为全局。

      静态和全局是否存储在两个不同的内存段中 还是它们共享相同的内存数据段?

      通常它们位于同一个数据段中。

      https://www.geeksforgeeks.org/memory-layout-of-c-program/

      全局变量可以存储非常量值吗?

      是的,就像任何其他变量一样,因此名称为“变量”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-02
        • 1970-01-01
        • 2022-11-07
        • 1970-01-01
        • 2014-01-27
        • 2012-10-04
        • 1970-01-01
        • 2014-04-19
        相关资源
        最近更新 更多