char pointers

So there's another thread about this very topic, but since replies are disabled, I'm forced to ask a redundant question:
Why can char pointers hold strings? When I learned pointers, I was told that they pointed to one variable. How come a char pointer can point to a whole string? I've read many explanations but I really still don't get it. What are the inner workings of char pointer strings?

Thanks
Also, I have a function that is designed to handle char arrays, and it uses the [] operator, but yet, it still works on char* strings. On top of this not making sense to me, another interesting thing occurs. When I have three chars or less without counting the null, it works fine. When I have more than that, it works fine, but adds a segfault for some reason. What is going on?
Last edited on
A char pointer doesn't hold a string. it just points to it.

A pointer, strictly speaking, points to a memory address. The address could be a single variable, but it can also be the first one of a sequence of variables.

Do you understand the concept of a null terminated string?
Yes, but then, if it points to a string, why then would I have the interesting occurrence in the function I mentioned and does the compiler make sure that the string does not overwrite something already in memory?
I'll get back to you later. Before I continue, I want to point you at a diagram illustrating the matter. But I don't have time to Google for one right now.

#1
When I have three chars or less without counting the null, it works fine.

Please post a code fragment

#2
why then would I have the interesting occurrence in the function

I don't fully understand this statement. Please clarify.

Andy
Last edited on
This is the code, it was intended for a char array.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
template <class X>
X c2a (char* s)
{
int i, length = 0 , exponent = 0 , decimPointTrip = 0, decPlaces = 0, sign = 1;
X returnValue = 0;

    for (i = 0 ; s[i] != '\0' ; i++)
    length++;

    if (s[0] == '-') //If first character is '-', "delete" it from array and
    {                //make sure sign is changed to -1, you'll see why in a minute
        for (i = 0 ; s[i] != '\0' ; i++)
        s[i] = s[i + 1];

    sign = -1;
    length--;
    }

    for (i = 0 ; i + decimPointTrip != length ; i++ , exponent++)
    {
        if ( ( s[i] < 48 || s[i] > 57 ) && s[i] != '.') //Number characters in ascii range from 48 to 57
        {
        cout << "Error, input was invalid" << endl;
        return 0;
        }

        if (s[length - 1 - i - decimPointTrip] == '.')
        {
            if (decimPointTrip) //If there is more than one decimal point
            {
            cout << "Error, input was invalid" << endl;
            return 0;
            }

        decimPointTrip = 1;
        decPlaces = i;
        }

    returnValue +=  pow (10 , exponent) * ( s[length - 1 - i - decimPointTrip ] - 48 ); //-1 for OBOE, "array" is written backwards, beacuse
    }                                                                                  //the higher i is (s[i]) the lower the place value,
                                                                                        //so function reads "array" backwards. Does that make sense?
returnValue /= pow (10 , decPlaces);                                                    //If not, read more detailed description at end of header.
returnValue *= sign; //This is why
return returnValue;
}

It works fine with arrays, but with char* strings, it works fine, but when there are more than three characters without the null it still works, but it will say segmentation fault
I haven't looked closely ay your code, but sizeof(char*) = 4

But you're not supposed to store chars actually in a char*, and could only do so with a cast.

A char* must be initialized by pointing at some memory, either on the stack

1
2
3
4
5
void Func()
{
    char buffer[256];
    char* p = buffer;
}


Allocating memory on the heap

1
2
3
4
5
6
7
8
9
10
void Func()
{
    char* p_C_Style  = (char*)malloc(256);
     ...
    free(p_C_Style);

    char* p_Cpp_Style  = new char[256];
    ...
    delete [] p_Cpp_Style;
}


Or globally, which is like the stack, but with a global variable.

Andy

Last edited on
Okay, thanks Andy
You see where the block of memory storing the actual chars is, as opposed to one storing the pointer variable?
I think I understand now it points to char string, but why can you only do this with char*s? Also, why then would the function still work even if the pointer does not point to a location (like you said it should)

An array also has a location!

When you declare an array like

char example[32];

in an C program, the variable is (to C) just the location in memory of the first element. It acts just like a fixed pointer.

operator[] is a way of asking for the n'th element after the first one. C/C++ itself has no mechanism to check that the offset you use makes sense. But some compiler do inject code to trap this kind of error.

The difference between the address of an array like example and a normal pointer is that once an array is defined, it's at a fixed point in memory. But a pointer's value can be modified to point at a different bit of memory. So pointers are useful for searching through char arrays.

1
2
strcpy(example, "Hello World!");
char* pos = strstr(example, "World");


Here, pos will end up as the address of the character 'W' in memory.

I said a "normal" pointer. In C++ you can also declare a pointer as const.

const char* ptr;
is a pointer which can be adjusted to point at a different bit of memory, but you're not allowed to change what it points to.
char const * ptr;
is the same as the last line.
char * const ptr;
is a pointer which points at a fixed bit of memory but can change the value.
char const * const ptr;
is a pointer which points at a fixed location in momory and cannot be moved.
const char * const;
is the same as the last line.

(Don't blame me for the const rules! The rule is that the const applies to the token to the left, unless its's the left-most token itself. Then it applies to the token to its right. Note that the following in invalid as it uses const in the same way twice:

const char const * ptr;

It's the same as writing

const const char* ptr;

)

So, is this helping?
Last edited on
Topic archived. No new replies allowed.