Thread: pointer to char

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    153

    pointer to char

    Hey everyone,
    I was curious why the following line of code doesnt work like I thought it would...assume the right files have been included and that str is a pointer to char:
    Code:
    int len = strlen(str);
    for (int i = 0; i < len; i++)
        *str++ = toupper(*str++);
    Now I was under the impression that what this is doing is dereferencing str, thus meaning the particular element in that iteration, and then assigning that element the new upper case element.
    What really happens is the program displays trash and I sit at my computer confused...hehe.

    What I find even more interesting (ie: puzzling) is that when I changed the code to the following it works just fine even though I feel it is identical to the problem code:

    Code:
    int len = strlen(str);
    for (int i = 0; i < len; i++)
        *(str+i) = toupper(*(str+i));
    Any insight is always appreciated
    -Chap

  2. #2
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128
    It isn't identical at all, in your first example you are incrementing str twice. str++ modifies the pointer, unlike str+i.

  3. #3
    Tropical Coder Darryl's Avatar
    Join Date
    Mar 2005
    Location
    Cayman Islands
    Posts
    503
    as wootsoft said your are incrementing str twice,

    str = toupper(*str++);

    should work though

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    assume the right files have been included and that str is a pointer to char:
    Unfortunately, you left out the most important line of of the program. Neither program will work if str is a pointer to a char: both programs will crash without displaying any output.

    Since you say your second program works, str must actually be a char array. While not actually a pointer, an array name acts like a constant pointer, so you are not allowed to change its address. In your first program, the expression:

    str++

    attempts to move the pointer: the ++ operator involves an assigment at some point which changes the address of str.

    On the other hand, in your second program, in the expression:

    *(str+i)

    there is no assignment involved: (str + i) is not the same as (str = str + i). Therefore, you are not illegally attempting to change the address of str. Instead, all that happens is that the memory i places over from str is examined.

    Compare a char array, e.g. char str[], to a variable of type pointer to char, e.g. char* str. When a variable of type pointer to char is initialized with a string literal:

    char* str = "hello world";

    the pointer is really of type pointer to const char. That means the pointer can be moved, but what it points to cannot be changed. So, if str were actually a pointer to type char as you stated in your post, both programs would crash because in both programs you try to change the value of what str points to.

    As a final note, it's good practice to always declare your pointers to type char as const:

    const char* str = "hello world";

    Then, the compiler will alert you if you illegally try to change what str points to--instead of you being surprised at runtime by an unexplained crash. Even though the compiler will not flag it as an error, there is a type mismatch when you do this:

    char* str = "hello world";

    What's on the right is a constant by definition, but on the left is a pointer that isn't constant. I think that's the only time a C++ compiler will not flag a type mismatch like that, and it has to do with C legacy code or some such. However, it is still illegal to change the string literal, and at runtime if you attempt that, your program will crash. If you declare the pointer on the left as const, then the compiler will check for you to make sure you didn't attempt to change what's on the right.
    Last edited by 7stud; 05-10-2005 at 01:32 AM.

  5. #5
    Registered User
    Join Date
    Sep 2004
    Posts
    153
    So actually, I'm gonna try to clear things up...based on what you were just saying about how you can't change the value of what the pointer points to:

    Code:
    #include <iostream>
    #include <cstring>
    #include <cctype>
    using namespace std;
    /////////////////////////////////////////////////////////////////////////////
    class String
    {
    private:
    	char* str;
    public:
    	String(char* s)
    	{
    		int len = strlen(s);	
    		str = new char[len+1];	
    		strcpy(str, s);			
    	}
    
    	~String()			
    	{
    		cout << "Deleting str...\n";
    		delete[] str;			
    	}
    
    	void display()		
    	{ cout << str << endl; }
    
    	void upit()
    	{
    		char* pstr = str;		
    		while ( *pstr )           //while value at pointer is not null
    		{	
    			*pstr = toupper(*pstr);	
    			pstr++;			
    		}
    	}
    };
    //////////////////////////////////////////////////////////////////////////////
    
    int main()
    {
    	String s1 = "The end is nigh!";		
    	cout << "s1: ";     s1.display();	
    	s1.upit();		//make uppercase
    	cout << "\ns1: ";  s1.display();	
    	return 0;
    }
    my question lies in the String::upit() function, now what you said about const char*, does that only apply to when the pointer is initialized to a string literal? As opposed to the char* in upit() that is initialized to an address?

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Code:
    private:
    	char* str;
    public:
    	String(char* s)
    	{
    		//other code
    	}
    When you call that constructor, it will be with a statement like this:

    String myString("some text");

    A parameter to a function, e.g. s, creates a local function variable, which means its name can be used inside the function. Since a parameter variable is assigned whatever argument is sent to the function, this is effectively what happens:

    char* s = "some text";

    Whenever the compiler sees a string literal, it automatically slaps a '\0' on it, stores it in memory somewhere, and makes it const. If the left side of the assignment statement is of type char*, the compiler returns the address of the string literal. The result is that s is a pointer to the string literal. String literals are constants and you cannot change them, which means the parameter should be declared const. That way if you illegally try to change what s points to, the compiler will flag it as an error. Otherwise, the compiler will let it go, and if you end up changing the string literal inside the function, the program will unexpectedly crash at runtime.

    Next come these lines:

    int len = strlen(s);
    str = new char[len+1];
    strcpy(str, s);

    The second line uses 'new' to allocate some space in memory(on the heap) for a new char array, and 'new' returns the address of the memory. Whenever you use 'new', it returns an address, so the left side of the equals sign has to be a pointer type.

    In the next line, strcpy() copies each character in the string literal s, including the '\0' char, to the location in memory set aside for str by 'new'. Since str never gets assigned a string literal or the address of a string literal, there is no automatic constantness forced upon str. A string literal is something between double quote marks. Since you didn't declare str as a const type, you are therefore free to change whatever it points to.

    As noted above, if the left side of an assignment statement is of type char* then the compiler returns the address of the string literal. On the other hand, if you have a char array on the left side of an assignment statement:

    char myArr[] = "hello world";

    then as before the compiler slaps a '\0' onto the end of the string literal and stores it in memory, but in this case the compiler does not return an address. Instead, it sets aside some additional space in memory for myArr, and then strcpy()'s the string literal to the memory set aside for myArr. myArr is made const, so you cannot change the address of myArr, but you can change what is located at the address named myArr. For instance:

    char myArr[] = "abc";
    strcpy(myArr, "xyz");

    cout<<myArr<<endl;
    Last edited by 7stud; 05-10-2005 at 08:43 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. Direct3D problem
    By cboard_member in forum Game Programming
    Replies: 10
    Last Post: 04-09-2006, 03:36 AM
  3. Program Crashing
    By Pressure in forum C Programming
    Replies: 3
    Last Post: 04-18-2005, 10:28 PM
  4. Could somebody please help me with this C program
    By brett73 in forum C Programming
    Replies: 6
    Last Post: 11-25-2004, 02:19 AM
  5. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM