I made a array of words and made a function to return a random word from the array. But it shows this error -
hangman.cpp: In function 'std::__cxx11::string get_random_word(std::__cxx11::string*)':
hangman.cpp:17:33: warning: 'sizeof' on array function parameter 'words' will return size of 'std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}' [-Wsizeof-array-argument]
size_t length = sizeof(words) / sizeof(words[0]);
^
hangman.cpp:15:47: note: declared here
std::string get_random_word(std::string words[])
^
Here is the code -
#include <iostream>
#include <string>
#include <ctime>
std::string get_random_word(std::string words[]);
int main()
{
srand(time(0));
std::string words[] = {"cpp", "python", "java"};
std::cout << get_random_word(words);
return 0;
}
std::string get_random_word(std::string words[])
{
size_t length = sizeof(words) / sizeof(words[0]);
return words[rand() % length];
}
CodePudding user response:
It's not an error but a very important warning and you are not calculating the correct thing so the program will unlikely do what you intended it to do.
When you pass an array as argument to a function, there is something called decay. The whole array decays into a pointer to the first element in the array. If you've never heard about this before - keep it in mind.
I'll rewrite your code as it will be interpreted by the compiler in broad strokes:
// note, this one pointer - it has but one sizeof
std::string get_random_word(std::string* words) {
// sizeof(words) has the same value no matter
// how many "words" you have in the array:
size_t length = sizeof(words) / sizeof(words);
return words[rand() % length];
}
When re-written like I did it above it becomes a bit more clear that sizeof(words)
won't work. The size of a pointer will be the same (on one platform) even if what it is pointing at occupies a lot of space. A pointer is only ever a pointer to one element. It is the only element - or the first element in an array of elements.
A common C solution is to pass around references to std::vector
s, like std::vector<std::string>
. With that, you can get the size and a lot more.
CodePudding user response:
The sizeof
operator may not be doing exactly what you think. According to cppreference: (sizeof
) Yields the size in bytes of the object representation of type. This may include any internal members needed for the class, and not just how many characters are used in the string for example. std::string has the size()
and length()
functions for this, which are the same, and instead of using an array you can use a vector that also provides a size()
function.
#include <iostream>
#include <string>
#include <ctime>
#include <vector>
std::string get_random_word(std::vector<std::string>& words)
{
return words[rand() % words.size()];
}
int main()
{
srand(time(0));
std::vector<std::string> words = {"cpp", "python", "java"};
std::cout << get_random_word(words);
return 0;
}