【问题标题】:Character String Pointer vs. Array字符串指针与数组
【发布时间】:2012-12-12 09:23:03
【问题描述】:

我想知道像这样定义的字符串之间是否有任何区别(在语法和性能方面)

char str[200];

char *str;
str = calloc(200, sizeof(char));

在使用方面有区别吗? (比如,一个不兼容strncpy什么的)更重要的是,在性能方面有区别吗?

编辑:我知道由char *calloc 定义的数组可以增长和缩小,但是出于任何原因我应该选择堆内存而不是堆栈内存还是相反?这才是我真正想问的。

【问题讨论】:

标签: c arrays string pointers char


【解决方案1】:

char str[200] 分配在堆栈内存中,而calloc() 分配在堆内存中。

根据 calloc() 的性质,它会将 0 分配给它分配的所有字节。

堆栈和堆比较请参考以下内容

Which is faster: Stack allocation or Heap allocation

http://www.linuxquestions.org/questions/programming-9/stack-faster-than-heap-685004/

What and where are the stack and heap?

【讨论】:

  • 我明白...但是堆内存总是会变慢吗?
  • @Kitchi:是的,堆内存会变慢,并且在使用手动动态内存管理时更容易出错。
  • @AlokSave,我同意。堆栈比堆内存访问快。
【解决方案2】:

在使用方面有区别吗? (例如,一个不是 兼容 strncpy 什么的)

我很惊讶没有人提到第一个 str 即数组名称的计算结果是一个 常量指针 并且 不能重新分配,而第二个是一个 指针变量,可以重新赋值。

所以

char str[SIZE];
char * b = malloc(SIZE);

str = b; // This is a compilation error

b = str; // where as this is perfectly legal (ignoring the fact 
         // that we are losing malloced memory without actually freeing it)

【讨论】:

  • 还有很多其他的区别:e.g. sizeof(str) 返回SIZE * sizeof(char);而sizeof(b) 返回sizeof(char *)&str 的类型为 char (*)[SIZE],而 &b 的类型为 char **
【解决方案3】:

首先在栈上分配内存,其次分配动态内存。堆栈内存是自动管理的,而动态内存需要手动管理。

当你有选择的时候,你应该总是选择第一个:

  • 你不必记住释放任何东西
  • 动态内存在性能方面的开销很小。

在使用方面有区别吗? (例如,一个与 strncpy 或其他东西不兼容)

就函数的使用而言,两者都是相似的,从简单的意义上来说,当使用函数时,两者都是指向连续内存块的指针。当您将数组传递给函数时,它会衰减为指向第一个元素的指针。
区别在于它们的存储位置以及它们是自动管理还是手动管理。

【讨论】:

  • 你应该总是喜欢第一个 - 我可以不同意吗?如果堆栈大小较小而变量较大或此类变量很多,则堆可能是更好的选择。
  • @mouviciel:当然,这是课程的马。所以很明显,我的评论说你什么时候可以使用。无论如何,我会为了清楚起见进行编辑。
  • 投反对票的理由是什么?如果是技术推理,请赐教。
  • 我没有投反对票,但在数组名称评估为常量指针并且不能重新分配指针变量可以重新分配的情况方面,用法可能有所不同 - 只要我们不泄漏内存。跨度>
  • @mouviciel - If stack size is small and variable is big... - 你能解释一下吗?从我读过的其他线程中,我了解到堆栈分配和解除分配总是更快,因为它不必跟踪连续的内存段。
【解决方案4】:

char str[200];

  • 是一个简单的声明(不是动态分配),
  • 默认值是垃圾,
  • 快速访问(在堆栈段中),
  • Scope is local(在 {} 中)。

字符 *str;
str = calloc(200, sizeof(char));

  • 所有元素的值都为零(因为calloc()),
  • 访问缓慢(使用堆段),
  • 动态分配使用,即有效使用内存。
  • 需要明确解除分配,
  • 内存Scope is global,可以返回例如return str 来自函数`。

【讨论】:

  • 我可能没有投反对票,但静态声明默认为零(不是垃圾)。分配的堆内存垃圾。而且您本可以多花一分钟时间将您的答案格式化为更易读的内容。
  • 静态声明意味着编译时间不是动态的..我知道有关键工作'静态'
  • static declaration 表示不是static variable
  • 对于 c 程序员来说,静态声明意味着a variable declared in static storage。这只是行话,这就是你被误解的原因。
  • 堆分配是垃圾,但如果你使用calloc分配它只会是0(零)。
【解决方案5】:

您应该尽可能使用堆栈分配:对于程序员来说更容易维护,而且对性能的要求也较低。

很多情况下数组堆栈分配是不可能的。

  • 如果您在编译时不知道数组的大小。但是最近的 C 标准对此提供了一些支持,
  • 您有一个大小不相同的数组,
  • 您需要分配的内存在您的函数返回后仍然存在。

还要注意char str[200]“知道”它的大小(即sizeof(str) == 200*sizeof(char)),而您必须在辅助变量中记住分配数组的大小才能使用它(sizeof(str) == sizeof(char*),通常为 4 或 8 )。

【讨论】:

    【解决方案6】:

    字符数组内存分配在栈上。一旦控制移出包含数组的函数,内存就会被释放,现在无法访问数组。

    虽然 calloc 函数在堆上分配内存并一直保持到程序正在执行或内存被手动释放

    【讨论】:

      【解决方案7】:

      一旦你创建了字符串,在使用上就没有区别了。

      char str[100] 在堆栈上分配字符串,而另一种方法使用堆。堆栈上的分配总是比堆上更快(请参阅此讨论:Which is faster: Stack allocation or Heap allocation

      此外,calloc() 将数组的所有元素设置为 0/NULL,进一步降低了性能。如果您使用 C++ 编程并需要使用堆,请始终编写:

      char *str = new char[200];

      这有额外的好处,例如如果堆已满,则引发错误。

      【讨论】:

      • 在使用方面仍然存在一个差异,即不能重新分配数组名称,而指针变量可以是。
      • 我在函数参数方面考虑得更多,但是是的,感谢您指出这一点。
      猜你喜欢
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2013-06-07
      • 1970-01-01
      • 2011-01-11
      相关资源
      最近更新 更多