如何在C中获取数组参数的实际大小?

时间:2018-05-16 04:40:34

标签: c arrays parameters typedef sizeof

编辑:虽然有人认为此问题与他们发布链接的问题相同。这是非常不同的问题。

考虑以下事项:

tempCount

类型BUFFER_SPACE是一个大小为200字节的数组(假设为UTF16)

在大多数情况下,声明一个变量,例如:

#define HUNDRED 100
typedef WCHAR BUFFER_SPACE[HUNDRED]; 

将导致wprintf输出200(如预期的那样。)

现在,请考虑以下简单的示例程序:

BUFFER_SPACE abuffer         = { 0 };

wprintf(L"sizeof abuffer        : %zd\n", sizeof(abuffer));

我想在函数中获取缓冲区参数的整个大小。使用VC ++并编译为64位,

sizeof(abuffer)是8,这是有意义的,因为它是一个指向数组的指针

sizeof(* abuffer)是2,我认为这是值得怀疑但是,这不是我想辩论的内容。

sizeof(BUFFER_SPACE)应该是200。

我的问题是:有没有办法从参数中获取200的值(在这种情况下为abuffer)或是使用该类型获取它的唯一方法?

2 个答案:

答案 0 :(得分:2)

让我们首先看一下如何将数组传递给函数 -

引用C11,章§6.7.6.3p7

  

参数声明为"类型"的数组;应调整为"符合类型"的限定指针,其中类型限定符(如果有)是在数组类型派生的[和]内指定的那些。 ...

这意味着你的功能原型有效地变成了 -

void Function(WCHAR *abuffer);

在此函数的主体中,编译器不再具有类型信息。它可以是WCHAR[100]WCHAR[200]甚至是WCHAR[]

我认为你已经理解为什么sizeof(abuffer)8 - 因为它是一个指针。

现在来sizeof(*abuffer)abuffer的类型为WCHAR*,因此*abuffer的类型将为WCHAR,因此sizeof(*abuffer) == sizeof(WCHAR) == 2

要回答你的主要问题,有没有办法让函数知道缓冲区的大小,有两种方法 -

  1. 您将信息作为第二个参数传递。但这不是必需的,因为大小始终为sizeof(BUFFER_SPACE)
  2. 您将指针传递给BUFFER_SPACE而不是BUFFER_SPACE。您可以将原型更改为 -

    void Function(BUFFER_SPACE *abuffer);
    

    并在任何地方使用*abuffer代替abuffersizeof(*abuffer)现在也将返回200,因为类型信息已正确保留。

答案 1 :(得分:2)

要完成answer by Ajay Brahmakshatriya:在您的特定情况下,您知道数组的大小(实际上是维度),并且您可以使用预处理器常量HUNDRED

但总的来说(特别是指向堆分配数组的指针)没有自动获取大小的方法,你应该采用一些关于数组大小的约定 。通常的做法是将数组的维度作为另一个参数传递给函数。典型示例是fwrite标准函数,或qsort标准函数或snprintf

您还可以考虑使用flexible array members的结构,其惯例是某些固定字段给出了该灵活数组成员的大小。

然后你可以考虑一些abstract data type。我举了一个简单的Matrix示例here。但是你仍然需要约定。

请注意,C是一种低级语言,coding conventions非常重要(特别是当您处理指向堆分配的指针时 - malloc - ed或calloc - ed-数据:您应该定义并记录一些约定,解释这些指针应该是free - d的人和方式,以及指向数据的大小。)

记住比在C数组中衰减成指针(例如,当你将它们作为参数传递给你的Function时),并且sizeof某些指针总是固定的(在我的x86-64 Linux系统上)它总是8)并且不依赖于指向的存储区域(以及它分配的大小,如果有的话)。

  

有没有办法从参数

获取值200

,不是一般的。你需要约定来处理它。您经常将维度作为一些额外参数传递(例如,您的main应该同时包含argcargv。有时它的结构不同(通过某些结构中的某些字段,某些全局变量等等)。