How to initialize a char*?

D

DaKoadMunky

Can you provide a working example with a main() using such a function
accepting char * &?

A library function I developed dynamically allocated data which it then passed
to a callback. The callback had the option of assuming ownership of that
dynamically allocated data. The callback had an argument of type reference to
pointer to type T. If the callback wanted to assume ownership of the
dynamically allocated data it could do so by copying the referenced pointer and
then setting the referenced pointer to zero. The library would then attempt to
delete a null pointer, which of course is a safe operation. If the callback
did not want to assume ownership of the dynamically allocated data then it did
not modify the referenced pointer. In that case the library deleted the
dynamically allocated data.

typedef void (*DataUser)(char*&);

void DataCreator(DataUser dataUser)
{
char *data = new char(0);
dataUser(data);
delete data;
}

void DataUser1(char*& data)
{
//Make copy of data for later usage and deletion
data = 0;
}

void DataUser2(char*&)
{
}

int main()
{
DataCreator(DataUser1);
DataCreator(DataUser2);

return 0;
}
Brian F. Seaberg
Naperville, Illinois
Delray Beach, Florida
 
J

Julie

Ioannis said:
Ok, so zero-initialisation or any other "premature" initialisation does not
protect you from anything. Btw try using the new C++ casts instead (of
course avoid them completely if possible).

Regards,

Ioannis Vranos

How do you define when "premature" is "post-mature"?

The c-style cast was used for absolute simplicity, not as a model for casting.
 
I

Ioannis Vranos

Julie said:
Ioannis said:
Buster said:
Ioannis, post one that doesn't compile. Your problem is elsewhere.

void func(char * const input, int word_number, char * & ptr_to_word)
{
}

int main()
{
char array[]="b";

func("a",5, array);
}

Ioannis Vranos

Yes, your problem is elsewhere.

The function takes a reference argument of type char *, you are (attempting) to
pass a type of char[2].


A type of what?
Here is your hat and coat.


Check this out:


#include <iostream>


int main()
{
using namespace std;

char array[]="12345";

*array='X';

cout<<array<<endl;
}






Ioannis Vranos
 
I

Ioannis Vranos

DaKoadMunky said:
A library function I developed dynamically allocated data which it then passed
to a callback. The callback had the option of assuming ownership of that
dynamically allocated data. The callback had an argument of type reference to
pointer to type T. If the callback wanted to assume ownership of the
dynamically allocated data it could do so by copying the referenced pointer and
then setting the referenced pointer to zero. The library would then attempt to
delete a null pointer, which of course is a safe operation. If the callback
did not want to assume ownership of the dynamically allocated data then it did
not modify the referenced pointer. In that case the library deleted the
dynamically allocated data.

typedef void (*DataUser)(char*&);

void DataCreator(DataUser dataUser)
{
char *data = new char(0);
dataUser(data);
delete data;
}

void DataUser1(char*& data)
{
//Make copy of data for later usage and deletion
data = 0;
}

void DataUser2(char*&)
{
}

int main()
{
DataCreator(DataUser1);
DataCreator(DataUser2);

return 0;


Yes it works only for a straight char * pointer. Check this:


It doesn't compile:

void f (char * &) { }

int main ()
{
char c;
f (&c);
}



Yes i meant that we can't pass an object by using it's address directly as
in code:

void f(char * &x)
{
*x='a';
}


int main()
{
char c='a';

f(&c);
}

since there is not a real pointer object so it cannot assign a reference. I
was talking about convenience. I expressed myself erroneously, apologies it
is ~04:00 here...






Ioannis Vranos
 
I

Ioannis Vranos

Ioannis Vranos said:
Yes it works only for a straight char * pointer. Check this:


It doesn't compile:

void f (char * &) { }

int main ()
{
char c;
f (&c);
}



Yes i meant that we can't pass an object by using it's address directly as
in code:

void f(char * &x)
{
*x='a';
}


int main()
{
char c='a';

f(&c);
}

since there is not a real pointer object so it cannot assign a reference. I
was talking about convenience. I expressed myself erroneously, apologies it
is ~04:00 here...


which is obvious since i posted twice above. :)






Ioannis Vranos
 
I

Ioannis Vranos

