C++ why can you initialize an empty string array? - c++

This is a "how does it work" question. Based on my understanding, you have to initialize a non-dynamic array with a constant number of elements (int intarr[5]) or your array will write over blocks of memory that might be allocated for something else.
So why is it that you can initialize a string array (string strArray[]) without any elements?
Example:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s[] = {"hi", "there"};
cout << s[0] << s[1];
cin >> s[10]; //why is this ok?
cout << s[10];
return 0;
}

As a feature C++ (and C) allows you to declare an array without specifying the number of elements if you specify an initializer for it. The compiler will infer the number of elements that's needed.
So for
int intarr[] = { 1,2,3,4,5};
The compiler will see that the array need to have room for 5 ints, and this is will be exactly the same as if you stated:
int intarr[5] = {1,2,3,4,5};
A string array is just the same;
string s[] = {"hi", "there"};
is the same as if you wrote
string s[2] = {"hi", "there"};
Your code has a serious bug though;
string s[] = {"hi", "there"};
cout << s[0] << s[1];
cin >> s[10]; //why is this ok?
cin >> s[10]; is absolutely NOT ok. The array s has only 2 elements, and even if the compiler does not generate an error, you cannot use s[10]
Doing so results in undefined behavior - so it could appear to work, or it could crash, or it could do anything.

You can use string strArray[] in 2 ways
string strArray[] = {"apple","banana"};
or
void function(string strArray[]) {
...
}
In the first case, the size of the array is automatically determined by the number of initializers (2). In the second case, the size of the array is not needed because it is a formal argument.
Other than that, you must declare a size to the array. It doesn't matter if it is based on string or int.
If you are writing to s[10] in your example but only have 2 elements, you are writing to unallocated memory and the program behavior is undefined. It may not crash, but later on something bad will happen.

Related

How to make the array size correct in C++?

I'm trying to create an array and the size of the array depends on the user input. But there is an error in my code, It said: "expression must have a constant value".
Here is my code:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int var;
cout << "What size do you want to choose: "<< endl;
cin >> var;
int arr[var];
}
How can I change my code and make it work?
How can I change my code and make it work?
Change
int arr[var];
to
std::vector<int> arr(var);
This will require #include <vector>
The syntax you are using is known as a "variable length array", and is NON-STANDARD. Only a few compilers support it as an vendor-specific extension to the C++ language.
A standard compliant fixed-length array must have its size known to the compiler as a compile-time constant.
For what you want, you need to use the new[] operator instead:
int *arr = new int[var];
...
delete[] arr;
Or better, use a std::vector container:
#include <vector>
std::vector<int> arr(var);
To allocate an array dynamically, we use the array form of new and delete (often called new[] and delete[]):
#include <iostream>
int main()
{
std::cout << "Enter a positive integer: ";
int length{};
std::cin >> length;
int *array{ new int[length]{} }; // use array new. Note that length does not need to be constant!
std::cout << "I just allocated an array of integers of length " << length << '\n';
array[0] = 5; // set element 0 to value 5
delete[] array; // use array delete to deallocate array
// we don't need to set array to nullptr/0 here because it's going to go out of scope immediately after this anyway
return 0;
}
Arrays in C++ must have constant size known at compile-time. You can preallocate several constant sizes known at compile time and offer the user to choose one of them. Alternatively, you can use another data structure that allows dynamic size allocation e.g std::vector.
Good luck!

C++ getting the size of an array of strings

I need to use an array of strings with an unknown size. Here I have an example to see if all works fine. I need to know that array's size in ClassC but without passing that value as an argument. I've see so many ways to do it (here and in google) but as you will see now, they didn't work. They return the number of chars in the first position of the array.
void ClassB::SetValue()
{
std::string *str;
str = new std::string[2]; // I set 2 to do this example, lately it will be a value from another place
str[0] ="hello" ;
str[1] = "how are you";
var->setStr(str);
}
Now, in ClassC if I debug, strdesc[0] ="hello" and strdesc[1] = "how are you", so I suppose that class C is getting the info ok....
void classC::setStr(const std::string strdesc[])
{
int a = strdesc->size(); // Returns 5
int c = sizeof(strdesc)/sizeof(strdesc[0]); // Returns 1 because each sizeof returns 5
int b=strdesc[0].size(); // returns 5
std::wstring *descriptions = new std::wstring[?];
}
So.. in classC, how can I know strdesc's array size, that should return 2?? I have also tried with:
int i = 0;
while(!strdesc[i].empty()) ++i;
but after i=2 the program crashes with a segmentation fault.
Thanks,
Edit with the possibles SOLUTIONS:
Conclusion: There is no way to know the array's size once I pass its pointer to another function
Pass the size to that function... or...
Use vectors with std::vector class.
how can I know strdesc's array size
You cannot know the size of an array from a pointer to that array.
What you can do is pass the size as another parameter. Or even better, use a vector instead.
but after i=2 the program crashes with a segmentation fault.
Accessing beyond the array boundary has undefined behaviour.
With this Kind of code you will get memory leaks and other kind of C-style problems.
use vector:
#include <vector>
#include <string>
#include <iostream>
...
std::vector<std::string> my_strings;
my_strings.push_back("Hello");
my_strings.push_back("World");
std::cout << "I got "<< my_strings.size() << " strings." << std::endl;
for (auto& c : my_strings)
std::cout << c << std::endl;

