C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

char[] and char*

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Neelesh
Guest





PostPosted: Mon Oct 24, 2005 4:42 pm    Post subject: char[] and char* Reply with quote



A strange problem here -

/*******************************************/
/* file foo.cc */

extern char test[] = "helloworld";

/*********************************************/
/* file bar.cc */

#include <iostream>

extern char* test; /* this line will be commented later. */
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/

This code compiles without any problem but on running it gives
segmentation fault. Why so?
I remember reading that "there is no implicit or explicit conversion
possible from pointer to an array" - but I doubt whether that has
anything to do here even remotely - and if so, then why doesnot the
compiler issue a warning?

Further, uncommenting the second declaration and commenting the first
one makes the program behave properly.

Is there any explanation for this behavior?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Neelesh
Guest





PostPosted: Mon Oct 24, 2005 9:21 pm    Post subject: Re: char[] and char* Reply with quote



OOPS, Extremely Sorry, I have added an unnecessary extern here -

Neelesh wrote:

Quote:
A strange problem here -

/*******************************************/
/* file foo.cc */

/*extern */ char test[] = "helloworld";



Please consider this extern as being removed.
Me stupid :-(


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Hyman Rosen
Guest





PostPosted: Mon Oct 24, 2005 9:24 pm    Post subject: Re: char[] and char* Reply with quote



Neelesh wrote:

Quote:
/* file foo.cc */
extern char test[] = "helloworld";
/* file bar.cc */
extern char* test;
This code compiles without any problem but on running it gives
segmentation fault. Why so?


Because your program violates the requirements of 3.5/10:
...the types specified by all declarations referring
to a given object or function shall be identical...
A violation of this rule on type identity does not
require a diagnostic.
Therefore your program has undefined behavior.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Jack Klein
Guest





PostPosted: Mon Oct 24, 2005 10:59 pm    Post subject: Re: char[] and char* Reply with quote

On 24 Oct 2005 12:42:48 -0400, "Neelesh" <neelesh.bodas (AT) gmail (DOT) com>
wrote in comp.lang.c++.moderated:

Quote:
A strange problem here -

/*******************************************/
/* file foo.cc */

extern char test[] = "helloworld";

OK, 'test' is an array of 11 mutable characters (don't forget the
terminating '') with external linkage.

Now let's add:

extern char *test_ptr = test;

'test_ptr' is a pointer to char, and it happens to point to the first
character in 'test[]'.

Note that 'test' and 'test_ptr' are two different things, one an array
of characters and the other a pointer to char. If you put a function
in this source code file like this (with proper header inclusion):

void show_me()
{
std::cout << "sizeof test is " << sizeof test << 'n'
<< "sizeof test_ptr is " << sizeof test_ptr << std::endl;
}

....and called this function from main(), you would see one of the
differences.

Quote:
/*********************************************/
/* file bar.cc */

#include
extern char* test; /* this line will be commented later. */

Here you are telling the compiler that somewhere a pointer to char
named 'test' will be provided. But you are lying to the compiler,
'test' is not any sort of pointer, it is an array of characters.

Replace this with:

extern char *test_ptr;

....then you won't be lying to the compiler.

Quote:
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/

This code compiles without any problem but on running it gives
segmentation fault. Why so?

Because you lied to your compiler. You told it that 'test' is a
pointer to char, but it is not. Your compiler trued to use 'test' as
though it was a pointer to char. So now you know what can happen when
you lie to your compiler.

Quote:
I remember reading that "there is no implicit or explicit conversion
possible from pointer to an array" - but I doubt whether that has
anything to do here even remotely - and if so, then why doesnot the
compiler issue a warning?

There is an implicit conversion from the name of an array to a pointer
to its first element. This occurs in all contexts where the name of
an array is used with the exception of using the address-of (&) and
sizeof operators.

But your compiler can only perform this implicit conversion if it
knows that the identifier is the name of an array. You lied to it and
said that 'test' was not the name of an array, do it did not perform
the automatic conversion.

As for why the compiler does not issue a warning, you have produced
undefined behavior, and the C++ standard does not require that a
compiler diagnose or even recognize undefined behavior. In many
cases, it is not even possible to recognize undefined behavior at
compile time, because it is caused by something that happens at run
time.

Do you expect the compiler to be able to read your mind when it is
compiling bar.cc and know that you have, intentionally or
accidentally, declared 'test' incorrectly? The compiler deals with
one source code file at a time. It does not know that later on you
are going to link bar.cc with foo.cc.

Quote:
Further, uncommenting the second declaration and commenting the first
one makes the program behave properly.

Yes, now you are telling the compiler the truth, that 'test' is the
name of an array of characters. So it performs the proper conversion
and everything works.

Quote:
Is there any explanation for this behavior?

There is no real explanation for the behavior, because the C++
standard does not impose any requirements at all when undefined
behavior is produced.

But there is an explanation for the underlying cause. The C++
standard requires that the definition and declaration for objects
match. A pointer is not an array, an array is not a pointer.

The proper way to do this, so the compiler will catch the mistake, is
to create a header file, say test.h:

extern char test[];

Include this header file in foo.cc. Also include it in bar.cc, and
remove the external declaration already in bar.cc. Then if either the
definition of 'test' in foo.cc, or its usage in bar.cc, does not match
the declaration in the header, the compiler will issue a diagnostic.

Use of the 'extern' keyword in a source file is almost always a
mistake in C++. The only exception is when defining a file-scope
constant in one source file that you want to be accessible from other
source files, because C++ gives file-scope and namespace-scope
constants internal linkage by default.

Even then, the 'extern' keyword should only appear on the definition
of the const item. Other source files that reference it should see
its declaration in a header file that is also included by the defining
source file.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Pete Becker
Guest





PostPosted: Tue Oct 25, 2005 9:58 am    Post subject: Re: char[] and char* Reply with quote

Neelesh wrote:
Quote:

Further, uncommenting the second declaration and commenting the first
one makes the program behave properly.

Is there any explanation for this behavior?


An array is not a pointer. When you define test as an array in one
source file and declare it as a pointer in another you're lying to the
compiler. When you change the declaration to the correct type it works.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
wade@stoner.com
Guest





PostPosted: Tue Oct 25, 2005 9:59 am    Post subject: Re: char[] and char* Reply with quote


Neelesh wrote:
Quote:
A strange problem here -

/*******************************************/
/* file foo.cc */

extern char test[] = "helloworld";

/*********************************************/
/* file bar.cc */

#include
extern char* test; /* this line will be commented later. */
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/
... compiles without any problem but on running it gives
segmentation fault. Why so? ...

One declaration of test says char*. Another says char[]. 3.5/10 says
that all of the declarations need to be [almost] identical. No
diagnostic is required when the conflict is in different translation
units.

I suggest you put the declaration into an include file (foo.h), and use
the include file in both bar.cc and foo.cc. If the body of either
foo.cc or bar.cc (or both) was inconsistent with foo.h, you would get a
compile-time diagnostic. This isn't foolproof but it helps.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Antoun Kanawati
Guest





PostPosted: Tue Oct 25, 2005 12:46 pm    Post subject: Re: char[] and char* Reply with quote

Neelesh wrote:
Quote:
A strange problem here -

/*******************************************/
/* file foo.cc */

extern char test[] = "helloworld";

/*********************************************/
/* file bar.cc */

#include <iostream

extern char* test; /* this line will be commented later. */
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/

This code compiles without any problem but on running it gives
segmentation fault. Why so?

This is because you're declaring one thing, and defining another.

The "char*" form creates the following

test +----------------+
Quote:
SOME ADDRESS |---> ['h', 'e', 'l', ...., 0]
+----------------+



Whereas the "char[]" has the following form:

test +----------------------------+
Quote:
'h', 'e', 'l', 'l', ..., 0 |
+----------------------------+



So, in the program you show above, the mismatch between the types
leads your program to interpret the bit pattern representing the
characters 'hello...' as a pointer. Luckily, this particular
combination is not a valid address in your program, and the error is
observed as a segv.

--
A. Kanawati

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Carlos Moreno
Guest





PostPosted: Tue Oct 25, 2005 12:49 pm    Post subject: Re: char[] and char* Reply with quote

Neelesh wrote:
Quote:
A strange problem here -

/*******************************************/
/* file foo.cc */

extern char test[] = "helloworld";

/*********************************************/
/* file bar.cc */

#include
extern char* test; /* this line will be commented later. */
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/

This code compiles without any problem but on running it gives
segmentation fault. Why so?

Because you're lying to the compiler. Blatantly lying :-)

You're telling it that test is a pointer that is declared
in an external file -- which is not true.

You're being misled by the fact that implicit conversion
from char[] to char * is allowed -- but the compiler needs
to *know* that something is a char[] to *know that it has
to do* the implicit conversion. Otherwise, it thinks that
no implicit conversion is required.

A description of what's happening at CPU-level is more or
less as follows: you're telling the compiler that the
symbol test represents a variable (somewhere in memory)
that is storing a pointer. The compiler, once it resolved
the symbol test and knows the memory address where the
symbol is, it goes to that memory location to read the
4 bytes that indicate the memory address where the actual
string is (you know, because it is a pointer); but when
it goes to that memory location, it's not going to find
a pointer -- it's going to find "hell" -- *literally*!!
(wow!!! Beautiful example you chose!! My God, I don't
believe I've seen such a beautiful play on words come out
of a bug in a program!!! Smile)

When it tries to go to that location pointed by the
32-bits represented by h-e-l-l, you get your segmentation
fault.

If you tell the compiler the truth -- that test is the
memory address where an array of characters is found, and
not a pointer to the array of characters, then the compiler
knows what to do -- and it does the right thing.

Quote:
anything to do here even remotely - and if so, then why doesnot the
compiler issue a warning?

It can't. The linker is the one that resolves symbols, but
at that point, the symbols are type-less. (hmmm, experts
out there, correct me if I'm wrong here)

HTH,

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Krakers
Guest





PostPosted: Tue Oct 25, 2005 2:09 pm    Post subject: Re: char[] and char* Reply with quote

"Neelesh" wrote...

Quote:
A strange problem here -
extern char test[] = "helloworld"; // in one file
extern char* test; // in another

int main() { std::cout << test << std:: endl; }

This code compiles without any problem but on running it gives
segmentation fault. Why so?

The actual global variable is an 11-character table. An attempt
to interprete this memory space as a pointer and dereference
it leads to undefined behaviour. You can try this to see more
exactly what happens:
printf("Pointer value = %pn", test);

What is actually surprizing is that the linker does not report
an error. I tried Visual C++ and it links without an error in this
case. It does show an error when mixing int* and char* types.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Howard Lee Harkness
Guest





PostPosted: Wed Oct 26, 2005 1:19 pm    Post subject: Re: char[] and char* Reply with quote

"Neelesh" <neelesh.bodas (AT) gmail (DOT) com> wrote:

Quote:
extern char* test; /* this line will be commented later. */
// extern char test[]; /* this line will be uncommented later. */

int main()
{
std::cout << test << std:: endl;
}

/**********************************************/

This code compiles without any problem but on running it gives
segmentation fault. Why so?

The problem is the difference between an array and a pointer. While C++ allows
similar syntax for both (a language design error dating back to K&R C), they are
not the same.

A pointer is a variable which can hold the address of another variable. The
contents of a pointer may be changed. A pointer actually occupies a location in
the program memory. A pointer must be initialized before use -- and it has to
point to something that is properly allocated.

An array name is essentially just an entry in the compiler's symbol table. It
doesn't occupy a location, and the contents of that symbol table entry can't be
changed. That symbol table entry is the address of a block of storage which
can't move.

In some circumstances, array syntax may be used on a pointer, and vice versa.
However, it's not good practice (it amounts to lying to the compiler, which can
cause very difficult-to-find errors), and you can run into exactly the sort of
problem you are having here. In general, arrays are problematic in C++ for this
as well as for other reasons.

For that matter, pointers have their own problems, but that's a whole 'nother
thread.
--
Howard Lee Harkness, http://www.Celtic-Fiddler.com
My violins are finally in and ready to sell! See
my website for pictures and details.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.