开发者

How to determine the size of an array of strings in C++?

I'm trying to simply print out the values contained in an array.

I have an array of strings called 'result'. I don开发者_如何学编程't know exactly how big it is because it was automatically generated.

From what I've read, you can determine the size of an array by doing this:

sizeof(result)/sizeof(result[0])

Is this correct? Because for my program, sizeof(result) = 16 and sizeof(result[0]) = 16 so that code would tell me that my array is of size 1.

However that doesn't appear correct, because if I manually print out the array values like this:

std::cout << result[0] << "\n";
std::cout << result[1] << "\n";
std::cout << result[2] << "\n";
std::cout << result[3] << "\n";
etc...

...then I see the resulting values I'm looking for. The array is upwards of 100+ values in length/size.

It seems like it should be very simple to determine the size/length of an array... so hopefully I'm just missing something here.

I'm a bit of a C++ newb so any help would be appreciated.


You cannot determine the size of an array dynamically in C++. You must pass the size around as a parameter.

As a side note, using a Standard Library container (e.g., vector) allieviates this.

In your sizeof example, sizeof(result) is asking for the size of a pointer (to presumably a std::string). This is because the actual array type "decays" to a pointer-to-element type when passed to a function (even if the function is declared to take an array type). The sizeof(result[0]) returns the size of the first element in your array, which coincidentally is also 16 bytes. It appears that pointers are 16 bytes (128-bit) on your platform.

Remember that sizeof is always evaluated at compile-time in C++, never at run-time.


As a side comment, there are better ways of checking the size of an array (for the cases where the array is in scope and has not decayed into a pointer) that are typesafe:

// simple: runtime result
template <typename T, std::size_t N>
inline std::size_t sizeof_array( T (&)[N] ) {
   return N;
}

// complex: compile time constant
template <typename T, std::size_t N>
char (&static_sizeof_array( T(&)[N] ))[N];   // declared, not defined
#defined SIZEOF_ARRAY( x ) sizeof(static_sizeof_array(x))

In both cases the compiler will detect if you try to pass in a pointer (dynamic array or decayed array):

void f( int array[] ) { // really: void f( int *array )
{
//   sizeof_array(array);              // compile time error
//   int another[SIZEOF_ARRAY(array)]; // compile time error
}
int main() {
   int array[] = { 1, 2, 3 };
   std::cout << sizeof_array(array) << std::endl; // prints 3
   int another_array[ SIZEOF_ARRAY(array) ];
   std::cout << sizeof_array(another_array) << std::endl; // 3 again
}


If what you have is a "real" array, then the sizeof(x)/sizeof(x[0]) trick works. If, however, what you have is really a pointer (e.g. something returned from a function) then that trick doesn't work -- you'll end up dividing the size of a pointer by the sizeof a pointer. They are pointers to different types, but on a typical system all pointers are the same size, so you'll get one. Even when the pointers are different sizes, the result still won't have anything to do with how many strings you have.


Better use std::vector<std::string> instead of a raw array. Then you don't have to manually manage the arrays memory and you can use the size() method if you want to know the number of elements.

If you use a dynamically allocated raw array you are expected to keep track of its size yourself, the size cannot be obtained from the array. Best save it in an extra variable.


The sizeof(array)/sizeof(element) works for fixed-length-array of fixed-length-arrays (not of pointers). As an array of strings we most often use a (fixed-length-)array of pointers-to-various-(fixed-)length-strings so this trick wouldn't work. sizeof() is used for objects which size is known at compile time. It's not applicable to dynamically allocated data itself.

When an object contains pointers like in the case of an array of strings, sizeof() returns the size of the highest-level (fixed-size) structure. Often it's just the size of a single pointer. It does not include the size of the allocated data pointed to by the pointers. Because that data actually is not part of the main object, it's indeed one or more separate objects (we have aggregation here instead of composition, see http://en.wikipedia.org/wiki/Object_composition).

In C++ using vectors is very convenient for your needs. Other suitable standard containers could be used too. length() and size() methods are synonyms, see http://www.cplusplus.com/reference/string/string/size/)

P.S. Please note that for std::string s object sizeof(s) is a constant independent of the actual (variable) string length returned by s.length(). The actual allocated memory size is returned by s.capacity() and could be greater than length().

Example using vector array:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string s = "01234";
    cout << "s[" << s.length() << "]=\"" << s << "\"" << endl; 
    cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
    cout << endl;

    s += "56789012345";
    cout << "s[" << s.length() << "]=\"" << s << "\"" << endl; 
    cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
    cout << endl;

    vector<string>vs={"12","23","345","456","567","67888","7899999999","8","9876543210"};

    cout << "vs[" << vs.size() << "]={";
    size_t sz=0;
    for (size_t index=0; index<vs.size(); index++)
    {
        sz+=vs[index].size();
        if (index>0)
            cout << ",";
        cout << "\"" << vs[index] << "\":" << vs[index].size();
    }
    cout << "}:" << sz << endl;
    cout << "sizeof(vs)=" << sizeof(vs) << " (implementation dependent)" << endl;

    return 0;
}

Result:

s[5]="01234"
sizeof(s)=8 (implementation dependent)

s[16]="0123456789012345"
sizeof(s)=8 (implementation dependent)

vs[9]={"12":2,"23":2,"345":3,"456":3,"567":3,"67888":5,"7899999999":10,"8":1,"9876543210":10}:39
sizeof(vs)=24 (implementation dependent)


template< class T, size_t N >
std::size_t Length(const T(&)[N])
{
    return N;
};

std::cout << Length(another_array) << std::endl;


In String vector use size() method


Something to be aware of: text can be represented in different methods. An array of text can also be represented in different methods.

Array of pointers to C-Style strings

A common method is to have an array of pointers to char. The issue is that the size of the array doesn't represent the size of all of the text. Also, the ownership of the data or pointer must also be established, as the text may have to be delete (and can the callee delete the text or does the caller?). Because it is an array, the size of the array must always accompany the array in all parameters (unless the array is always a fixed size).

Array of char - packed text

Another method is to pass an array of char and have the strings contiguous in the array. One string follows the termination char of the previous. With this array, the total size of all of the strings is represented, no wasted space. Again, with arrays, the size of the array must accompany the array when passed around.

Array of std::string

In C++, text can be represented using std::string. In this case, the array represents the quantity of strings (similar to the array of C-Strings above). To get the total size of all the strings, one must sum up the size of each individual string. Since this is an array, the size of the array must be passed also.

Summary

During run-time array sizes must accompany the array when the array is passed around. sizeof is only processed at compile time. A simpler structure is std::vector, which handles size and memory allocation dynamically.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