C++ , string in a function has always the same length

What is wrong with this code? input has always the length of 4 in my function test, no matter if my string is actually longer or shorter.
#include <iostream>
#include <string>
using namespace std;
void test(char arr[]){
string input;
input = arr[0];
for (int i=1; i<sizeof(arr)/sizeof(char); i++){input=input+arr[i];}
cout << input << endl;
cout << "length: " << input.length() << endl;
}
int main(){
string input;
cout << "String: " << endl;
getline(cin, input);
char arr[input.length()];
for(int i=0; i<input.length(); i++) {arr[i] = input[i];}
test(arr);
}
Arrays decays to pointers while passing to function
sizeof(arr) will give you size of char*
Don't use arrays; instead prefer std::vector. When you think you're passing an array to a function, you're actually passing a pointer, and on your architecture pointers are 4 bytes wide. char arr[] is a weird way of spelling char* arr in function parameters. This is known as “pointer decay”.
If you really have to use raw pointers, pass in the length as an additional parameter:
void test(size_t length, char* arr) {
...
}
test(input.length(), arr);
You are taking the size of the pointer when you do sizeof(arr) in the function. Passing an array to a function like you did is a syntactic sugar, effectively it is passing a pointer to the array and you are just taking the size of the pointer (which happens to be 4bytes on the machine you are using). You need to pass the size of the array to the function in another parameter or use a convenient STL container.
Also take a look at this question for more details.

Dynamically allocated string array, then change it's value?

I'm trying to create a string array and use a pointer to modify it. I'm not sure how to declare the pointer since strings can vary in length, and I think this is what causes the error.
My code looks something like this:
#includes <string>
#includes <iostream>
using namespace std;
string *users = NULL;
int seatNum = NULL;
cin >> seatNum;
users = new string[seatNum];
string name;
cin >> name;
users[seatNum] = name;
It throws me an Write Access Violation when I try to change its value. From what I've read it's because strings are compiled as read-only, so my question is how would I/what would I do to change it? Easy-to-understand explanations would be preferable.
You're accessing memory beyond the range of the allocated array
users = new string[seatNum];
users[seatNum] = name;
The first element is [0]. The last is [seatNum-1]
You have created an array of seatNum elements. Array element indexing starts at 0 therefore the range of valid indexes is [0, seatNum - 1]. By accessing users[seatNum] = ... you are effectively going past the last valid element of the array. This invokes UB (undefined behavior).
I see you have already made the right choice of using std::string instead of C-style strings. Why not make the same choice over arrays?
#include <string>
#include <array>
#include <iostream>
int main(int, char*[]) {
int seatNum = 0;
std::cin >> seatNum;
std::vector<std::string> users(seatNum);
std::cin >> users[0];
return 0;
}
Try to avoid pointers and C-style arrays, especially dynamic ones.
A few things:
int seatNum will be allocated on the stack and will never be NULL. You should set it to 0.
You are setting users[seatNum] which is out of bounds causing your program to crash. You
can only use indices from 0 to seatNum-1.
Updated: Chris is correct. I looked into it and strings are indeed mutable in C++.
firstly you cannot set null value to int type data
int seatNum = NULL; // wrong
int seatNum = 0; // right
secondly string bounds from 0 to seatnum -1
users[seatNum-1] = name; // right

how does compiler do with array declaration

char c='c';
char *pc = &c;
char a[]="123456789";
char *p = &(a[1]);
cout <<"the size of the a: "<< sizeof (a)<< endl; //10
cout <<"the size of the p: "<< sizeof (p)<< endl; //4
cout << p[100] <<endl;//cross boundary intentionally
cout << pc[0];//c
cout << pc[1];
Compiler no longer treat the p as an array? how does compiler verify whether it is or not an Array? Is there any difference between p and pc ?
Thanks!!!!
Compiler no longer treat the p as an array?
It never treated it as an array, because it was not. It was always a pointer. Arrays are not pointers. Read this, accept it, embrace it! They sometimes decay into pointers (when passed as parameters), but they are not pointers.
Is there any difference between p and pc ?
Type-wise - no. There's a difference in that they point to different chars.
Also, pc[1] is undefined behavior. You only own the memory pc points to directly - i.e. a single byte that contains the character 'c'. Same goes for p[100].
The compiler treats as arrays only variables declared as arrays, i.e. with square brackets. Pointers are not arrays, though, although you can treat array names as if they were pointers for the purposes of constructing pointer expressions.
If you would like to use an array structure where the compiler checks the bounds of the array, you can use std::vector. For example
#include <vector>
int main()
{
int array[]={0,1,2,3,4,5};
std::vector<int> vec;
vec.assign(array, array+6);
for(unsigned int i=0; i<vec.size(); ++i)
{
std::cout << vec.at(i);
}
return 0;
}
Here, vec.at(i) checks the bounds of the vector. If you use vec[i], this is also valid but the compiler does not check the bounds. Hope that helps.
The compiler cannot and will not treat p as an array. p is just a pointer to a char to which any address can be assigned. Why would the compiler treat it as an array?