具有静态指针的动态内存分配 [英] Dynamic Memory Allocation with Static Pointer

查看:91
本文介绍了具有静态指针的动态内存分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以向我解释为什么下面的代码按其工作方式工作.在这里,我已将outd初始化为文件code2.c中的静态指针.然后,我使用malloc为它动态分配内存.从主函数在一个单独的文件code1.c中一次又一次地调用它,看起来整个数组的行为都是静态的,因为它保留了从一个函数调用到另一个函数调用的所有值,即使为数组分配了内存动态地.我原本期望的是细分错误.

Can somebody please explain to me why the following piece of code works the way it works. Here I have initialized outd as a static pointer in the file code2.c. Then I allocate memory to it dynamically with malloc. Calling it again and again from the main function in a separate file code1.c, it looks the entire array behaves in a static way as it preserves all the values from one function call to another function call even though the memory for the array was allocated dynamically. I was expecting something like segmentation fault.

code2.c

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

static double *outd;

void init0(int len)
{
    int i;
    outd=malloc(sizeof(double)*len);
    for (i=0; i<len; i++)
    {
       outd[i]=0.0;
    }
}

void showarray(int len, int iterno)
{
    int i;
    printf("iteration %d, array is \n",iterno);
    for (i=0; i<len; i++)
    {
        outd[i]=outd[i]+iterno;
        printf("%.2f ",outd[i]);
    }
    printf("\n");
}

void deletearray()
{
    free(outd);
}

code1.c

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

void init0(int len);
void showarray(int len, int iterno);
void deletearray();

int main(int argc,char* argv[])
{
    int i, len;
    len=5;

    init0(len);

    for (i=0; i<7; i++)
    {
        showarray(len,i);
    }

    deletearray();
}

编译

$(CC) -c -O2 code1.c 
$(CC) -c -O2 code2.c 
$(CC) -o bb5 code1.o code2.o -lm

运行

localhost:testfft avinash$ ./bb5
iteration 0, array is 
0.00 0.00 0.00 0.00 0.00 
iteration 1, array is 
1.00 1.00 1.00 1.00 1.00 
iteration 2, array is 
3.00 3.00 3.00 3.00 3.00 
iteration 3, array is 
6.00 6.00 6.00 6.00 6.00 
iteration 4, array is 
10.00 10.00 10.00 10.00 10.00 
iteration 5, array is 
15.00 15.00 15.00 15.00 15.00 
iteration 6, array is 
21.00 21.00 21.00 21.00 21.00 

推荐答案

Yunnosch的答案很好地解释了示例不同声明的作用,但是我想从语言规范中添加一些背景知识,因为我认为这有助于理解很多东西.

Yunnosch's answer explains the effects of different declarations by example quite well, but I want to add some background from the language specification because I think this helps understanding a lot.

  • C中的标识符具有作用域.范围确定此标识符引用与其关联的对象的区域.在C语言中,标识符的范围是一对大括号({ ... }).

  • Identifiers in C have scopes. The scope determines the area in which this identifier refers to the object associated with it. In C, the scope of an identifier is the enclosing pair of curly braces ({ ... }).

if (1) {
    int i = 2;
    // i refers to an object holding the value 2 here
}
// i doesn't refer to any object

大括号外的标识符具有文件作用域,它们引用整个源文件中的对象.

Identifiers outside any braces have file scope, they refer to the object in the whole source file.

C语言中的对象可以具有不同的存储持续时间.存储持续时间确定对象可以存活并可以访问的时间.您应该了解以下内容:

Objects in C can have different storage durations. The storage duration determines for how long an object is alive and can be accessed. You should know about the following:

  • 自动:只要执行在其作用域之内,该对象就存在.这是文件范围中所有变量的默认设置.
  • 静态:该对象在程序的整个执行时间内都有效.这是文件范围中声明的默认设置.
  • 动态:该对象由分配(malloc()和朋友)创建,并且一直存在直到被手动释放(free()).
  • automatic: The object lives as long as the execution is inside of its scope. This is the default for any variable not in the file scope.
  • static: The object lives for the whole execution time of the program. This is the default for a declaration in file scope.
  • dynamic: The object is created by allocation (malloc() and friends) and lives until it is manually deallocated (free()).

最后,标识符可以具有不同的链接.这确定了不同翻译单元之间的可见性.带有外部链接的标识符在其自身的翻译单元之外可见,而具有内部链接的标识符则不可见.

Finally, Identifiers can have different linkage. This determines the visibility between different translation units. An identifier with external linkage is visible outside of its own translation unit, one with internal linkage is not.

文件作用域标识符的默认链接为 external .

The default linkage for file scoped identifiers is external.

在此理论背景下,让我们看看static的含义. static存储类,并将存储持续时间设置为静态,而将链接设置为内部.

With this theoretical background, let's see what static means. static is a storage class and sets the storage duration to static and the linkage to internal.

example1.c:

example1.c:

static int i;
// static storage duration, internal linkage

int foobar(void) {
    static int j = 5;
    // static storage duration, internal linkage
    return ++j;
    // returns one more at each call, starting from 6
}

vs example2.c:

vs example2.c:

int i;
// static storage duration, external linkage

int foobar(void) {
    int j = 5;
    // automatic storage duration, internal linkage
    return ++j;
    // always returns 6, because with automatic storage duration,
    // j refers to a NEW object every time the function is entered
}


关于问题中的代码:指针具有 static 的存储持续时间,因此它对于整个程序都是有效的.只要您不使用malloc(),它的生命就一直存在(请参见上文:动态存储持续时间),因此使用此代码非常合适.


Concerning your code in the question: The pointer has static storage duration, so it lives for the whole program. Whatever you malloc() lives as long as you don't free() it (see above: dynamic storage duration), so you're perfectly fine with this code.

这篇关于具有静态指针的动态内存分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