2

I am new to C++, I know that character arrays/char*(c-strings) terminate with a Null byte, but is it the same for string arrays/char**?

My main question is: how can i know if I reached the end of a char** variable? Will the following code work?

#include <cstddef>

char** myArray={"Hello", "World"};

for(char** str = myArray; *str != NULL; str++) {
  //do Something
}

2 Answers 2

3

For starters this declaration

char** myArray={"Hello", "World"};

does not make a sense, You may not initialize a scalar object with a braced-list with more than one expression.

It seems you mean a declaration of an array

const char* myArray[] ={ "Hello", "World"};

In this case the for loop can look like

for( const char** str = myArray; *str != NULL; str++) {
  //do Something
}

But the array does not have an element with a sentinel value. So this condition in the for loop

*str != NULL

results in undefined behavior.

You could rewrite the loop for example like

for( const char** str = myArray; str != myArray + sizeof( myArray ) / sizeof( *myArray ); str++) {
  //do Something
}

Or instead of the expression with the sizeof operator you could use the standard function std::size introduced in the C++ 17 Standard.

Otherwise the initial loop would be correct if the array is declared like

const char* myArray[] ={ "Hello", "World", nullptr };

In this case the third element will satisfy the condition of the loop.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer, would sizeof or std::size work inside a function? I heard that when you pass the variable in a function the sizeof doesn't work, is that correct?
@PTorPro If you will pass the array by reference then it will work. Otherwise the array designator will be converted to a pointer to its first element. In this case you need also to pass the number of elements in the array. Or append the array with the sentinel value nullptr. as it was already pointed.
3

You need to terminate it:

const char** myArray={"Hello", "World", nullptr};

As you should be using nullptr in C++, not NULL which is for C code.

Additionally, use std::vector and std::string instead of this mess:

std::vector<std::string> myArray = { "Hello", "World" };

for (auto&& str : myArray) {
  // ... str is your string reference
} 

8 Comments

std::array is better adapted for this than std::vector.
@FrançoisAndrieux Why? It's an academic distinction. 99% of the time std::vector is totally fine. This isn't performance critical code, and it's not hitting any memory limits.
The size is compile-time constant. std::vector adds a dynamic allocation and size mutability.
It isn't any more premature optimization than using const reference arguments to avoid copies. This is using the tool for the job it was designed for... std::array better expresses the intent.
There are a lot of thing in that "quote" that don't reflect anything I said, or propose saying. I don't think std::vector is wrong here, and I accordingly didn't downvote. But std::array is a simple improvement that I would have thought would be uncontroversial. I agree that it may be best to limit the number of containers a beginner should be exposed to, but std::array doesn't seem so complex or arcane that it is something that beginners should be shielded from. But this is your answer, use what you want.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.