c中声明和定义的内存分配

时间:2018-09-26 07:54:41

标签: c allocation

我尝试了以下两段代码:

void swap_woPointer()
{ 
    int a=5;
    static int b=5;
    printf("value of a : %d , value of b: %d \n", a, b);
    printf("address of a: %p , address of b %p \n", &a, &b);

    a++;
    b++;
}



void main(int argc, char *argv[]) 
{
    int ii;
    for (ii=0; ii<10; ii++){
        swap_woPointer();
    }

}

void swap_woPointer()
{ 
    int a;
    static int b;
    printf("value of a : %d , value of b: %d \n", a, b);
    printf("address of a: %p , address of b %p \n", &a, &b);

    a++;
    b++;
}



void main(int argc, char *argv[]) 
{
    int ii;
    for (ii=0; ii<10; ii++){
        swap_woPointer();
    }

}

这两段代码之间的唯一区别是,一旦我只声明了变量a和b

int a;
static int b;

在另一种情况下,我定义了它们

int a=5;
static int b=5;

在两种情况下,我获得的输出是不同的。在仅声明变量的情况下,获得

value of a : 0 , value of b: 0 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 1 , value of b: 1 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 2 , value of b: 2 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 3 , value of b: 3 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 4 , value of b: 4 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 5 , value of b: 5 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 6 , value of b: 6 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 7 , value of b: 7 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 8 , value of b: 8 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 9 , value of b: 9 
address of a: 0xffffcbbc , address of b 0x100407000

如果我立即定义变量,我将获得

value of a : 5 , value of b: 5 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 6 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 7 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 8 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 9 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 10 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 11 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 12 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 13 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 14 
address of a: 0xffffcbbc , address of b 0x100402010

我不明白差异的来源。它某种程度上必须与内存分配有关。我认为在两种情况下我都应该获得相同的结果,例如声明为非静态的变量a应该在每次调用该函数时分配一次。显然,只有在直接定义变量而不仅仅是声明变量的情况下。

2 个答案:

答案 0 :(得分:3)

int a;为您提供了一个不确定值的变量。如here所述,如果您打印不确定的值,将会发生未指定的行为。绝对不能保证值0。您可以获得任何值,并且该值有时可能会有所不同,即使尚未重新编译程序也是如此。

通常,某些编译器在设置为调试生成时会将所有内存归零,即使未初始化也是如此。这可以解释为什么该值似乎是确定性的。当您以后切换到发布版本时,您可能会得到垃圾。我们很高兴知道这种现象,因为这是为什么代码会在发布版本中中断的一个常见解释:您忘记了初始化初始化并切换到发布版本的某些变量,从而暴露了该错误。

在两种情况下,a都分配在本地堆栈上。

对于b,有一条规则规定所有未由程序员初始化的静态存储持续时间变量都必须初始化为零。因此,在static int b;的情况下,您得到的值0实际上得到保证,与int a;的情况不同。

此外,编译器将静态存储持续时间变量分配给不同的段,具体取决于它们是否初始化为0或其他某个值。初始化为零的变量以.bss结尾,而初始化为值的变量以.data结尾。这就是为什么您在两种不同的情况下为b获得不同的地址的原因:static int b;.bss中被分配,static int b=5;.data中被分配。


给书呆子读者的注意事项:

  • 该代码实际上不包含未定义的行为,如链接的文章中所述。取局部变量的地址。假设主流系统没有任何补码表示补码整数。

  • C标准不保证在哪里分配变量。 .stack.bss.data是行业实际的标准名称,但不受C语言标准强制。

答案 1 :(得分:0)

未初始化的局部非静态变量(也称为“自动”变量)实际上是未初始化的。它们将具有不确定(看似随机)的值。不要使用未初始化的变量。

另一方面,局部 static 变量 将自动初始化为零。


对于未初始化的currentlyReadingIssue变量会发生什么,它恰好是变量所在的内存中任何值。

如果您使用之间的局部(和初始化)变量调用其他函数,则可能会得到其他(且不可预测)结果。