如何在 C 中获取数组参数的实际大小?
How to get the real size of an array parameter in C?
编辑: 虽然有人认为这个问题与他们发布 link 的问题相同。这是一个非常不同的问题。
考虑以下因素:
#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。
我的问题是:有没有办法从参数(在本例中为 abuffer)获取 200 的值,或者使用类型是获取它的唯一方法?
让我们先看看数组是如何传递给函数的 -
引用 C11
,章节 §6.7.6.3p7
A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. ...
这意味着您的函数原型实际上变成了 -
void Function(WCHAR *abuffer);
在这个函数体中,编译器不再有类型信息。它可能是 WCHAR[100]
、WCHAR[200]
甚至 WCHAR[]
。
我想您已经明白为什么 sizeof(abuffer)
是 8
-- 因为它是一个指针。
现在 sizeof(*abuffer)
。 abuffer
的类型是 WCHAR*
,因此 *abuffer
的类型将是 WCHAR
,因此 sizeof(*abuffer) == sizeof(WCHAR) == 2
.
为了回答你的主要问题,有没有办法让函数知道缓冲区的大小,有两种方法 -
- 您将信息作为第二个参数传递。但这不是必需的,因为大小将始终为
sizeof(BUFFER_SPACE)
。
您将指针传递给 BUFFER_SPACE
而不是 BUFFER_SPACE
。您可以将原型更改为 -
void Function(BUFFER_SPACE *abuffer);
并在所有地方使用 *abuffer
而不是 abuffer
。 sizeof(*abuffer)
现在也会 return 200
,因为正确地保留了类型信息。
要完成 :在您的特定情况下,您知道数组的大小(实际上是维度),并且您可以使用预处理器常量 HUNDRED
.
但通常(尤其是指向堆分配数组的指针)没有自动获取它们大小的方法,你应该采用一些约定关于数组大小。一个非常常见的方法是将数组的维度作为另一个参数传递给函数。一个典型的例子就是fwrite standard function, or the qsort one, or the snprintf。
您也可以考虑使用具有 flexible array members 的结构,约定一些固定字段给出该灵活数组成员的大小。
然后你可以考虑一些abstract data type. I gave a simple Matrix
example 。但是你仍然需要约定。
请注意,C 是一种低级语言,coding conventions 非常重要(特别是当您处理指向堆分配的指针时 -malloc
-ed 或 calloc
- ed- 数据:你应该定义和记录一些约定,解释这些指针应该是谁以及如何free
-d,以及指向数据的大小是多少)。
请记住,在 C 数组中,数组会衰减为指针(例如,当您将它们作为参数传递给您的 Function
时),并且 sizeof
某些指针始终是固定的(在我的 x86-64 上Linux 系统它总是 8) 并且不依赖于指向的内存区域(以及它分配的大小,如果有的话)。
is there a way to get the value of 200 from the parameter
没有,一般不会。你需要约定来处理这个问题。您经常将维度作为一些附加参数传递(例如,即使您的 main
也应该同时具有 argc
和 argv
)。有时它以不同的方式为人所知(通过某些结构中的某些字段、某些全局变量等...)。
编辑: 虽然有人认为这个问题与他们发布 link 的问题相同。这是一个非常不同的问题。
考虑以下因素:
#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。
我的问题是:有没有办法从参数(在本例中为 abuffer)获取 200 的值,或者使用类型是获取它的唯一方法?
让我们先看看数组是如何传递给函数的 -
引用 C11
,章节 §6.7.6.3p7
A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation.
...
这意味着您的函数原型实际上变成了 -
void Function(WCHAR *abuffer);
在这个函数体中,编译器不再有类型信息。它可能是 WCHAR[100]
、WCHAR[200]
甚至 WCHAR[]
。
我想您已经明白为什么 sizeof(abuffer)
是 8
-- 因为它是一个指针。
现在 sizeof(*abuffer)
。 abuffer
的类型是 WCHAR*
,因此 *abuffer
的类型将是 WCHAR
,因此 sizeof(*abuffer) == sizeof(WCHAR) == 2
.
为了回答你的主要问题,有没有办法让函数知道缓冲区的大小,有两种方法 -
- 您将信息作为第二个参数传递。但这不是必需的,因为大小将始终为
sizeof(BUFFER_SPACE)
。 您将指针传递给
BUFFER_SPACE
而不是BUFFER_SPACE
。您可以将原型更改为 -void Function(BUFFER_SPACE *abuffer);
并在所有地方使用
*abuffer
而不是abuffer
。sizeof(*abuffer)
现在也会 return200
,因为正确地保留了类型信息。
要完成 HUNDRED
.
但通常(尤其是指向堆分配数组的指针)没有自动获取它们大小的方法,你应该采用一些约定关于数组大小。一个非常常见的方法是将数组的维度作为另一个参数传递给函数。一个典型的例子就是fwrite standard function, or the qsort one, or the snprintf。
您也可以考虑使用具有 flexible array members 的结构,约定一些固定字段给出该灵活数组成员的大小。
然后你可以考虑一些abstract data type. I gave a simple Matrix
example
请注意,C 是一种低级语言,coding conventions 非常重要(特别是当您处理指向堆分配的指针时 -malloc
-ed 或 calloc
- ed- 数据:你应该定义和记录一些约定,解释这些指针应该是谁以及如何free
-d,以及指向数据的大小是多少)。
请记住,在 C 数组中,数组会衰减为指针(例如,当您将它们作为参数传递给您的 Function
时),并且 sizeof
某些指针始终是固定的(在我的 x86-64 上Linux 系统它总是 8) 并且不依赖于指向的内存区域(以及它分配的大小,如果有的话)。
is there a way to get the value of 200 from the parameter
没有,一般不会。你需要约定来处理这个问题。您经常将维度作为一些附加参数传递(例如,即使您的 main
也应该同时具有 argc
和 argv
)。有时它以不同的方式为人所知(通过某些结构中的某些字段、某些全局变量等...)。