【问题标题】:calculating array sizes in C在 C 中计算数组大小
【发布时间】:2012-01-05 22:24:56
【问题描述】:

我的 C 代码中有一个用于计算数组大小的宏:

#define sizearray(a)  (sizeof(a) / sizeof((a)[0]))

当我测试它时,它适用于静态定义的数组,但不适用于动态定义的数组(见下文)。不知道我明白为什么会这样。有什么方法可以计算分配在堆上的数组的大小吗?

/* test sizearray macro */
void testSIZEARRAY(void)
{
    /* test case for statically defined array */
    int a[5] = {0,0,0,0,0};

    assert(sizearray(a) == 5);

    /* test case for dynamically defined array */
    int *b;

    b = calloc(5, sizeof(int));

    assert(sizearray(b) == 5);

    free(b);
}

【问题讨论】:

标签: c arrays


【解决方案1】:

答案是否定的,没有获取动态分配数组大小的标准方法。
出于所有实际目的,您必须自己跟踪它。

但是,有一些特定于编译器的方法可以做到这一点:

Windows (Visual Studio): _msize()

GCC: msize() 在 GCC 文档中找不到它...

【讨论】:

  • 你可能会说,一般来说没有办法计算动态分配的数组的大小,你只需要跟踪它。
  • @dbeer 是的,我会补充的。谢谢。
  • 返回分配的大小还是被询问的大小?
  • @AProgrammer 好问题。我不确定,文档也不清楚。
  • @AProgrammer 看起来它确实返回了被询问的大小。我刚刚用163 对其进行了测试,这些尺寸肯定会被填充 - 它确实返回163
【解决方案2】:
int *b;
...
assert(sizearray(b) == 5);

指针不是数组。 b 被声明为指向 int 的指针

这里

sizeof b == sizeof (int *)

应用于指针类型对象的sizeof运算符与指针类型的大小相同,不等于分配数组的大小。

要知道分配的数组对象的大小,您必须检查分配的内容。在您的示例中,您分配了一个 5 int 的对象,因此您的数组大小为:

 5 * sizeof (int)

(或等效的,5 * sizeof *b

【讨论】:

    【解决方案3】:

    如果你只有一个指向它的第一个元素的指针,就没有办法计算数组的大小(就像你在上面的例子中使用 int *b 所做的那样)。您需要单独存储数组大小并将其与指针一起使用,或者以某种方式标记数组的末尾。后一种解决方案用于字符数组,这些数组通常以空字符结尾(最后一个字符为 \0)。在这种情况下,您可以通过循环直到遇到这样的终止字符来计算大小。

    【讨论】:

      【解决方案4】:

      以下是不好的建议,不要那样做。

      要获取当前glibcmalloc()(等)分配的内存,您可以尝试以下操作:

      #include <stdlib.h>
      #include <stdio.h>
      
      #define GLIB_MSIZE_T size_t /* We need to have a four byte unsigned integer type 
                                     here. */
      
      #define GLIB_MSIZE(p) \
              *((GLIB_MSIZE_T*) (((char*) p) - sizeof(GLIB_MSIZE_T)))
      
      int main(int iArgC, char ** ppszArgV)
      {
              if (1 >= iArgC)
              {
                      fprintf(stderr, "usage: %s <bytes to allocate>\n", ppszArgV[0]);
                      return EXIT_FAILURE;
              }
      
              {
                      /* This conversion uing 'atol()' only works up until to a certain size
                         of the integer represented by 'ppszArgV[1]'. */
                      size_t size = atol(ppszArgV[1]);
      
                      void * pv = malloc(size);
                      if (!pv)
                      {
                              fprintf(stderr, "Allocation of %u bytes failed.\n", size);
                              return EXIT_FAILURE;
                      }
      
                      printf("Asked for %u bytes, got %u bytes.\n", size, GLIB_MSIZE(pv));
              }
      
              return EXIT_SUCCESS;
      }
      

      除了确实可以获得分配的内存量之外,使用此代码付款时看到的有趣的事情是,在大多数情况下,分配的内存大小超过了请求的内存大小.

      无论如何,后者使得尝试从这里以最初请求的确切大小提取信息是不安全的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-17
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        • 1970-01-01
        • 2015-02-18
        • 1970-01-01
        相关资源
        最近更新 更多