【问题标题】:How to do one line assignment to malloc() arrays in C?如何在 C 中对 malloc() 数组进行一行赋值?
【发布时间】:2016-12-01 23:03:51
【问题描述】:

在 C 中,我可以像这样在堆栈上初始化一个数组:

SOME_DATA_TYPE* x = (SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5};

是否有类似的单行方法将值分配给堆上的malloc()-ed 数组?

SOME_DATA_TYPE* y = malloc(sizeof(SOME_DATA_TYPE)*5);  
// what comes here?  

还是我必须遍历数组并单独分配值?

【问题讨论】:

  • *y = (SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5}; 呢?
  • malloc 只想要一个大小。计算嵌套结构的大小并请求那么多字节。
  • @DaBler 右边被解释为栈内存。我知道这一点是因为 free(y) 然后我的应用程序崩溃了。
  • 如果你的意思是x:那不是数组!如果它是一个数组,它就不会被称为“指针”。
  • 那么你可以使用memcpy(y, (SOME_DATA_TYPE[5]){v1, v2, v3, v4, v5}, sizeof(SOME_DATA_TYPE)*5);...

标签: c arrays heap-memory


【解决方案1】:

关于“初始化”malloc() 的结果的第一个问题是分配可能会失败。这里y初始化为某个指针值。引用的数据仍然不确定。

#define  element_count  5
SOME_DATA_TYPE *y = malloc(sizeof *y * element_count);
if (y == NULL) Handle_OutOfMemory();

使用C11,代码可以使用复合文字来设置y指向的数据,而不是初始化

memcpy(y, (SOME_DATA_TYPE[element_count]) {v1, v2, v3, v4, v5}, sizeof *y * element_count);

在不检查分配的情况下使用 direct 单行代码不会是健壮的编程。

// one-liner, but not robust code
SOME_DATA_TYPE *y = memcpy(malloc(sizeof *y * element_count), 
    (SOME_DATA_TYPE[element_count]) {v1, v2, v3, v4, v5}, sizeof *y * element_count);

注意代码使用sizeof *pointer_variable * element_count 而不是sizeof (pointer_variable_dereferenced_type) * element_count,因为它更易于编码、不易出错、更易于查看和维护。两种方法都行。

【讨论】:

  • 这段代码不正确 - 如果数组大小为零,它可能会调用 Handle_OutOfMemory()。
  • @TLW 好眼力。是的,对于malloc() 的结果的一般测试,代码应该使用if (y == NULL && element_count > 0) Handle_OutOfMemory(); 当然,由于OP 想要“初始化一个数组”,数组大小为0 除了malloc() 之外还有其他问题,例如SOME_DATA_TYPE[element_count]。如果element_count 是一个变量,我会编写element_count > 0 测试。
  • 可以通过滥用逗号运算符来检查单行中的 malloc 结果......当然会让我们脱离“可维护/可读”的界限跨度>
  • @MM 同意。然而,无论如何,听起来 OP 主要是为了测试目的而这样做,这么多 OOM 不是问题吗?
【解决方案2】:

你可以像这样定义一个函数:

#include <stdarg.h>
#include <stdlib.h>

int * intMallocInit (int length, ...) {
   // Initialize Variable Arguments
   va_list args;
   va_start (args, length); 

    // Allocate Memory
    int * arr = malloc (sizeof(int) * length);
    if (arr == NULL) return NULL;

    // Initialize Array
    for (int i = 0; i < length; i++) {
        arr[i] = va_arg(args, int);
    }

    // Clean Up and Return
    va_end(args)
    return arr;
}

我们可以这样称呼它:

int len = 3;
int * myArray = intMallocInit (len, 4, 5, 2);
if (myArray == NULL) return 0; 

for (int i = 0; i < len; i++) {
    printf("%d,", myArray [i]);
}

输出: 4,5,2,

注意:我们也可以定义floatMallocInit()等

你也可以使用 void 指针,或者 enum& 开关,但我不会去那里。

一般功能的未经测试的尝试 我确信围绕 fhe 开关有一个聪明的工作,但这是我能想到的。

#include <stdarg.h>
#include <stdlib.h>
enum {INT, FLOAT /* etc...*/}

 int getSize(int type) {
     int typeSize = 0;
     switch (type) {
        case INT: 
             typeSize = sizeof (int);
             break;
        case FLOAT:
             typeSize = sizeof (float);
             break;
        // Etc...
        default:
             return -1;
    }
    return typeSize;
 }


void * mallocInit (int type, int length, ...) {
   // Initialize Variable Arguments
   va_list args;
   va_start (args, length); 

    // Get Size of type
    int typeSize = getSize(type);
    if (typeSize == -1) return NULL;

    // Allocate Memory
    void * arr = malloc (typeSize * length);
    if (arr == NULL) return NULL;

    // Initialize Array, Maybe va_copy can be used? No good reference
    for (int i = 0; i < length; i++) {
         switch(type) {
            case INT:
             arr[i] = va_args(args, int);
             break;
            // Etc..
        }
    }

    // Clean Up and Return
    va_end(args)
    return arr;
}

调用

float myArray = mallocInit (FLOAT, 3, 1, 5, 7);

【讨论】:

  • 这是一个非常好的解决方案!
  • 对不起,类型是什么意思?到目前为止,我从未使用过...,您能否简要解释一下它是如何工作的?
  • 我对其进行了修改以使其更清晰。 ... 表示可变数量的参数。 (你必须包括 )检查 tutorialpoint 它有一个很好的参考。
  • arr[i] = args[i];?!?!那甚至不编译。充其量,这是非标准的。您需要使用arr[i] = va_arg(args, int);
  • for (int i = 0; i &lt; length; i++;) 无法编译,它的va_arg,不是va_args,它应该是va_end (args); 而不是va_end。 (否则,很好的功能)
【解决方案3】:

在不偏离自然 C 内存管理理念的情况下,一种方法是使用类似memdup 的函数。由于它不是标准的,您可能必须自己实现它

SOME_DATA_TYPE *y = memdup(
  (SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5},
  5 * sizeof(SOME_DATA_TYPE)); 

【讨论】:

  • 嗯,很高兴知道。 LSNED。也许可以使用#define MEMDUP(x) (memdup((x), sizeof (x))) 来简单地调用MEMDUP((SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5})
猜你喜欢
  • 2016-11-16
  • 1970-01-01
  • 2012-05-09
  • 2015-11-22
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多