different results for C/C++ compiler

V

Vols

char s[7] = "1234567";

when we use C compiler (gcc), it works fine.
An error is reported if using C++ compiler (g++).

any story for this one?

Vol
 
J

jacob navia

Vols said:
char s[7] = "1234567";

This is an error since you do not
end the array with zero You put 7
chars, in a 7 position array, then the string
is not zero terminated.

legal in C, illegal in C++.
 
V

Vols

The reason I asked this question is: why is it legal in C?
So we don't need to end with '0' in C?
Thanks.

Vol


Vols said:
char s[7] = "1234567";
when we use C compiler (gcc), it works fine.
An error is reported if using C++ compiler (g++).
any story for this one?

Too many initialisers. In C++, the array is initialised from the
array that is the string literal. The string literal "1234567" has
8 (eight) characters in it, the numbers and the terminating zero.
C++ does not allow to provide more initialisers to array elements
than the array size. Drop the size, just do

char s[] = "1234567";

or change it to 8.

V
 
J

Joe Greer

The reason I asked this question is: why is it legal in C?
So we don't need to end with '0' in C?
Thanks.

C is not nearly as strongly typed as C++ and therefore allows a bit more
sloppyness/or is a bit more tolerant depending on your POV.

joe
 
F

fred.l.kleinschmidt

The reason I asked this question is: why is it legal in C?
So we don't need to end with '0' in C?
Thanks.

Vol

Vols said:
char s[7] = "1234567";
when we use C compiler (gcc), it works fine.
An error is reported if using C++ compiler (g++).
any story for this one?
Too many initialisers.  In C++, the array is initialised from the
array that is the string literal.  The string literal "1234567" has
8 (eight) characters in it, the numbers and the terminating zero.
C++ does not allow to provide more initialisers to array elements
than the array size.   Drop the size, just do
    char s[] = "1234567";
or change it to 8.

- Show quoted text -

An array in C need not be terminated with a NUL character.
Such an array is not considered to be a string unless it is
NUL terminated.

Most C library functions (strxxx, printf, etc.) expect
their char* arguments to be strings.
 
J

Joe Greer

(e-mail address removed) wrote in

An array in C need not be terminated with a NUL character.
Such an array is not considered to be a string unless it is
NUL terminated.

Most C library functions (strxxx, printf, etc.) expect
their char* arguments to be strings.

I think it's less to do with the null and arrays than with the fact that in
C++

"Hello" is of type char const[6]

and trying to assign that to a char[5] will fail. (There is a special rule
to get around the constness problem, but not the size problem.)

Of course, I am not really a language lawyer type, so I could be off base,
but that is what I think is happening.

joe
 
D

Default User

Joe said:
(e-mail address removed) wrote in
:
An array in C need not be terminated with a NUL character.
Such an array is not considered to be a string unless it is
NUL terminated.

Most C library functions (strxxx, printf, etc.) expect
their char* arguments to be strings.

I think it's less to do with the null and arrays than with the fact
that in C++

"Hello" is of type char const[6]

and trying to assign that to a char[5] will fail. (There is a
special rule to get around the constness problem, but not the size
problem.)

No, it doesn't. There's no assignment going on. You can't assign to an
array. The string literal is an initializer.

The rules for C allow that initialization, the rules of C++ don't.



Brian
 
D

Default User

Victor said:
Vols said:
char s[7] = "1234567";

when we use C compiler (gcc), it works fine.
An error is reported if using C++ compiler (g++).

any story for this one?

Too many initialisers. In C++, the array is initialised from the
array that is the string literal. The string literal "1234567" has
8 (eight) characters in it, the numbers and the terminating zero.
C++ does not allow to provide more initialisers to array elements
than the array size. Drop the size, just do

char s[] = "1234567";

or change it to 8.

And for why in C, it's allowed by the Standard. The following is from
the C99 draft:

6.7.8 Initialization

