How to reliably get size of C-style array?

2019-01-07 22:46发布

How do I reliably get the size of a C-style array? The method often recommended seems to be to use sizeof, but it doesn't work in the foo function, where x is passed in:

#include <iostream>

void foo(int x[]) {
  std::cerr << (sizeof(x) / sizeof(int)); // 2  
}

int main(){
    int x[] = {1,2,3,4,5};
    std::cerr << (sizeof(x) / sizeof(int)); // 5                              
    foo(x);
    return 0;
}

Answers to this question recommend sizeof but they don't say that it (apparently?) doesn't work if you pass the array around. So, do I have to use a sentinel instead? (I don't think the users of my foo function can always be trusted to put a sentinel at the end. Of course, I could use std::vector, but then I don't get the nice shorthand syntax {1,2,3,4,5}.)

标签: c++ c arrays size
9条回答
欢心
2楼-- · 2019-01-07 23:06

You need to pass the size along with the array, just like it is done in many library functions, for instance strncpy(), strncmp() etc. Sorry, this is just the way it works in C:-).

Alternatively you could roll out your own structure like:

struct array {
    int* data;
    int size;
};

and pass it around your code.

Of course you can still use std::list or std::vector if you want to be more C++ -ish.

查看更多
够拽才男人
3楼-- · 2019-01-07 23:10

How about this?..

template <int N>
void foo(int (&x)[N]) {
    std::cerr << N;
}
查看更多
兄弟一词,经得起流年.
4楼-- · 2019-01-07 23:19

A common idiom mentioned in GNU Libstdc++ documentation is the lengthof function:

template<typename T, unsigned int sz>
inline unsigned int lengthof(T (&)[sz]) { return sz; }

You can use it as

int x[] = {1,2,3,4,5};
std::cerr << lengthof(x) << std::endl;

Warning: this will work only when the array has not decayed into a pointer.

查看更多
劳资没心,怎么记你
5楼-- · 2019-01-07 23:20

An array expression will have its type implicitly converted from "N-element array of T" to "pointer to T" and its value will be the address of the first element in the array, unless the array expression is the operand of either the sizeof or address-of (&) operators, or if the array expression is a string literal being used to initialize another array in a declaration. In short, you can't pass an array to a function as an array; what the function receives is a pointer value, not an array value.

You have to pass the array size as a separate parameter.

Since you're using C++, use vectors (or some other suitable STL container) instead of C-style arrays. Yes, you lose the handy shorthand syntax, but the tradeoff is more than worth it. Seriously.

查看更多
Lonely孤独者°
6楼-- · 2019-01-07 23:22

Since c++11, there is a very convenient way:

static const int array[] = { 1, 2, 3, 6 };
int size = (int)std::distance(std::begin(array), std::end(array))+1;
查看更多
干净又极端
7楼-- · 2019-01-07 23:24

c provides no native support for this. Once an array is passed out of its declared scope, its size is lost.

You can pass the size with the array. You can even bundle them into a structure if you always to to keep the size, though you'll have some bookkeepping overhead with that.

查看更多
登录 后发表回答