Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算数组的大小_C++_C - Fatal编程技术网

C++ 计算数组的大小

C++ 计算数组的大小,c++,c,C++,C,我使用以下宏计算数组的大小: #define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0]))) 但是,当我计算函数中数组的大小(计算的值不正确)时,它计算的值与调用函数的位置(计算的值正确)不同。代码+下面的输出。任何想法、建议、提示等。欢迎 DP 这不起作用,因为sizeof是在编译时计算的。函数没有关于其参数大小的信息(它只知道它指向内存地址) 考虑改用STL向量,或者将数组大小作为参数传递给函数。您应该只调用数组上的sizeof。在

我使用以下宏计算数组的大小:

#define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0])))  
但是,当我计算函数中数组的大小(计算的值不正确)时,它计算的值与调用函数的位置(计算的值正确)不同。代码+下面的输出。任何想法、建议、提示等。欢迎

DP


这不起作用,因为sizeof是在编译时计算的。函数没有关于其参数大小的信息(它只知道它指向内存地址)


考虑改用STL向量,或者将数组大小作为参数传递给函数。

您应该只调用数组上的sizeof。在指针类型上调用sizeof时,大小将始终为4(或8,或系统执行的任何操作)

MSFT的匈牙利符号可能很难看,但如果你使用它,你就知道不要对任何以“p”开头的东西调用宏


还要签出WinNT.h中ARRAYSIZE()宏的定义。如果你使用C++,如果你这样做,你可以用模板来做一些奇怪的事情来获得编译时间。

如果你改变了FoO函数,它会让你感觉更舒服:

void foo(int * pointertofoo) 
{              
   printf("pointertofoo : %x\n", pointertofoo);  
   printf ("sizeof pointertofoo: %d\n", G_N_ELEMENTS(pointertofoo));
}

这就是编译器将看到的与函数完全不同的上下文。

这是因为
int*
的大小是int指针的大小(在我使用的现代平台上是4或8字节,但它完全取决于平台)。
sizeof
是在编译时计算的,而不是在运行时,因此即使是
sizeof(arr[])
也不会有帮助,因为您可以在运行时使用许多不同大小的数组调用
foo()
函数

整数数组的大小是整数数组的大小

这是C/C++中的一个棘手问题——数组和指针的使用并不总是相同的。在很多情况下,数组将衰减为指向该数组第一个元素的指针

至少有两种解决方案与C和C++兼容:

  • 将长度与数组一起传递(如果函数的目的是实际计算数组大小,则该函数不太有用)
  • 传递标记数据结束的哨兵值,例如,
    {1,2,3,4,-1}

请注意,即使您试图告诉C编译器函数中数组的大小,它也不会接受提示(my
DIM
相当于您的
G\u N\u元素
):

如果您想知道函数中的数组有多大,请将大小传递给函数。或者,在C++中,使用STL <代码>矢量< /代码>等。< /P> sizeof(arr)是sizeof(int*),即4

除非您有很好的理由编写这样的代码,否则不要这样做。我们现在处于21世纪,请使用std::vector

更多信息,请参见C++ FAQ:


请记住:C++中的“数组是邪恶的”

,可以定义这样的Gnn-元素:

template<typename T, size_t N> 
size_t G_N_ELEMENTS( T (&array)[N] )
{
  return N;
}
模板
大小\u t G\u N\u元素(t(&数组)[N])
{
返回N;
}
如果希望在编译时使用数组大小,请按照以下方法操作:

// ArraySize
template<typename T> 
struct ArraySize;

template<typename T, size_t N> 
struct ArraySize<T[N]> 
{ 
  enum{ value = N };
};
//数组化
模板
结构阵列化;
模板
结构阵列化
{ 
枚举{value=N};
};

感谢j_random_hacker纠正了我的错误并提供了更多信息。

编辑:C++11是在编写此答案后引入的,它包含了一些函数,可以完全实现我在下面显示的功能:和。Const版本
std::cbegin
std::cend
也将进入标准的未来版本(C++14?),并且可能已经在您的编译器中。如果你能访问标准函数,就不要考虑使用下面的函数。
我想在此基础上再接再厉