Julie said:
How do you define when "premature" is "post-mature"?


"premature"=initial value not actually intended to be used.


Too tired, going off line now. Good day/night there.






Ioannis Vranos
 
B

Buster

Ioannis said:
But this doesn't compile:

void f (char * &) { }

int main ()
{
char c;
f (&c);
}

Of course not. What would it do if it did compile?
Modify the address of c?
 
S

Sam Holden

But this doesn't compile:

void f (char * &) { }

int main ()
{
char c;
f (&c);
}

Because the const-ness is incorrect.

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

Buster

Sam said:
Because the const-ness is incorrect.

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

Kind of. The type of "& c" is not "char * const &". In fact, "& c"
is an rvalue of type "char *". It is true that you can compile

void f (char * const &) { }

int main ()
{
char c;
f (& c);
}

This is because you can bind a const reference to an rvalue.
 
L

Leor Zolman

David said:
On Tue, 13 Apr 2004 15:47:58 -0700 in comp.lang.c++, Julie
Yes, my statement was directed at the 'evil' part -- there is nothing 'evil'
about it, it just has the potential to lead to undefined behavior.

This issue is covered in Marshall Cline's C++ FAQ. See the topic
"[6.14] What does the FAQ mean by "such-in-such is evil"?".
http://www.parashift.com/c++-faq-lite/

Thanks for pointing it out.

After reading, that section definitely comes off as infantile and
inappropriate. I'd much prefer a more precise (and less humanity-subjective)
term as 'evil'. But I didn't write that FAQ, nor have any plans to write one,
so MC is free to write what he wants. Regardless, that doesn't preclude me
from stating that 'evil' is a poor word choice when discussing programmatic
constructs and behaviors.

Probably a bit too late to derail the use of "evil" in this context. Herb
Sutter, Scott Meyers and others have pretty much blessed it and it is here
to stay. I think saying "X is evil" concisely and effectively conveys the
message "X is a legal syntactic construct that, IMHO, if not executed with
the utmost care bordering on radical paranoia, is about as likely as
anything else you can write in this language to lead you down the slippery
slope into deep doo-doo, and then make it very hard for you to slog your
way back out."
-leor
 
C

Christopher Benson-Manica

David Harmon said:
If so, it is an evil func. You can tell me which fatal error does it
have, buffer overflow, or thread-hostile static buffer, or dynamically
allocating memory that the caller will forget to free? It needs to be
rewritten to use std::string.

The point of all this pedantry was merely to identify what is legal,
not what is good practice.
 
O

Old Wolf

Peter said:
So many times, I have seen compile warning: "you used a char* without
initilize it",

This is the compiler being nice by telling you you have probably made
a logic error in your program. You should fix your program, instead of
trying to shut the compiler up.
probably on the code like this:

And indeed you have made a logic error. I'm not quite sure how to
describe the nature of this error, other than to say "you used a
variable without initializing it". So obviously func() is not going
to do what you wanted (unless it ignores that parameter).
How to properly initialize a char*?

Well that question doesn't really make sense. It depends what func()
is expecting. Let me replace your example by a more well-known function:

char *ptr;
puts(ptr);

To "properly" initialize ptr in this example, you would have to point
it to a string. Making it a null pointer (as some others have suggested)
would not be an improvement.
I used to use
char* ptr = "";
but was told this is not good.
Can anybody explain to me why, and what's a good way to initilize it?

Why does the variable even exist in the first place?
Once you have answered that question, then you know what its value
should be.

Note that other people on this thread have said that you must initialize
variables to something, before you get up to the bit where you put them
to their intended use. This is in fact a matter of coding style;
personally I think such initializations are a waste of time (coding time,
run time, and maintenance time), and only serve to hide logic errors
that might be revealed by the warning "use of uninitialized variable".
You should do whatever seems right to you.
 
K

Kevin Goodsell

Ioannis said:
Check this out:


#include <iostream>


int main()
{
using namespace std;

char array[]="12345";

*array='X';

cout<<array<<endl;
}

I'm not sure what your point is here... But I'm afraid Julie is correct.
References to pointers are fine, and your example code demonstrated a
problem because you passed an incompatible type. Try it again like this:

