C语言 函数作用域之外的动态分配

ar7v8xwq  于 2023-01-20  发布在  其他
关注(0)|答案(2)|浏览(138)

如果我想创建一个作为全局变量工作的数组,如果我已经知道大小,我可以这样做:

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

int array[]={1,1,1,1};

int main()
{
    printf("%d", array[0]);
}

但是,这不适用于malloc

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

int* array=malloc(4*sizeof(int));

int main()
{
    printf("%d", array[0]);
}

将返回一个错误(error: initializer element is not constant),但是如果我尝试在函数的作用域内做同样的事情,就不会有问题。
我相信我一定遗漏了一些关于动态分配如何工作的东西。
这是怎么回事?如何在任何函数的作用域之外动态定义一个数组,并将其作为全局变量使用?

eoxn13cs

eoxn13cs1#

在C语言中,代码只能在函数体中执行。
第二个代码无效,因为您尝试在函数外部调用malloc
在C语言中使用全局变量被认为是一种不好的做法,所以如果不是100%必要的话,尽量避免。
如果您想使用全局指针:

int *array;

int main(void)
{
     array = malloc(100);
     /* .... */
}

有些编译器支持非标准扩展。例如,在GCC中,您可以使用属性在调用函数main之前执行代码

int* array;

void __attribute__((constructor)) aray_const(void)
{
    array = malloc(4 *sizeof(*array));
    if(array) memcpy(array, (int[]){1,2,3,4}, 4 * sizeof(*array));
}

int main()
{
    printf("%d %d %d %d\n", array[0], array[1], array[2], array[3]);
     /* .... */
}

https://godbolt.org/z/bz4YjzfK5

hof1towb

hof1towb2#

在C语言中,具有静态存储时间的对象可以由常量表达式初始化,并且在文件作用域中的第二个程序中声明的指针array与在文件作用域中声明的任何对象一样具有静态存储时间。
来自C标准(6.7.9初始化)

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

函数malloc也分配未初始化的内存。

printf("%d", array[0]);

在任何情况下都可以调用未定义的行为。
例如,您可以使用main中的赋值运算符按以下方式重写程序

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

int *array;

int main( void )
{
    size_t n = 4;
    array = malloc( n * sizeof( int ) );

    if ( array != NULL )
    {
        int value = 1;
        for ( size_t i = 0; i < n; i++ )
        {
            array[i] = value++;
        }

        for ( size_t i = 0; i < n; i++ )
        {   
            printf( "%d ", array[i] );
        }
        putchar( '\n' );
    }

    free( array );
}

或者你可以使用calloc函数代替malloc,在这种情况下,分配的内存将被零初始化。

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

int *array;

int main( void )
{
    size_t n = 4;
    array = calloc( n, sizeof( int ) );

    if ( array != NULL )
    {
        for ( size_t i = 0; i < n; i++ )
        {   
            printf( "%d ", array[i] );
        }
        putchar( '\n' );
    }

    free( array );
}

请注意,当不再需要分配的内存时,应始终释放它。

相关问题