How to initialize a char*?

I

Ioannis Vranos

Sam Holden said:
Because the const-ness is incorrect.

"char * &" is not the same as "char * const &".


In the case of a const char * &, a temporary char * is created and the
reference points to that untill the end of the function call.






Ioannis Vranos
 
I

Ioannis Vranos

Kevin Goodsell said:
I'd be happy to clarify if you'll tell me which part you have a problem
with. I did already go over this in a bit more detail elsewhere in the
thread (in another reply to you, I believe), so you might check there
first.


char *s="whatever"; is not an error and i don't think any copiler exists
that ould give a warning about this. If it did, we would get thousands of
warnings in cases like this:



void whatever(char *);


/// ...

// We would get a warning
whatever("something")'


whatever( something_else() );


Even strcpy() family for example would give warnings in the case:


strcpy(destination, "something");

If you want to check the standard you can find this in D.4
[depr.string]. There's also information in 4.2/2 [conv.array]. Finally,
2.13.4 explicitly states that string literals consist of const
characters, and I know it's stated somewhere that modifying const
objects gives undefined behavior, but I'm not sure where to look.


Yes noone suggested modify string literals.


Failing to initialize in itself is not an error. But using the
uninitialized value is undefined behavior.


My point is that using an object by mistake in a way not intended to will
invoke undefined behaviour anyway. Premature initialisation does not protect
us from any of our mistakes. E.g.



#include <cstddef>
#include <iostream>


// Returns the length of the string, '\0' not included
inline std::size_t slength(char *array)
{
char *p;

// To avoid any questions, '\0'==0
for(p=array; *p; ++p)
;

return p-array;
}


int main()
{
using namespace std;

// Happily initialised
char *p=0;

cout<<endl<<slength("Pinky & the Brain")<<endl;

cout<<"\nPinky we are now protected, right?\n";

cout<<endl<<slength(p)<<endl;
}






Ioannis Vranos
 
I

Ioannis Vranos

Ioannis Vranos said:
I do not think it is. You can take references from pointers only in
templates. Even in this case passing an unitialised char * would not have
any bad effect by its own.


My above response is erroneus. Noone really knows what i had in my mind. It
was after 3 a.m. ... :)






Ioannis Vranos
 
K

Kevin Goodsell

Christopher said:
There are better alternatives, I'm sure, but IMHO the following is
"useful":

const char * const err_string = "Error: " __FILE__ " " __LINE__;

I meant that it's probably not useful in this particular case, which I
base on the idea that the OP apparently used it for the sole purpose of
quieting a warning. In general, string literals and pointers to them
could be useful for any number of purposes, but not as a general
catch-all char pointer initializer (such as the way 0 is sometimes used
for various types).

-Kevin
 
K

Kevin Goodsell

Ioannis said:
char *s="whatever"; is not an error and i don't think any copiler exists
that ould give a warning about this. If it did, we would get thousands of
warnings in cases like this:

It's not (strictly speaking) an error, but it does use a deprecated and
unsafe conversion. My compiler warns about it, because I ask it to.
void whatever(char *);


/// ...

// We would get a warning
whatever("something")'

A warning here is completely appropriate, in my opinion. You would
expect a diagnostic if you did this, wouldn't you?

const char example[] = "something";
whatever(example);

The key point here is that both calls, your example and mine, pass an
object of exactly the same type. Your example may or may not give a
warning, but in my opinion it's best if it does. My example requires a
diagnostic. Both (if allowed) are unsafe in exactly the same way. That
being that whatever() may do something like this:

void whatever(char *p)
{
*p = '\0';
}

If, on the other hand, whatever() is not intended to modify the thing
its parameter points to, it should be declared like this:

void whatever(const char *p);

Now both examples are safe and silent.
whatever( something_else() );


Even strcpy() family for example would give warnings in the case:


strcpy(destination, "something");

No, because the second parameter has type const char *.
If you want to check the standard you can find this in D.4
[depr.string]. There's also information in 4.2/2 [conv.array]. Finally,
2.13.4 explicitly states that string literals consist of const
characters, and I know it's stated somewhere that modifying const
objects gives undefined behavior, but I'm not sure where to look.



Yes noone suggested modify string literals.

But making use of the deprecated conversion from a string literal to a
(non-const) char* allows code that does exactly that, without the
compiler being able to catch and diagnose it. This (and future
compatibility) is why you should not use this conversion.
My point is that using an object by mistake in a way not intended to will
invoke undefined behaviour anyway. Premature initialisation does not protect
us from any of our mistakes. E.g.

I wasn't advocating an "always initialize, even if the value is not
meaningful" policy, just stating the facts as giving by the language
definition.

My personal preference is to always initialize, but do so at the point
the object is needed, not before. In other words, don't create an object
(initialized or otherwise) until you need it, then create and initialize
at the same time.

-Kevin
 
I

Ioannis Vranos

Kevin Goodsell said:
void whatever(char *);


/// ...

// We would get a warning
whatever("something")'

A warning here is completely appropriate, in my opinion. You would
expect a diagnostic if you did this, wouldn't you?

const char example[] = "something";
whatever(example);

The key point here is that both calls, your example and mine, pass an
object of exactly the same type. Your example may or may not give a
warning, but in my opinion it's best if it does. My example requires a
diagnostic. Both (if allowed) are unsafe in exactly the same way. That
being that whatever() may do something like this:

void whatever(char *p)
{
*p = '\0';
}