void func(char * const input, int word_number, char * & ptr_to_word)
{
}


int main()
{
char array[]="b";
char *p = array;


func("a",5, p); // pass a pointer, not an array
}

I think you are hinting at the usual conversion ("decay") of an array
name to a pointer. It doesn't apply when binding to a reference.

-Kevin
 
K

Kevin Goodsell

Ioannis said:

Assuming ptr is being passed by value, the behavior is undefined. You
are generally only allowed to do a few things with an uninitialized
variable. For example, you can assign to it, take its address, bind it
to a reference, apply 'sizeof' to it, etc. However, inspecting the value
(as must be done to make a copy when passing to a function) is not
permitted.

The technical details of this are described in the standard in the
section about converting from a lvalue to an rvalue, if I recall
correctly. Essentially, this conversion is not defined for an
uninitialized lvalue.
And what would be the use of that?

You should not assign a string literal to a non-const char pointer. This
is a deprecated and dangerous conversion, included for C compatibility.
In both languages it is dangerous. In C++, the type of a string literal
is 'const char[N]' where N is chosen to be the appropriate size. The
conversion to (non-const) char* is permitted, but breaks
const-correctness and allows code that attempts to modify a
const-object, causing undefined behavior.
The above is entirely, completely useless.

I don't understand why you think it is useless. If your point is that
the assignment itself is wrong, you may be right. We don't know what
he's doing, but it seems likely that pointing to a string literal is not
useful (particularly when it is done only to silence a warning).

-Kevin
 
K

Kevin Goodsell

Ioannis 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.

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.
It is not an error!

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

-Kevin
 
K

Kevin Goodsell

Kevin said:
I don't understand why you think it is useless. If your point is that
the assignment itself is wrong, you may be right.

Should be "the initialization itself". And judging from your other
replies, I guess this is what you meant. The initialization to an
arbitrary string literal is probably not useful.

-Kevin
 
G

Gary Labowitz

<<snip>>
And after all the smoke clears we find ...

#include <iostream>
using namespace std;

int main( )
{
void change(const char*, char* &);

char s[10]= {"x"};
char* ptr = &s[0];
cout << "content of pointer is " << ptr << endl;
change("ABC", ptr);
cout << "content of pointer is " << ptr << endl;
return 0;
}

void change(const char* nus, char* &nup)
{
strcpy(nup, nus);
return;
}
 
B

Buster

Gary said:
And after all the smoke clears we find ...
[snip]

Maybe you shouldn't smoke that stuff during the week.

#include <ostream>
#include <iostream>

void redirect (char const * & reference, char const * pointer)
{ reference = pointer; }

int main ()
{
char const * p = "Hello.\n";
redirect (p, "Goodbye.\n");
std::cout << p;
}
 
C

Christopher Benson-Manica

Kevin Goodsell said:
Should be "the initialization itself". And judging from your other
replies, I guess this is what you meant. The initialization to an
arbitrary string literal is probably not useful.

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

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

Ioannis Vranos

Kevin Goodsell said:
Ioannis said:
Check this out:


#include <iostream>


int main()
{
using namespace std;

char array[]="12345";

*array='X';

cout<<array<<endl;
}

I'm not sure what your point is here... But I'm afraid Julie is correct.
References to pointers are fine, and your example code demonstrated a
problem because you passed an incompatible type. Try it again like this:

void func(char * const input, int word_number, char * & ptr_to_word)
{
}


int main()
{
char array[]="b";
char *p = array;


func("a",5, p); // pass a pointer, not an array
}

I think you are hinting at the usual conversion ("decay") of an array
name to a pointer. It doesn't apply when binding to a reference.


My point for the above code was that the name of an array is "converted" as
a pointer to the first element which in this case is char *. She had said:

"The function takes a reference argument of type char *, you are
(attempting) to pass a type of char[2]."


I was passing a "char *" as an address, the real problem was that the
function was accepting a char * & and there was not a char * object, so it
naturally failed.


Anyway i had expressed myself erroneusly in the beginning regarding the char
* &, and we got astray of the original subject which was about "premature
initialisation", that is initialisation with a value which is not going to
be used, but only to protect us. Such an initialisation does not protect us
in any way.






Ioannis Vranos
 

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
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top