Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question on "range-for-statement"

46 views
Skip to first unread message

Joseph Hesse

unread,
Oct 3, 2019, 10:04:06 AM10/3/19
to
I am puzzled how the following program works.

=====================================================
#include <iostream>
using namespace std;

int main()
{
char x[] = {"Hello"}; // x is a 0 terminated character array

for(const auto &i : x)
cout << i << " ";

cout << "\n";
}
=====================================================

Putting a 0 at the end of a character array to indicate the end is a
convention and not part of the language. There are library functions
that understand this convention but the library is not part of the
language definition.

How does the range-for-statement, which is a language construct, know
that it has to stop when it sees a 0?

Thank you,
Joe

Paavo Helde

unread,
Oct 3, 2019, 10:12:45 AM10/3/19
to
It doesn't know and it doesn't stop at any zero byte. Instead, it knows
the size of the x array.

#include <iostream>
using namespace std;

int main()
{
char x[] = { "Hello\0\0World" };

for (const auto &i : x)
cout << int(i) << " ";

cout << "\n";
}


72 101 108 108 111 0 0 87 111 114 108 100 0


Keith Thompson

unread,
Oct 3, 2019, 1:21:50 PM10/3/19
to
It doesn't. When I compile and run your program, the output *looks
like*

H e l l o

but in fact it prints the null character:

./c | cat -A
H e l l o ^@ $

As Paavo Helde correctly states, it knows the size of the array, not the
length of the string contained in the array.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Jorgen Grahn

unread,
Oct 3, 2019, 3:00:52 PM10/3/19
to
On Thu, 2019-10-03, Joseph Hesse wrote:
...
> Putting a 0 at the end of a character array to indicate the end is a
> convention and not part of the language. There are library functions
> that understand this convention but the library is not part of the
> language definition.

Why do people keep saying that? The standard library is part of the
language.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

unread,
Oct 3, 2019, 5:49:58 PM10/3/19
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
> On Thu, 2019-10-03, Joseph Hesse wrote:
> ...
>> Putting a 0 at the end of a character array to indicate the end is a
>> convention and not part of the language. There are library functions
>> that understand this convention but the library is not part of the
>> language definition.
>
> Why do people keep saying that? The standard library is part of the
> language.

The word "language" is, dare I say it, overloaded.

For example, in the ISO C standard section 6 is titled "Language"
and section 7 is "Library".

The C++ standard doesn't have the same division (at least not as
clearly), but the same logic could apply.

Having said that, the "language" and the "library" are both specified
by the same standard, and it's also reasonable to refer to the
whole thing as the "language". (I'll also note that most of the
library is optional for freestanding implementations.)

Juha Nieminen

unread,
Oct 4, 2019, 2:54:50 PM10/4/19
to
Joseph Hesse <jo...@gmail.com> wrote:
> char x[] = {"Hello"}; // x is a 0 terminated character array

To give a slightly different answer as others, which might give
some insight, please note that

char x[] = "Hello";

is a rather different thing than

char* x = "Hello";

(Technically that's not completely kosher because it should be
a const pointer, but that's not really the point.)

The former is a built-in array, which is being initialized with
the values in that string literal. The latter is a char pointer
that's initialized to point to that string literal.

Normally built-in arrays (which don't have a specified size
inside the brackets) would be initialized like:

int x[] = { 1, 2, 3, 4 };

That would be a built-in array with 4 elements.

There exists, however, a special syntax for char arrays, which
allows them to be initialized (and their size determined) with
a string literal:

char x[] = "Hello";

This is syntactic sugar that's equivalent to:

char x[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

When you create a range-based for using that array, it will
see that it's an array of 6 elements, and will iterate through
those 6 elements.

Joseph Hesse

unread,
Oct 13, 2019, 10:34:12 AM10/13/19
to
This is similar to my last post.
How can one put a "range based for loop" for a built in array type
inside a function? The following program will not compile to an object
file.

#include <iostream>
using namespace std;

void func(int a[])
{
for(const auto &i : a)
cout << i << endl;
}

Chris Vine

unread,
Oct 13, 2019, 11:12:09 AM10/13/19
to
On Sun, 13 Oct 2019 09:33:56 -0500
Joseph Hesse <jo...@gmail.com> wrote:
> This is similar to my last post.
> How can one put a "range based for loop" for a built in array type
> inside a function? The following program will not compile to an object
> file.
>
> #include <iostream>
> using namespace std;
>
> void func(int a[])
> {
> for(const auto &i : a)
> cout << i << endl;
> }

You have to prevent pointer decay so as enable the array to retain its
size. One way to do that is to take the array as a reference so that
the size remains part of its type:

void func(int (&a)[5]) {
for(const auto &i : a)
cout << i << endl;
}

Another way is to use std::array, which has its size as its second
template parameter.

Bonita Montero

unread,
Oct 14, 2019, 1:53:35 PM10/14/19
to
>   for(const auto &i : x)
>     cout << i << " ";

I think auto shold be used only when really needed, f.e. when x would be
a templated object whose iterators reference a "dyamic" type. But in the
upper case the code simply becomes less readable.

0 new messages