Sign in to follow this  
jamesbf

char confusion!

Recommended Posts

hey guys, ive been coding in c/c++ for a fairly long time now, and i like to think im ok at it. unfortunately though, im still pretty confused about the use of char/char* etc. the way i understand it (even though i don't really...), a char datatype is a pointer by default, so char c[15]="12345678901234"; int i; then using for (i=0;i<15;i++) printf("%c\n",c[i]); is the same as using for (i=0;i<15;i++) printf("%c\n",*(c+i)); right? so...getting to my question....why do people use char * at all? if my statement above is correct, then a char * is a double pointer? whats the point (heh)? To make my question a little clearer....why doesnt this code work? char * testing() { char temp[15]="23456789012345"; temp[0]='H'; temp[1]='i'; return(temp); } int main(int argc, char* argv[]) { char c[15]="12345678901234"; int i; for (i=0;i<15;i++) printf("%c\n",*(c+i)); c=testing(); for (i=0;i<15;i++) printf("%c\n",*(c+i)); return 0; } PS: To anyone thats gonna say "go read a tut", i've tried...but everytime they mention chars, they say the simple stuff, then "search the net for more info on chars" or whatever...

Share this post


Link to post
Share on other sites
Quote:
Original post by jamesbf
hey guys,

ive been coding in c/c++ for a fairly long time now, and i like to think im ok at it. unfortunately though, im still pretty confused about the use of char/char* etc.

the way i understand it (even though i don't really...), a char datatype is a pointer by default, so


No no...

char * c; //c is a pointer to a char
char c; //c is a single char

I think you know this, just clarifying to make sure.

Quote:
char c[15]="12345678901234";
int i;

then using

for (i=0;i<15;i++)
printf("%c\n",c[i]);

is the same as using

for (i=0;i<15;i++)
printf("%c\n",*(c+i));

right?


Yes.

Quote:
so...getting to my question....why do people use char * at all?


Instead of [] you mean? Well, sometimes you don't know the size of a string ahead of time, and you need to be able to allocate at run time memory for it, like so:

char string1[] = "I like pie oh yes I do...";
char string2[] = "my name is Mike and I'm a foo!!";
char string3 * = malloc( strlen( string1 ) + strlen( string2 ) + 1 );
strcpy( string3 , string1 );
strcat( string3 , string2 );
free( string3 );

Note that there's a much better alternative in C++ called std::string:

#include <string>
std::string string1 = "I like pie oh yes I do...";
std::string string2 = "my name is Mike and I'm a foo!!";
std::string string3 = string1 + string2;

Reasons this method is better, in general:
1) std::string manages it's memory automatically, meaning you won't have a memory leak if you froget to use a free statement, or if you never reach the free statement, etc.
2) It avoids "the Shlemiel the painter's algorithm", meaning contrary to what some programmers stuck in 1985 think, std::string can actually outpreform the C equivilant (unless you do a lot of manual, error prone tracking and stuff). (article on this)
3) It makes more sense, IMO. Which do you think makes more sense:

std::string string3 = string1 + string;

or:

char string3 * = malloc( strlen( string1 ) + strlen( string2 ) + 1 );
strcpy( string3 , string1 );
strcat( string3 , string2 );
free( string3 );

Quote:
if my statement above is correct, then a char * is a double pointer? whats the point (heh)?


Again, no. a char is just like an int, only it can't hold as large a number as int can, and the number it holds is usually an ASCII code which corresponds to a letter.

You can do this for example:
char a = 3;
char b = 4;
char c = a + b;
assert( c == 7 );

The only oddity about char in and of itself is that it can be either signed or unsigned, depending on your compiler. "unsigned char" is allways unsigned, "signed char" is allways signed, but "char" can behave like either.

Quote:
To make my question a little clearer....why doesnt this code work?

char * testing()
{
char temp[15]="23456789012345";

temp[0]='H';
temp[1]='i';
return(temp);
}


Because temp[] is declared in testing. Once the function returns, the array is destroyed. The pointer will still point to where it used to be, but the data will no longer be there*.

(* well, it might, if you havn't run another function. The memory is no longer reserved when the function returns, and as soon as you call another function, it will most likely overwrite the data with it's own. Even if you arn't running another function, relying on this is an extremely bad idea, as it will cause "undefined behavior". Using that pointer could cause your program to crash, or launch nukes at a cow ranch in Alaska)

Quote:
int main(int argc, char* argv[])
{
char c[15]="12345678901234";
//...
c=testing();
return 0;
}


There's another problem here too, c is an array of characters, and you're trying to assign it to a pointer. I don't think that's valid C++.

Now, if we wanted to do your example again using std::string, here's what it'd look like:

#include <iostream> //for cout example bellow
#include <string>
using namespace std; //so we don't have to type std::string every time

string testing()
{
string temp = "23456789012345";
temp[0] = 'H';
temp[1] = 'i';

return temp;
}

int main(int argc, char* argv[])
{
string c = "12345678901234";
int i;

//c.c_str() returns a pointer to a constant char, that is, (const char *).
//this allows us to use std::string with old C-style functions.

//I'm going to implement this many times to show a few options:
//for (i=0;i<15;i++)
// printf("%c\n",*(c+i));

for ( i = 0 ; i < 15 ; ++i )
printf( "%c\n", *(c.c_str()+i) );

for ( i = 0 ; i < 15 ; ++i )
printf( "%c\n", c[i] );

for ( i = 0 ; i < 15 ; ++i )
cout << c[i] << endl;

//If we want to print all of the string on one line:

printf( "%s\n" , c.c_str() );

cout << c << endl;

c = testing();

//for (i=0;i<15;i++)
// printf("%c\n",*(c+i));
cout << c << endl;

return 0;
}



Hope this helps!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Now, you say you've been coding in C/C++. If you are, in fact, using C++, I would highly recommend using ostreams as opposed to printf(). If you don't know about ostreams, I shall demonstrate their use, right now:

#include<iostream>
int main()
{
char c[15]="12345678901234";
std::cout<<c;
.
.
.
}


Also, you posted:
 
char * testing()
{
char temp[15]="23456789012345";

temp[0]='H';
temp[1]='i';
return(temp);
}


I agree with the previous about the used of std::string, however, I would like to point out that this function will work if temp declared as a static char. Just wanted to acknowledge that.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yo, proper authorities. While composing the previous post, I noticed that '+'s don't display when you click the "Show Preview" option. Ya'll might wanna fix that.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
I agree with the previous about the used of std::string, however, I would like to point out that this function will work if temp declared as a static char. Just wanted to acknowledge that.


Or if temp[] is made a global variable, I should've clarifed on that, good to point out :-).

That said, I would like to similarly point out that I would consider these methods bad to use, as they can cause you many nightmares if you ever try to add multithreading to your program, since they'll end up modifying the same data.

Quote:
Original post by Anonymous Poster
Yo, proper authorities. While composing the previous post, I noticed that '+'s don't display when you click the "Show Preview" option. Ya'll might wanna fix that.


Hmm, what do you know, it dosn't!!! I'll post a thread in GDNet Comments, Suggestions, and Ideas on your behalf, since IIRC APs can't start new threads.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
But this should work fine.

[code]
char * testing() {
char* temp = "23456789012345";
return(temp);
}
[\code]

String literals are static snd const char*.

And this will fail..

[code]
char * testing() {
char* temp = "23456789012345";
*temp = 'H';
*(temp+1) = 'i';
*(temp+1) = 0 ;
return(temp);
}
[\code]

So but it compiles ! hm..
Never thought of it before..

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this