[#14] An array of character type may be initialized by a
character string literal, optionally enclosed in braces.
Successive characters of the character string literal
(including the terminating null character if there is room
or if the array is of unknown size) initialize the elements
of the array.

[#32] EXAMPLE 8 The declaration

char s[] = "abc", t[3] = "abc";

defines ``plain'' char array objects s and t whose elements
are initialized with character string literals. This
declaration is identical to

char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };



Brian
 
I

Ivan Vecerina

: The reason I asked this question is: why is it legal in C?
: So we don't need to end with '0' in C?
....
: > > char s[7] = "1234567";

I believe that it used to be illegal in C as well. This "feature"
may(?) have been added in the C99 revision of the C standard.

The point would have been that some embedded developers found
that the NUL char, when not needed, was wasting space (yes,
this can matter on chips with only few kilobytes of ram).

So if you want portable code with the NUL char,
you can just write:
char s[] = "1234567";

If you want portable code *without* the NUL,
you can write instead:
char s[7] = {'1','2','3','4','5','6','7'};
// can get cumbersome for large data tables...

The "in-between" style is to be avoided in portable code.
It just happens to be one of the (too many, some futile)
areas where the C and C++ standard have chosen different
routes...
 
J

Joe Greer

No, it doesn't. There's no assignment going on. You can't assign to an
array. The string literal is an initializer.

The rules for C allow that initialization, the rules of C++ don't.

Technically, of course you are correct, but that is entirely beside the
point. The type mismatch is still the problem.

joe
 
D

Default User

Joe said:
Technically, of course you are correct, but that is entirely beside
the point. The type mismatch is still the problem.

Sorry, but you don't know what you are talking about. The type of the
initializer has nothing to with it.





Brian
 
N

Nick Keighley

(e-mail address removed) wrote innews:1f8038bb-febb-41d9-8741-39be60486452@z24g2000prf.googlegroups.com:
An array in C need not be terminated with a NUL character.
Such an array is not considered to be a string unless it is
NUL terminated.
Most C library functions (strxxx, printf, etc.) expect
their char* arguments to be strings.

I think it's less to do with the null and arrays than with the fact that in
C++

"Hello" is of type char const[6]

and trying to assign that to a char[5] will fail.  (There is a special rule
to get around the constness problem, but not the size problem.)

Of course, I am not really a language lawyer type, so I could be off base,
but that is what I think is happening.

try this:

int main (void)
{
char s7[7] = "1234567";
char s8[8] = "1234567";
char s9[9] = "1234567";

return 0;
}

according to your logic s9[] will also give an error in C++.

The fact is this is an odd corner of C. I thing "sloppiness"
is the wrong term. I think this was intentional. I believe
Unix used to have some odd things that were arrays of chars
(or small numbers) of fixed size. They were not terminated
by a zero. C provided means to manipulate them like
strncpy() and the initialisation stuff above.
 
D

Default User

Nick said:
(e-mail address removed) wrote
in.com:
An array in C need not be terminated with a NUL character.
Such an array is not considered to be a string unless it is
NUL terminated.
Most C library functions (strxxx, printf, etc.) expect
their char* arguments to be strings.

I think it's less to do with the null and arrays than with the fact
that in C++

"Hello" is of type char const[6]

and trying to assign that to a char[5] will fail. (There is a
special rule to get around the constness problem, but not the size
problem.)

Of course, I am not really a language lawyer type, so I could be
off base, but that is what I think is happening.

try this:

int main (void)
{
char s7[7] = "1234567";
char s8[8] = "1234567";
char s9[9] = "1234567";

return 0;
}
according to your logic s9[] will also give an error in C++.

And this works in C:

int main (void)
{
const char s7[7] = "1234567";

return 0;
}

I don't follow at all what he thinks the type of the initalizer has to
do with anything.
The fact is this is an odd corner of C. I thing "sloppiness"
is the wrong term. I think this was intentional.

As it is specifically mentioned in the C standard, with an example, I
think "intentional" is accurate.




Brian
 
J

Joe Greer

And this works in C:

int main (void)
{
const char s7[7] = "1234567";

return 0;
}

I don't follow at all what he thinks the type of the initalizer has to
do with anything.

Well, apparently it doesn't have anything to do with it for char arrays.
Try initializing an object with the wrong type for most other things though
an you will have a problem. Anyway, I finally did what I should have done
to begin with and looked it up in the standard. In [dcl.init.string]/1-2
it says:

1. A char array (whether plain char, signed char, or unsigned char)
can be initialized by a stringliteral (optionally enclosed in
braces); a wchar_t array can be initialized by a wide stringliteral
(optionally enclosed in braces); successive characters of the
stringliteral initialize the members of the array.

[Example:
char msg[] = "Syntax error on line %s\n";
shows a character array whose members are initialized with a
stringliteral.
Note that because ’\n’ is a single character and because a trailing
’\0’ is appended, sizeof(msg) is 25. ]

2 There shall not be more initializers than there are array elements.
[Example:
char cv[4] = "asdf"; // error
is illformed since there is no space for the implied trailing ’\0’.
]

So, for whatever it's worth, they seem to consider a string literal to be
null terminated and refuse to let the compiler do the truncating for you.

joe
 
D

Default User

Joe said:
And this works in C:

int main (void)
{
const char s7[7] = "1234567";

return 0;
}

I don't follow at all what he thinks the type of the initalizer has
to do with anything.

Well, apparently it doesn't have anything to do with it for char
arrays.

Which is what we are discussing.
Try initializing an object with the wrong type for most
other things though an you will have a problem.

Really? Try this:

int main(void)
{
const int ci = 3;
int i = ci;
double d = ci;

return 0;
}

There's a wide variety of compatible types in initalization. Some are
not. You could NOT for instance do:

int main(void)
{
const int ci = 3;
double *d = &ci;

return 0;
}

Anyway, I finally
did what I should have done to begin with and looked it up in the
standard. In [dcl.init.string]/1-2 it says:
[snip]

So, for whatever it's worth, they seem to consider a string literal
to be null terminated and refuse to let the compiler do the
truncating for you.

In C++. Not in C, where it is specifically allowed. Nothing to do with
the type of a string literal, but rather the fact that it is a string
literal.

Are we clear now?




Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,490
Latest member
Finplus

Latest Threads

Top