首页 > 解决方案 > 如何在C中获取数组参数的实际大小?

问题描述

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

考虑以下:

#define HUNDRED 100
typedef WCHAR BUFFER_SPACE[HUNDRED]; 

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

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

BUFFER_SPACE abuffer         = { 0 };

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

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

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

#include "stdafx.h"
#include <Windows.h>
#include <WinNt.h>

#define HUNDRED 100
typedef WCHAR BUFFER_SPACE[HUNDRED]; 

void Function(BUFFER_SPACE abuffer)
{
  BUFFER_SPACE anotherbuffer = { 0 };

  wprintf(L"sizeof  abuffer      : %zd\n", sizeof(abuffer));         // 8
  wprintf(L"sizeof *abuffer      : %zd\n", sizeof(*abuffer));        // 2
  wprintf(L"sizeof anotherbuffer : %zd\n", sizeof(anotherbuffer));   // 200

  // a highly undesirable solution is to apply sizeof to the type but, if the
  // type of the parameter changes, the programmer has to be aware that the
  // original/old type is being used in sizeof() someplace else in the
  // function/program

  wprintf(L"sizeof BUFFER_SPACE  : %zd\n", sizeof(BUFFER_SPACE));  // 200

  getchar();
}

int main()
{
  BUFFER_SPACE abuffer         = { 0 };

  WCHAR anotherbuffer[HUNDRED] = { 0 };

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

  Function(abuffer);

  return 0;
}

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

sizeof(abuffer) 是 8,这是有道理的,因为它是指向数组的指针

sizeof(*abuffer) 是 2,我认为这很值得怀疑,但我不想讨论这个问题。

sizeof(BUFFER_SPACE) 应该是 200。

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

标签: carraysparameterstypedefsizeof

解决方案


让我们先看看数组是如何传递给函数的——

引用C11,第§6.7.6.3p7章

将参数声明为“类型数组”应调整为“类型限定指针”,其中类型限定符(如果有)是在数组类型派生的 [ 和 ] 中指定的限定符。...

这意味着您的函数原型有效地变为 -

void Function(WCHAR *abuffer);

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

我想你已经明白为什么sizeof(abuffer)8——因为它是一个指针。

现在来到sizeof(*abuffer). 的类型abufferWCHAR*,所以 的类型*abufferWCHAR,因此sizeof(*abuffer) == sizeof(WCHAR) == 2

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

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

    void Function(BUFFER_SPACE *abuffer);
    

    并使用*abuffer而不是abuffer无处不在。sizeof(*abuffer)现在也将返回200,因为类型信息已正确保留。


推荐阅读