aromans
aromans

Reputation: 53

c++ - char const * const * - <error reading characters of string>

I have a variable that is a pointer to a constant pointer to a constant char.

char const * const * words;

I then add the word "dog" to that variable.

words = (char const * const *)"dog";

However, when when I debug the code, it states this about words:

{0x616d7251 Error reading characters of string.}

My question is, how would I properly access the characters of that variable to the point where I can record each individual character of the string.

Here is some example code below:

char const * const *words;
words = (char const * const *)"dog";

for (int i = 0; i < 5; ++i)
{
    char c = (char)words[i]; // Gives me, -52'i symbol', 'd', and then '\0'
    // How do I access the 'o' and 'g'?
}

Thanks for the help in advance.

Upvotes: 1

Views: 1194

Answers (3)

R Sahu
R Sahu

Reputation: 206747

Short answer:

Your program has undefined behavior. To remove the undefined behavior use:

char const * word = "dog";
for (int i = 0; i < std::strlen(word); ++i)
{
    char c = word[i];
}

or

char const * word = dog;
char const * const *words = &word;
for (int i = 0; i < std::strlen(*words); ++i)
{
    char c = (*words)[i];
}

Long answer:

You are forcing a cast from char const* to char const* const* and treating the location of memory that was holding chars as though it is holding char const*s. Not only that, you are accessing memory using an out of bounds index.

Let's say the string "dog" is held in some memory location as (it takes four bytes that includes the null character) and give it an address.

a1
|
v
+---+---+---+----+
| d | o | g | \0 |
+---+---+---+----+

You can treat the address a1 as the value of a pointer of type char const*. That won't be a problem at all. However, by using:

words = (char const * const *)"dog";

You are treating a1 as though it is holding objects of type char const*.

Let's assume for a moment that you have a machine that uses 4 bytes for a pointer and uses little endian for pointers.

words[0] evaluates to a pointer. Its value will be:

 'd' in decimal +
 256 * 'o' in decimal +
 256*256 * 'g' in decimal +
 256*256*256 * '\0' in decimal.

After that, you truncate that value to char, which will give you back the character d, which is not too bad. The fun part (undefined behavior) begins when you access words[1].

words[1] is same as *(words+1). words+1 evaluates to a pointer whose value is the address a2.

                 a2
                 |
                 v
+---+---+---+----+
| d | o | g | \0 |
+---+---+---+----+

As you can see, it points to memory that is beyond what the compiler allocated for you. Dereferencing that pointer is cause for undefined behavior.

Upvotes: 1

Aganju
Aganju

Reputation: 6405

You are consistently missing the second *.

Ignoring the const stuff, you are declaring a char** word, which is a pointer to a pointer to a single char. You won't get a word or many words into that, and casting just hides the problem.

To get "dog" accessible through such a pointer, you need to take an extra step; make a variable that contains "dog", and put its address into your word.

Upvotes: 1

pm100
pm100

Reputation: 50210

maybe you mean this

char const * const words = "dog";

for (int i = 0; i < strlen(words); ++i)
{
    char c = words[i]; 
}

now of course in c++ code you should realy be using std::string

Upvotes: 4

Related Questions