How would I get the size of this:
char* stringit[4] = {"H","H","UH","i"};
I tried:
sizeof(stringit);
and it outputed 32.
I tried to make a for loop:
for (i= 0; check != 0; ++i){
check = stringit[i];
}
and that did not work either. Is there anyway to do this without having to pass in the size of the array?
make it a NULL terminated array of pointers
char* stringit[] = {"H","H","UH","i" , NULL };
Then just count the pointers until you find a null pointer.
The right way to get the number of elements of an array is to divide its actual size (in bytes) by the size of an element:
sizeof(stringit) / sizeof(stringit[0])
But unless you have extremely specific requirements, you should use a standard container like vector (and string too instead of char* C strings):
std::vector<std::string> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As #KonradRudolph mentioned, vector is nice if your number of elements is variable. If the number of elements is known at compile time and will never change you could instead use array:
std::array<std::string, 4> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As long as you have access to the array itself, i.e. as long as you have not converted it to a pointer, the number of elements can be calculated as
sizeof stringit / sizeof *stringit
which will evaluate to a compile-time constant 4 in your case.
Whether this is what you are looking for or not depends on some additional details, which you did not provide in your question. You mention "having to pass in the size of the array". Pass where?
32 is the right size. The variable stringit is an array of 4 char pointers, and each pointer is 8 bytes.
What is it that you are trying to do?
char* stringit[4] = {"H","H","UH","i"};
is an array of 4 strings, i.e. array of 4 char* (pointer holds an address, 64bit address = 8 bytes). That's why you get 32. To retrieve the number of elements, you could do:
int count = sizeof(stringit) / sizeof(stringit[0]);
which will give you 4. But note that this kind of approach isn't much flexible and I'd rather use some STL container, i.e. std::vector<char*> or yet even better, get rid of C-style strings as well and use std::vector<std::string> instead.
The sizeof works for static arrays. It's giving you the size of the construct in bytes.
If you want length, do sizeof(stringit) / sizeof(char*).
For a more flexible solution that is probably the ``Right way" to do things in C++ (which works for dynamic arrays), just use std::array, or std::vector/std::list, if you need more dynamic allocation.
http://www.cplusplus.com/reference/array/array/
http://www.cplusplus.com/reference/vector/vector/
http://www.cplusplus.com/reference/list/list/
With this construct, you can simply use a size() member.
Remember to pass by reference when necessary to avoid needless copying.
Related
I am working on a coding assignment for my class and I ran into a problem!
I have this constructor here, for a String object:
String::String(char str[]) {
size = (sizeof(str)/sizeof(str[0]));
data = new char[size];
for (int i = 0; i < size; ++i) {
data[i] = str[i];
}
}
Here is part of the main I was provided:
char test[11] = "Hello world";
String two(test);
cout << "The length of String two is: " <<
two.length() << endl;
cout << "The value of String two is: ";
two.print();
So when I run this, I would get 8 for the size (should be 11). However, after some research, I figured out it is because the sizeof(str) is returning the byte size of a pointer, rather than the entire array.
So is there any way to get the size of the whole array with what I have? I am not supposed to manipulate the provided main, therefore I cannot add an int size to the parameters, which would be the obvious solution.
I've been stuck on this one for a bit, thanks for any help and suggestions,
Array decays to pointer when passed to a function.
You have to either pass the length to the function, pass a STL container e.g. std::vector or use strlen() inside function. (Note that strlen() need a terminating null-character to work properly and you have to add that to your array)
You can not get size of array at runtime in C. At runtime, array is just the address. The size is simply not stored anywhere. In source code, at compile time, in a place where compiler knows the size, you can use sizeof operator, but that gets essentially converted to a constant numeric literal, ie. same as writing the right number there yourself (VLAs are a bit more complex case, and of course using sizeof can create portable code unlike hard-coded number).
To make matters worse (for understanding C), when you have a function parameter that looks like an array, it really is a pointer. Even if you give it static size in the parameter list, sizeof still it gives you size of pointer, for example. Only non-parameter variables can actually be arrays, with sizeof working as expected.
You have to pass the size somehow (usually as extra parameter) or have some other way of telling where the data ends (such as strings' '\0' at the end).
Use a vector instead of char array. You can get size by calling size() method of vector container. If you want to use a char array, then it is a common practice in c programming to pass size as second parameter in the function.
You will only get size of array using sizeof() function on the function stack in which the array is defined and if the array size is known in compile time.
What is the difference between
char (CharBuff[50])[10];
and
char CharBuff[10][50];
My requirement is to have 10 character buffers, each of length 50 max (including null terminating character)
And, I would like to access the buffers as CharBuff[0], CharBuff[1] and so on.
char (CharBuff[50])[10];
declares CharBuff as a 50-element array of 10-element arrays of char. The parentheses are superfluous in this case.
char CharBuff[10][50];
declares CharBuff as a 10-element array of 50-element arrays of char.
Given that you want 10 strings of up to 50 characters, you would use the second form; the type of each CharBuff[i] will be "50-element array of char".
If you really wanted to create a separate type definition for a 50-element array of char, you could do something like
typedef char Str[50];
...
Str CharBuff[10];
Now CharBuff is a 10-element array of Str, which is a 50-element array of char.
Normally, I would not create a separate typedef like this unless I wanted to make Str opaque; that is, I don't want to expose the details of its implementation to whomever's using it. In addition to the typedef, I'd also supply an API for allocating, assigning, copying, formatting, and displaying objects of type Str.
Put another way, if the person using the Str type has to be aware that it's a 50-element array of char in order to use it properly, then it's better to just make them use a 50-element array of char.
The other answers here which say they're the same are wrong! Both are NOT the same arrays and their sizes are very different. Here's a snippet to show that:
char i[50][10];
std::cout << sizeof(i[1]) << '\n';
char (j[10])[50];
std::cout << sizeof(j[1]) << '\n';
10
50
You can see the live example here.
i is a 50-element array with each element being a 10-element array of characters, while j is a 10-element array with each element being a 50-element array of characters. Although the total sizes of both would be the same, the size of an element at each level would be different. If you assume they're the same, it would lead to undefined behaviour
i[25][5] // OK
j[25][5] // accessing j beyond index 9 is undefined behaviour!
This shows that the parenthesis have no significance in a non-pointer, non-reference array declaration i.e. char (j[10])[50] is just confusing notation for char j[10][50].
My requirement is to have 10 character buffers, each of length 50 max
Then you should declare your array as char CharBuff[10][50].
Nobody ever uses the former, always use the latter form:
char CharBuff[10][50];
Latter syntax will be proficient and less confusing as per you requirement of 10 rows (char buffers) having length of 50 each.
Go for the last one as it clearly states what you are allocating.
However, since the question is tagged with c++ too, I would advise using std::vector and std::string as it follows:
std::vector<std::string> CharBuff(10, std::string(50, '\0'));
The big problem that i see here is confusing syntax. When you use parenthesis they already have known roles in c and c++ syntax such as type conversions, pointers to functions(which looks a bit like what you wrote). What you are using them for add's a new meaning which makes code more obfuscated and ignores the fact that c and c++ have a great and intuitive way, for anybody that used matrices at least once, to express 2d arrays. So, for a clean and not confusing syntax use the latter version:
char CharBuff[10][50];
You are looking for 10 arrays of 50 chars each.
To declare a single buffer of 50 bytes, you would use
char CharBuff[50];
But you want to have 10 buffers, so just tack that on to before[50], e.g.:
char CharBuff[10][50];
Now CharBuff[0] will address the first fifty-byte buffer, CharBuff[1] will get the second, and so on.
class Simple {
string *data ;
//some functions and declaration of some variable,const, dest
};
When I did ;
data = new string [10] ;
cout << sizeof data / sizeof *data << endl ;
==> 1 // output
data = new string [50];
cout <<sizeof data / sizeof *data <<endl ;
==> 1 // output
**Why** do all output display the same ?
Because it simply doesn't work at all.
It only works for plain old arrays that are declared this way :
string a[10];
and it is the only case when this work.
in your case, you can't retrieve the size from the pointers you have. you have to either store the size of what you have, or just use the STL containers which all have a .size() member. The latter is preferable.
Because sizeof is a compile-time calculation, not a run-time one. And your array size is not known until run-time.
sizeof does not know anything about where the pointer points to, so it doesn't matter how big of a buffer you allocated, or even that you allocated a buffer at all. You can even do:
data = NULL;
x = sizeof(*data);
Because it's calculated at compile-time, there is no null-pointer dereferencing.
sizeof only looks at the datatype you pass in, not the data itself. In this case, string*, which is the same size no matter where it points to.
You have a few options to make this "work":
Use a statically-sized array (e.g. string data[50];) where you can use your sizeof idiom, but of course you get all the standard limitations of static arrays then.
Continue to dynamically allocate using new, but just store the array size and pass it around wherever you need it.
Preferred: Use std::vector for arrays -- this is basically the best of all worlds.
What is sizeof data? It is the size of a string*. What is sizeof *data? It is the size of what data points to, that is, size of string. Both of these are constant.
data does not have any knowledge about how many elements you allocated - it is just a stupid pointer.
You have to remember, sizeof always evaluates in compile-time. So you can never get sizeof info about things that happens in run-time, like new calls.
I need to be able to set the size of an array based on the number of bytes in a file.
For example, I want to do this:
// Obtain the file size.
fseek (fp, 0, SEEK_END);
size_t file_size = ftell(fp);
rewind(fp);
// Create the buffer to hold the file contents.
char buff[file_size];
However, I get a compile time error saying that the size of the buffer has to be a constant.
How can I accomplish this?
Use a vector.
std::vector<char> buff(file_size);
The entire vector is filled with '\0' first, automatically. But the performance "lost" might not be noticable. It's certainly safer and more comfortable. Then access it like a usual array. You may even pass the pointer to the data to legacy C functions
legacy(&buff[0]); // valid!
You should use a std::vector and not an array.
Real arrays require you to specify their size so that the compiler can create some space for them -- this is why the compiler complains when you don't supply a constant integer. Dynamic arrays are represented by a pointer to the base of the array -- and you have to retrieve the memory for the dynamic array yourself. You may then use the pointer with subscript notation. e.g.,
int * x;
x = (int *) malloc( sizeof(int) *
getAmountOfArrayElements() /* non-const result*/
);
x[5] = 10;
This leads to two types of problems:
Buffer over/under flows : you might subscript-index past either end of the array.
You might forget to release the memory.
Vector provides a nice little interface to hide these problems from you -- if used correctly.
Replace
char buff[file_size];
with
char *buff = new char[file_size];
and once the use of the buff is done..you can free the memory using:
delete[] buff;
There are two points in your question I'd like to cover.
The actual question, how do you create the array. Johannes answered this. You use a std::vector and create it with a size allocation.
Your error message. When you declare an array of some type, you must declare it with a constant size. So for example
const int FileSize = 1000;
// stuff
char buffer[FileSize];
is perfectly legitimate.
On the other hand, what you did, attempting to declare an array with variable size, and then not allocating with new, generates an error.
Problem is that buff needs be created on the heap (instead of stack). Compiler want s to know the exact size to create on the stack.
char* buff = new char[file_size];
In C++, arrays cannot be passed simply as parameters. Meaning if I create a function like so:
void doSomething(char charArray[])
{
// if I want the array size
int size = sizeof(charArray);
// NO GOOD, will always get 4 (as in 4 bytes in the pointer)
}
I have no way of knowing how big the array is, since I have only a pointer to the array.
Which way do I have, without changing the method signature, to get the size of the array and iterate over it's data?
EDIT: just an addition regarding the solution. If the char array, specifically, was initialized like so:
char charArray[] = "i am a string";
then the \0 is already appended to the end of the array. In this case the answer (marked as accepted) works out of the box, so to speak.
Use templates. This technically doesn't fit your criteria, because it changes the signature, but calling code does not need to be modified.
void doSomething(char charArray[], size_t size)
{
// do stuff here
}
template<size_t N>
inline void doSomething(char (&charArray)[N])
{
doSomething(charArray, N);
}
This technique is used by Microsoft's Secure CRT functions and by STLSoft's array_proxy class template.
Without changing the signature? Append a sentinel element. For char arrays specifically, it could be the null-terminating '\0' which is used for standard C strings.
void doSomething(char charArray[])
{
char* p = charArray;
for (; *p != '\0'; ++p)
{
// if '\0' happens to be valid data for your app,
// then you can (maybe) use some other value as
// sentinel
}
int arraySize = p - charArray;
// now we know the array size, so we can do some thing
}
Of course, then your array itself cannot contain the sentinel element as content.
For other kinds of (i.e., non-char) arrays, it could be any value which is not legal data. If no such value exists, then this method does not work.
Moreover, this requires co-operation on the caller side. You really have to make sure that the caller reserves an array of arraySize + 1 elements, and always sets the sentinel element.
However, if you really cannot change the signature, your options are rather limited.
In general when working with C or low-level C++, you might consider retraining your brain to never consider writing array parameters to a function, because the C compiler will always treat them as pointers anyway. In essence, by typing those square brackets you are fooling yourself in thinking that a real array is being passed, complete with size information. In reality, in C you can only pass pointers. The function
void foo(char a[])
{
// Do something...
}
is, from the point of view of the C compiler, exactly equivalent to:
void foo(char * a)
{
// Do something
}
and obviously that nekkid char pointer contains no length information.
If you're stuck in a corner and can't change the function signature, consider using a length prefix as suggested above. A non-portable but compatible hack is to specify the array length in an size_t field located before the array, something like this:
void foo(char * a)
{
int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1];
int c_len = ((size_t *)a)[-1];
}
Obviously your caller needs to create the arrays in the appropriate way before passing them to foo.
Needless to say this is a horrible hack, but this trick can get out of trouble in a pinch.
It actually used to be a quite common solution to pass the length in the first element of the array. This kind of structure is often called BSTR (for “BASIC string”), even though this also denoted different (but similar) types.
The advantage over the accepted solution is that determining the length using a sentinel is slow for large strings. The disadvantage is obviously that this is a rather low-level hack that respects neither types nor structure.
In the form given below it also only works for strings of length <= 255. However, this can easily be expanded by storing the length in more than one byte.
void doSomething(char* charArray)
{
// Cast unnecessary but I prefer explicit type conversions.
std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0]));
// … do something.
}
if it's nullterminated, strlen() would work.
You can't determine the size from charArray alone. That information is not automatically passed to the function.
Of course if it's a null-terminated string you can use strlen(), but you have probably considered that already!
Consider passing a std::vector<char> & parameter, or a pair of pointers, or a pointer plus a size parameter.
This is actually more C than C++, in C++ you'd probably rather use a std::vector. However, in C there's no way to know the size of an array. The compile will allow you to do a sizeof if the array was declared in the current scope, and only if it was explicitly declared with a size (EDIT: and "with a size", I mean that it was either declared with an integer size or initialized at declaration, as opposed to being passed as a parameter, thanks for the downvote).
The common solution in C is to pass a second parameter describing the number of elements in the array.
EDIT:
Sorry, missed the part about not wanting to change the method signature. Then there's no solution except as described by others as well, if there's some data that is not allowed within the array, it can be used as a terminator (0 in C-strings, -1 is also fairly common, but it depends on your actual data-type, assuming the char array is hypothetical)
In order for a function to know the number of items in an array that has been passed to it, you must do one of two things:
Pass in a size parameter
Put the size information in the array somehow.
You can do the latter in a few ways:
Terminate it with a NULL or some
other sentinel that won't occur in
normal data.
store the item count in the first entry if the array holds numbers
store a pointer to the last entry if the array contains pointers
try using strlen(charArray);
using the cstring header file. this will produce the number of characters including spaces till it reaches the closing ".
You are guarranteed to receive 4 in a 32-bit PC and that's the correct answer. because of the reason explained here and here.
The short answer is, you are actually testing the sizeof a pointer rather than an array, because "the array is implicitly converted, or decays, into a pointer. The pointer, alas, doesn't store the array's dimension; it doesn't even tell you that the variable in question is an array."
Now that you are using C++, boost::array is a better choice than raw arrays. Because it's an object, you won't loose the dimention info now.
I think you can do this:
size_t size = sizeof(array)/sizeof(array[0]);
PS: I think that the title of this topic isn't correct, too.
Dude you can have a global variable to store the size of the array which will be accessible throughout the program. At least you can pass the size of the array from the main() function to the global variable and you will not even have to change the method signature as the size will be available globally.
Please see example:
#include<...>
using namespace std;
int size; //global variable
//your code
void doSomething(char charArray[])
{
//size available
}