不只是将数组的起始地址作为指针传递,或者像其他人建议的那样将指针加上大小,而是从标准库中获取线索,将两个指针传递到数组的开始和结束处。这不仅使你的代码更像现代C++,而且你可以使用任何标准的库算法在你的数组中!p>
template<typename T, int N>
T * BEGIN(T (& array)[N])
{
    return &array[0];
}

template<typename T, int N>
T * END(T (& array)[N])
{
    return &array[N];
}

template<typename T, int N>
const T * BEGIN_CONST(const T (& array)[N])
{
    return &array[0];
}

template<typename T, int N>
const T * END_CONST(const T (& array)[N])
{
    return &array[N];
}

void
foo(int * begin, int * end)
{
  printf("arr : %x\n", begin);
  printf ("sizeof arr: %d\n", end - begin);
}

int
main()
{
  int arr[] = {1, 2, 3, 4};

  printf("arr : %x\n", arr);
  printf ("sizeof arr: %d\n", END(arr) - BEGIN(arr));

  foo(BEGIN(arr), END(arr));
}
更新:上述带有模板的代码在MS VC++2005和GCC 3.4.6中正常工作。我需要一个新的编译器


我还重新考虑了这里使用的命名约定——伪装成宏的模板函数感觉不对。我相信不久我会在自己的代码中使用它,我想我会使用ArrayBegin、ArrayEnd、ArrayConstBegin和ArrayConstEnd。

现在我们在C++11中有了
constepr
,类型安全(非宏)版本也可以在常量表达式中使用

template<typename T, std::size_t size>
constexpr std::size_t array_size(T const (&)[size]) { return size; }
也就是说,如果可能的话,最好使用
std::array
。不要理会那些说要使用
std::vector
的人,因为这样更好
std::vector
是一种具有不同优势的不同数据结构<与C型数组相比,code>std::array没有开销,但与C型数组不同,它不会在任何刺激下衰减为指针<另一方面,code>std::vector,要求所有访问都是间接访问(通过指针),使用它需要动态分配。如果您习惯于使用C样式数组,请记住一件事,即确保将
std::array
传递给如下函数:

void f(std::array<int, 100> const & array);
void f(标准::数组常量和数组);

如果不按引用传递,则复制数据。这遵循了大多数设计良好的类型的行为,但在传递给函数时与C样式数组不同(更像是结构内部的C样式数组的行为)。

使用相同的名称调用foo参数会使这与您的直觉相反。考虑给它另一个名称来模拟编译器正在查看的内容。你可以在指针上调用siZeFor(),但是你得到的大小将是指针的大小,而不是数组的大小。+ 1。事实上,C++至少(也许C,我不确定)不符合大小
template<typename T, size_t N> 
size_t G_N_ELEMENTS( T (&array)[N] )
{
  return N;
}
// ArraySize
template<typename T> 
struct ArraySize;

template<typename T, size_t N> 
struct ArraySize<T[N]> 
{ 
  enum{ value = N };
};
template<typename T, int N>
T * BEGIN(T (& array)[N])
{
    return &array[0];
}

template<typename T, int N>
T * END(T (& array)[N])
{
    return &array[N];
}

template<typename T, int N>
const T * BEGIN_CONST(const T (& array)[N])
{
    return &array[0];
}

template<typename T, int N>
const T * END_CONST(const T (& array)[N])
{
    return &array[N];
}

void
foo(int * begin, int * end)
{
  printf("arr : %x\n", begin);
  printf ("sizeof arr: %d\n", end - begin);
}

int
main()
{
  int arr[] = {1, 2, 3, 4};

  printf("arr : %x\n", arr);
  printf ("sizeof arr: %d\n", END(arr) - BEGIN(arr));

  foo(BEGIN(arr), END(arr));
}
#define BEGIN(array) array
#define END(array) (array + sizeof(array)/sizeof(array[0]))
template<typename T, std::size_t size>
constexpr std::size_t array_size(T const (&)[size]) { return size; }
int new_array[array_size(some_other_array)];
void f(std::array<int, 100> const & array);