【问题标题】:Pointer and allocation outside function or static variable and allocation inside?函数外部的指针和分配还是内部的静态变量和分配?
【发布时间】:2011-08-16 13:38:42
【问题描述】:

不要担心我的帖子的长度,它很简单,我只是不知道如何把它更短:

我有两种非常类似于通过函数合并两个数组的方法。这里我调用函数combine_data()。这些数组称为data1data2。假设我的数组是这样的:

int num1 = 4;
int num2 = 6;

double data1[num1] = /* some values */
double data2[mum2] = /* some values */

解决方案 1

我可以使用我认为更优雅的解决方案,但我不确定这是否是好的做法并且会正常运行。 该解决方案依赖于一个旨在使数组持久化的静态变量。不知何故,感觉它可能会以某种方式在我的脸上爆炸。

// SOLUTION 1
double* combine_data(
    const int num1, const double* const data1,
    const int num2, const double* const data2
) {
    int i;
    int num = num1 + num2;
    double *combi;   // static because the data stored the should persist
    combi = (double*)malloc( num*sizeof(*combi) );
    /* some code */
    for(i=0; i<num1; ++i)   combi[i] = data[i];
    for(i=num1; i<num; ++i) combi[i] = data[i];

    return combi;
}

double *combi = combine_data(num1, data1, num2, data2);
/* some code */
free(combi);    // problem with free of a static variable in combine_data() ???

解决方案 2

或者我可以使用我更习惯的方法,将指针用于相同的功能:

// SOLUTION 2
void combine_data(
    const int num1, const double* const data1,
    const int num2, const double* const data2
    double* combi
) {
    /* some code */
    for(i=0; i<num1; ++i)   combi[i] = data[i];
    for(i=num1; i<num; ++i) combi[i] = data[i];
}

int num = num1 + num2;
double *combi = (double*)malloc( num*sizeof(combi) );
combine_data(num1, data1, num2, data2, combi);
/* some code */
free(combi);

解决方案 2 的问题是没有什么能阻止用户这样做:combine_data(num1, data1, num2, data2, data1),这会搞砸data1。解决方案 2 隐藏了分配,并且更易于使用,我发现它更优雅,但我不知道它会如何表现,尤其是在释放内存时。 哪种解决方案最好,为什么?

顺便说一句。两者有区别吗?:

const int* const name
const int const *name

编辑:其中一个确实是我在错误代码中看到并想知道的语法错误。也丢弃了static

【问题讨论】:

  • 为什么需要解决方案1中的静态指针?为什么不直接返回一个指向分配内存的指针并让调用者释放它呢?
  • double *combi = (double*)malloc( num*sizeof(combi) ); 的工作方式巧合,因为您有一个 64 位操作系统,并且指针的大小与 doubles 相同。 sizeof(combi)sizeof(double*) 相同;你真正需要的是sizeof(*combi)
  • @zbeak 是的,我知道。我只是打错了,但感谢您的更正!

标签: c pointers static


【解决方案1】:

为什么需要在解决方案 1 中将 combi 设为静态?指针不必持续存在,只有它所指向的内容。然后指针按值返回,因此不会发生内存泄漏。

您选择哪种解决方案完全取决于您对整个程序风格的假设。您必须决定该函数是应该分配并返回一个指向已分配内存的指针,还是接受一个指向已分配内存的指针。

两种解决方案都是正确的,在我看来同样好。在解决方案 2 中,您还可以检查输入和输出指针之间的相等性并返回错误代码。您甚至可以检查内存重叠,而不仅仅是指针相等。但是话又说回来,这一切都取决于您分配给程序的不同部分的职责。

【讨论】:

  • 嗯嗯嗯。我认为staic double *name 会使数据指向静态,double* static name 指针就像const 一样会使它们保持不变。
  • 不,函数中的static 指的是堆栈上的变量(局部变量),它指向的内存可能是任何东西,这就是为什么你不必(甚至不应该)在这种情况下使用它。另请注意,double const * name 中的 const 不会使内存保持不变,它只是不允许您通过此指针更改它。
【解决方案2】:

您的第二个解决方案更好。静态变量会杀了你,你会不会去多线程。

为了防止用户错误使用你的函数,你可以断言data1+num1data2+num2不重叠。

const int* const nameconst int* name 之间存在差异。后者意味着您无法更改name 指向的值,但您可以将name 本身分配给另一个指针,前者意味着您无法更改值和指针。

【讨论】:

  • 哇,真快。谢谢。我很肯定我永远不会使用多线程。
【解决方案3】:

const int* const name 和 const int 有区别吗 常量 *名称

是的,第二个是语法错误。

至于哪种解决方案更好...好吧,我认为您在解决方案 2 中担心的问题在解决方案 1 中不存在。您确实返回combi 在第一个解决方案中,因此用户可以保存它,然后再次将其传递给相同的函数,这也会搞砸事情。所以,我的投票赞成第二种解决方案。 (顺便说一下,你可以检查data1data2都不等于combi的函数)

【讨论】:

    【解决方案4】:

    第二种解决方案的优点是您可以传递不同存储类的数组。全局数组、堆栈分配 (VLA) 或堆分配。这为您提供了更大的灵活性,如果您的函数被大型项目的不同部分(想象一个库)使用,这可能会派上用场。

    double combi[num1+num2];
    combine_data(num1, data1, num2, data2, combi);
    /* some code */
    /*forget free(combi) it's not necessary anymore;
    

    编辑:此外,在调用者而不是被调用者中进行分配的优势也会影响解决方案的算法复杂性。如果我们想象您的 combine 函数在循环中被调用。使用第一个解决方案,您将拥有很多副本。

    第一种解决方案

     data1, data2, data3, data4
     comb1 = combine_data(len1, data1, len2, data2);
     comb2 = combine_data(len3, data3, len4, data4);
     comb3 = combine_data(len1+len2, comb1, len3+len4, comb2);
     /* ... */
     free(comb1); 
     free(comb2); 
     free(comb3); 
    

    第二个解决方案

     data1, data2, data3, data4
     comb = malloc(len1+len2+len3+len4);
     combine_data(len1, data1, len2, data2, comb);
     combine_data(len3, data3, len4, data2, comb+len1+len2);     /* This case can of course only be used because we know what combine does */
    
     /* ... */
     free(comb); 
    

    【讨论】:

    • 谢谢,我越来越倾向于解决方案#2。隐藏分配还有另一个缺点,就是忘记释放combi 比用户自己分配更容易。
    【解决方案5】:

    第一个解决方案中的static 没有用,您可以将其删除,并且功能将完全相同(除了它是线程安全的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-18
      • 2020-02-19
      • 2022-11-27
      • 2013-11-10
      • 2020-08-04
      相关资源
      最近更新 更多