Why sizeof Variablename / sizeof * VariableName not work as desired? - c++

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.

Related

Sizeof is returning pointer size rather than array size. Any other way to find the size?

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.

C++ string length in bytes

string str; str="hello"; str.length(); sizeof(str);
I see that str.length returns the length in bytes why sizeof(str) doesn't return the same?
Is there alternative in c++ to a c command which is strlen(str)? What is the alternative of this coomand in c++?
When I use winsock in the send function I return the length in bytes. What should I use?
str.length? Or sizeof(str)? Pr something else? Because I see they produce different results.
sizeof returns the size of the data structure, not the size of the data in contains.
length() returns the length of the string that str contains, and is the function you want
It might seem confusing because sizeof(char[30]) is 30, but that is because the size of the data structure is 30, and will remain 30 no matter what you put in it
The string is actually an extremely complicated structure, but suppose it was a simple class with a pointer and a length
class string
{
char *data;
int length;
};
then sizeof(string) would return:
The size of a char * pointer, possibly but not necessarily 4
plus the size of an int, possibly but not necessarily 4
So you might get a value of 8. What the value of data or length is has no effect on the size of the structure.
sizeof() is not really meant to be used on a string class. The string class doesn't store ONLY the string data; there would be no difference between its data and a C-style string; it has other stuff in it as well, which throws off sizeof(). To get the actual length of the characters in the string, use str.length().
Don't use the C strlen() on a C++ string object. Don't use sizeof() either. Use .length().
std::string in C++ is instantiated as a pointer to a string object, since a string may have varying length. What sizeof() is returning is the size of the pointer to the string object (which on a 32 bit machine will probably be 4)
Operator sizeof() returns size of given type or object in bytes. 'Type version' is quite simple to understand, bu with 'Object version' you need to rember one thing:
sizeof() looks only on type definition and deduces total size from size and number of its members (in general, polymorphic and multiple inherited types may have additional 'hidden' members).
In other words, let's assume we have:
struct A
{
int* p1;
char* p2;
};
As you can probably suspect, sizeof(A) will return 8 (as pointer is 4-byte type on most 32-bit systems). But, when you do something like this:
A a_1;
a_1.p1 = new int[64];
sizeof(a_1) will still return 8. That's because memory allocated by new and pointed by A's member, does not 'belong' to this object.
And that is why sizeof(str) and str.length() give different results. std::string allocates memory for chars on the heap (dynamically, via malloc()), so it doesn't change string's size.
So, if you want to send string via network, proper size is str.len() and data pointer can be retrieved by calling str.c_str().
I didn't understant part with "strlen(str) equivalent". In C++ there is also strlen() function, with the same prototype, working exactly in the same way. It simply requires const char*, so you cannot use it for std::string (but you can do strlen(str.c_str()), as std::string's internal string is guaranteed to be null-terminated). For std::string use .length() as you already did.

How to get size of char* x[]

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.

Determining the correct size for a C++ array

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];

C++ strcpy non-constant expression as array bound

I turned back to C++ after a long time in C#, PHP and other stuff and I found something strange:
temp.name = new char[strlen(name) + strlen(r.name) + 1];
this compiles
temp.name = (char *)malloc(sizeof(char[strlen(name)
+ strlen(r.name) + 1]));
this doesn't (temp.name is a char *)
The compiler error is
error C2540: non-constant expression
as array bound
Does anyone know what the problem might be and how it might be remedied? Thank you.
sizeof(...) expects a constant compile-time expression. strlen is not a compile-time expression, it is a function which needs to be executed to get a result. Therefore, the compiler is not able to reserve sufficient storage for an array declared like this:
char c[strlen("Hello")];
Although the length of the string is clearly 5, the compiler does not know.
To avoid this pitfall, do not use sizeof here. Instead:
char* c = (char*)malloc(strlen(name)+strlen(rname)+1);
This gives you a pointer to n bytes in return. sizeof(char)==1 is always true, so the number of bytes in the buffer equals the number of chars you can store in it. To malloc arrays of a different type, multiply with the static size of one array element:
int* c = (int*) malloc(sizeof(int)*100);
This is Ok, because sizeof is applied to a compile-time expression. Of course, the C++ way is much cleaner:
int* c = new int[100];
The problem is char[...] which is an array type and in C++ (and C89) array sizes need to be compile-time constants. You should probably use std::string instead of allocating the memory manually by new[] or malloc(), but if you prefer to use manual allocation, calculate the size directly as the number of characters instead of using arrays and sizeof to do it.
malloc needs a size_t as its input, meaning you need to calculate the actual size and pass that in instead of specifying the type:
temp.name = (char *) malloc( (strlen(name) + strlen(r.name) + 1)) * sizeof(char));
You should probably be using new anyway, so I don't see any real issues.