If, on the other hand, whatever() is not intended to modify the thing
its parameter points to, it should be declared like this:

void whatever(const char *p);

Now both examples are safe and silent.


Yes you are right.


My personal preference is to always initialize, but do so at the point
the object is needed, not before. In other words, don't create an object
(initialized or otherwise) until you need it, then create and initialize
at the same time.


As i have told before these are "religious waters". For example there are
coders out there who like to put the object definitions in the beginning,
because if they want to find an object definition they wouldn't have to
search the entire code.


In any case, premature initialisation in particular (that is giving a value
not intended to be used in the program), does not protect the programmer
from any disaster.






Ioannis Vranos
 
K

Kevin Goodsell

Ioannis said:
As i have told before these are "religious waters". For example there are
coders out there who like to put the object definitions in the beginning,
because if they want to find an object definition they wouldn't have to
search the entire code.

I thought it was because they were weaned on C90. :p

Seriously, declarations should not need to be placed in a particular
location in order for them to be easy to locate. Perhaps some of these
people need to write shorter subroutines.

-Kevin
 
K

Kevin Goodsell

Kevin said:
I thought it was because they were weaned on C90. :p

Or earlier, even. Being a fledgling myself I sometimes forget that
people were programming before 1990. ;)

-Kevin
 
I

Ioannis Vranos

Kevin Goodsell said:
I thought it was because they were weaned on C90. :p

Seriously, declarations should not need to be placed in a particular
location in order for them to be easy to locate. Perhaps some of these
people need to write shorter subroutines.


Seriously i agree with you. Objects should be created only at the time we
first need them.






Ioannis Vranos
 
I

Ioannis Vranos

Ioannis Vranos said:
Seriously i agree with you. Objects should be created only at the time we
first need them.


Well i guess those who talk about "premature initialisation" are a subset of
that kind of people (who like to define everything in the beginning of the
scope).






Ioannis Vranos
 
M

marbac

Peter said:
Hi,

So many times, I have seen compile warning: "you used a char* without
initilize it", probably on the code like this:

------------
char* ptr;

func(..., ptr);
----------

char *ptr is a flying pointer which points to nowhere.
If the compiler does not fetch it, it will lead to a runtime error.
How to properly initialize a char*? I used to use

char* ptr = "";

but was told this is not good.

This is a char-pointer to an empty array of chars (/0) , when i don't
know if a char-pointer will be redirected to a char [] then i also would
do it this way. But i recommend to use string.h for string-operations.
Can anybody explain to me why, and what's a good way to initilize it?

I only can tell you what i usually do with pointers, if i am not sure:

type *ptr=NULL; // flying pointer assigned to NULL-pointer

then i can check if the pointer points to NULL (NULL-pointer ... not
assigned to valid data yet)

if (ptr!=NULL) do_something (ptr);
else cerr_something_and_exit ();

But this should not be the standard method for pointers
 
M

Michiel Salters

Christopher Benson-Manica said:
There are better alternatives, I'm sure, but IMHO the following is
"useful":

const char * const err_string = "Error: " __FILE__ " " __LINE__;

Eh? __LINE__ expands to an integer, IIRC so you get something like
"Error: ""foo.cpp"" "42; which is illegal. Besides, the __LINE__
is taken from the definition of err_string, not where it's used,
which won't tell you much.

Regards,
Michiel Salters
 
M

Michiel Salters

Ioannis Vranos said:
To make long things short, initialization doesn't protect you from anything.
The only thing that it could "protect you" in theory is in the call of
delete/delete[] family to an ititialised-to-0 pointer. In reality however
such a call occurs at the end of a process and you will have done more
things previously by mistake on that 0 initialised pointer (e.g.
dereferencing it) that would be equally disastrous/undefined.

Initialisation does not protect you from any mistake.

A well-known idiom for pointer use is :
if ( pFoo ) pFoo->doIt();

which relies heavily on default initialization to 0. The point of
the idiom is that there is a sensible default, don't call doIt(),
which is used when pFoo is the null pointer. You can't test
if (pFoo is initialised ) pFoo->doIt; // syntax error.

Regards,
Michiel Salters
 
I

Ioannis Vranos

Michiel Salters said:
"Ioannis Vranos" <[email protected]> wrote in message
To make long things short, initialization doesn't protect you from anything.
The only thing that it could "protect you" in theory is in the call of
delete/delete[] family to an ititialised-to-0 pointer. In reality however
such a call occurs at the end of a process and you will have done more
things previously by mistake on that 0 initialised pointer (e.g.
dereferencing it) that would be equally disastrous/undefined.

Initialisation does not protect you from any mistake.

A well-known idiom for pointer use is :
if ( pFoo ) pFoo->doIt();

which relies heavily on default initialization to 0. The point of
the idiom is that there is a sensible default, don't call doIt(),
which is used when pFoo is the null pointer. You can't test
if (pFoo is initialised ) pFoo->doIt; // syntax error.


We can't tell that this is "premature initialisation" and that
initialisation does not protect you from any mistakes, that is
initialisation with a value which is actively used.






Ioannis Vranos
 
C

Christopher Benson-Manica

Michiel Salters said:
Eh? __LINE__ expands to an integer, IIRC so you get something like
"Error: ""foo.cpp"" "42; which is illegal. Besides, the __LINE__
is taken from the definition of err_string, not where it's used,
which won't tell you much.

I disagree with your assessment - the errors you listed were worthy of
at least three question marks, i.e. "Eh?????". Well, yikes. Thanks...
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top