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.
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
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.
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.
Related
Program 1:
#include <iostream>
using namespace std;
int main() {
string str;
char temp = 'a';
str += temp + "bc";
cout << str;
return 0;
}
Output:
Unknown characters
Program 2:
#include <iostream>
using namespace std;
int main() {
string str;
char temp = 'a';
str += temp;
str += "bc";
cout << str;
return 0;
}
Output:
abc
Why are both the outputs different? Shouldn't both outputs be the same?
This statement
str += temp + "bc";
can be represented like
str = str + ( temp + "bc" );
In the sub-expression temp + "bc" the string literal "bc" is implicitly converted to pointer to its first character and has the type const char *. The value of the variable temp is converted to the type integer due to the integer promotions that for example in ASCII table has the value 97.
So in the sub-expression there is used the pointer arithmetic. The expression temp + "bc" points to a memory that outside the string literal. So the result of the expression is undefined.
If you would write for example
char temp = 1;
then the expression temp + "bc" points to the second character of the string literal. As a result str would have the value 'b'.
Or to get the same result as in the second program you could write
str += temp + std::string( "bc" );
As for the second program then in this statement
str += temp;
str += "bc";
there are used overloaded operators += for the class std::string and objects of type char and char *. So these statements are well-defined.
Pat attention to that you should include explicitly the header <string>.
#include <string>
Program 1 in this line
str += temp + "bc";
first arguments of addition are evaluated
on right there is array of char: const char[3]
on left there is char which can be auto converted to int
const char[3] degrades to const char *
adding int (97) and const char * is doable, but results points beyond buffer range.
then you are using basic_string::operator+=( const CharT* s );, but argument is invalid. You have got buffer overflow.
Program 2.
Doesn't have this undefined behavior and operators form std::string are used.
Another reasonable version is:
str = str + temp + "bc";
Now each addition will create a std::string as a result.
std::string class has + and += operators overloaded, allowing you to use those to concatenate std::strings with each other, with individual characters and arrays of characters.
But just like in C, "bc" is not a std::string but a const char [3] (a constant array of 3 characters). Arrays are often automatically converted (decay) to pointers to their first elements. It happens here too.
str += "foobar"; appends the characters pointed by the pointer one by one, until it hits the null byte that terminates the string.
You can add integers to pointers: str += "foobar" + 3; will append "bar" to the string.
In C++, chars are simply small integers. So 'a' + "bc" actually means 97 + "bs" (assuming your compiler uses ASCII, all common ones do).
This forms a pointer that's out of bounds of the array and causes undefined behavior.
The random characters you're seeing are the contents of memory located 97 bytes after the "bc" array, terminated by a random null byte that was in that memory.
Since I am a newbie in this c++ programming. I kind a confuse with this question. If there is "const char str[]", How can I return this with integer value ??
for(int i=0; i<size; i++)
{
n = rand () % 98 + 1;
str [i] = n + '0';
}
Do I have to do str[i] = n -'0' ?
How can I return this character digit with integer value ??
First of all, if str is declared as a const char[] it means that the content of str is constant. Therefore you cannot modify it.
You could try to const_cast str, but it is usually a bad idea.
Secondly you can simply convert a char to an int by assigning your char variable to an intvariable.
char c = 'a';
int c_value = c;
You can find more inforation about const-correcteness here, and about type-casting here.
I want to convert a char value to an int. I am playing with following code snippets:
#include <iostream>
using namespace std;
int main() {
char a = 'A';
int i = (int)a;
//cout<<i<<endl; OUTPUT is 65 (True)
char b = '18';
int j = b;
//cout<<j<<endl; OUTPUT is 56 (HOW?)
char c = 18;
int k = c;
//cout<<c<<endl; OUTPUT is empty
//cout<<k<<endl; OUTPUT is 18 (Is this a valid conversion?)
return 0;
}
I want the third conversion, and I got correct output i.e 18. But is this a valid conversion? Can anyone please explain the above outputs and their strategies?
char a = 'A';
int i = (int)a;
The cast is unnecessary. Assigning or initializing an object of a numeric type to a value of any other numeric type causes an implicit conversion.
The value stored in i is whatever value your implementation uses to represent the character 'A'. On almost all systems these days (except some IBM mainframes and maybe a few others), that value is going to be 65.
char b = '18';
int j = b;
A character literal with more than one character is of type int and has an implementation-defined value. It's likely that the value will be '1'<<8+'8', and that the conversion from char to int drop the high-order bits, leaving '8' or 56. But multi-character literals are something to be avoided. (This doesn't apply to escape sequences like '\n'; though there are two characters between the single quotes, it represents a single character value.)
char c = 18;
int k = c;
char is an integer type; it can easily hold the integer value 18. Converting that value to int just preserves the value. So both c and k are integer variables whose valie is 18. Printing k using
std::cout << k << "\n";
will print 18, but printing c using:
std::cout << c << "\n";
will print a non-printable control character (it happens to be Control-R).
char b = '18';
int j = b;
b, in this case a char of '18' doesn't have a very consistent meaning, and has implementation-dependent behaviour. In your case it appears to get translated to ascii value 56 (equivalent to what you would get from char b = '8').
char c = 18;
int k = c;
c holds character value 18, and it's perfectly valid to convert to an int. However, it might not display very much if you display as a character. It's a non-printing control character.
If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right? For example:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This will print the value stored at num[1] and at num[2],
so num + 2 is actually num + 2*sizeof(int) if I'm not wrong.
Now, if I initialize an array of pointers to char to string literals, like this one:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
This can be done because a string literal like "hi" represents the address of its first character, in this case 'h'. Now my question is how can I write something like:
cout << *(ch + 2);
and get "I,m a string literal" as the output?
Since the pointer points to char, shouldn't adding 2 to the pointer actually be (ch + 2*sizeof(char)) ? giving me the output 'There' ?
Does it have something to do with cout? Does cout search the memory of the pointed to values to see if it finds '\0's recognizing the contents of the pointed to values as strings and then modifying pointer arithmetic? But then adding 1 to a pointer to char pointing to strings would mean adding different number of bytes (instead of the size of a char) everytime, since a string can be any size. Or am I totally wrong? I'm sorry I am new to C++, and programming in gerenal.
The array isn't storing chars, it's storing char *s. Hence saying ch + 2 will be equivalent to ch + 2*sizeof(char *). You then dereference that, which is pointing to "I'm a string literal".
Your initial example shows the confusion:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This is an array of pointers-to-int. Hence, *(num + 2) will be *(num + 2*sizeof(int *)), not 2*sizeof(int). Let's demonstrate this with a small program:
#include <iostream>
int main()
{
int *num[3];
int x, y, z;
x = 1;
y = 2;
z = 3;
num[0] = &x;
num[1] = &y;
num[2] = &z;
std::cout << *(num + 2) << "\n";
}
This will print out a memory address (like 0x22ff28) because it is holding pointers, not values.
In C and C++, arrays and pointers are very similar (many books claim they are exactly the same. This is not -quite- true, but it is true in a lot of situations).
Your first example should be int num[5]. Then *(num + 2) (which is equivalent to num[2]) will be equivalent to *(num + 2*sizeof(int). Hopefully this clears up your confusion somewhat.
"If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right?"
There's no guarantee in the C++ Standard that a pointer is the number of the byte of some memory where the pointer points to. If you add an integer n to a pointer, the result is a pointer to the nth next element in that array:
int iarr[10];
int* pi = iarr; // pi points to iarr[0]
int* pi2 = pi+2; // pi2 points to iarr[2]
What you get when you look at, e.g. int repr = (int)pi; is not defined by the C++ Standard.
What will happen on the most popular platforms/implementations, is that
(int)pi2 == ((int)pi) + 2*sizeof(int)
When you have arrays of pointers, the exact same thing happens:
int* piarr[10];
int** ppi = piarr; // ppi points to iarr[0]
int** ppi2 = piarr+2; // ppi2 points to iarr[2]
Note that the type of piarr is array of 10 pointer to int, therefore the elements of that array have the type pointer to int. A pointer to an element of that array consequently has the type pointer to pointer to int.
char* ch[5] is an array of 5 pointers to char.
"Hello" etc. are (narrow) string literals. A (narrow) string literal is an array of n const char, where n is the length of the string plus 1 (for the terminating \0 character). Arrays can be implicitly converted to pointers to the first element of the array, this is what happens here:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The array ch contains three pointer to char. As those have been obtained by converting arrays to pointers, each of them points to the first element of an array of char: The pointer ch[0] (the first element of the array ch) points to the first element of the array "Hi", ch[1] points to the first element of "There" and so on.
Note there's also a conversion involved from const char to char, which is deprecated and should be avoided. The better form would be:
char const* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The expression *(ch + 2) is interpreted as follows:
ch names that array (see above)
ch + 2 implicitly converts ch from array of 3 pointers to char to pointer to pointer to char, a pointer pointing to the first element of the array ch. The type of this expression therefore is pointer to pointer to char.
ch + 2 makes the pointer from the last step now point to the second next element; it pointed to the first element of ch, so it now points to the third element of the array ch.
*(ch + 2) finally, the * dereferences the pointer and "fetches" the object pointed to. The pointer created by ch + 2 points to the 3rd element of the array ch, therefore, this expression resolves into the third element of the array ch. The type of the expression now is pointer to char.
The result of the expression is passed to std::cout::operator<<. As the type of the expression is pointer to char, cout will print that string: the third element of the array ch.
In C, a character is represented by the datatype char. It can hold any ASCII character and it ranges from 0 to 255. Moreover it uses a single byte of size.
A string, however, is represented by char*, which technically is an array of chars. There's a difference. A char is not the same as a char*. The former stores a single character, and the latter stores a memory direction which corresponds to the offset of the string.
Now, in your example, ch is not a char* but a char**. This is, it is an array of an array of chars, or better said, an array of strings. If we dereference ch once, as in *ch, we will get the first string: Hi. If we dereference it twice, as in **ch, we will get the first character of the first string: H. So, we can start working with pointer arithmetics!
cout << *(ch + 2) will output I,m a string literal
cout << **(ch + 1) will output T (first character of second string)
cout << *(*ch + 1) will output i (second character of first string)
Keep on working with these examples to understand better how characters and strings are output! It's all about pointer arithmetics!
Does it have something to do with cout?
No:
const char* cstrings[5] =
{
"Hi",
"There",
"I,m a string literal"
};
const char** x = cstrings + 2;
cout << *x << endl;
.
.
But what can be confusing is that the << operator works differently when given a pointer to a cstring--instead of outputting the address, it outputs the string. Here is an example:
int x = 10;
int* pint = &x;
const char* pstr = "hello";
cout << pint << endl << pstr << endl;
--output:--
0x7fff5fbff85c //hexidecimal string representation of an integer
hello
Since the pointer points to char,
1) The literal strings are stored in your array as pointers. That's why the type of the array is pointer.
2) Pointers are adresses in memory, which are just integers.
3) So your array of pointers is really an array of integers.
So, I am learning about pointers via http://cplusplus.com/doc/tutorial/pointers/ and I do not understand anything about the pointer arithmetic section. Could someone clear things up or point me to a tutorial about this that I may better understand.
I am especially confused with all the parentheses things like the difference between *p++,(*p)++, *(p++), and etc.
*p++
For this one, ++ has higher precedence then * so it increments the pointer by one but retrieves the value at the original location since post-increment returns the pointer and then increments its value.
(*p)++
This forces the precedence in the other direction, so the pointer is de-referenced first and then the value at that location in incremented by one (but the value at the original pointer location is returned).
*(p++)
This one increments the pointer first so it acts the same as the first one.
An important thing to note, is that the amount the pointer is incremented is affected by the pointer type. From the link you provided:
char *mychar;
short *myshort;
long *mylong;
char is one byte in length so the ++ increases the pointer by 1 (since pointers point to the beginning of each byte).
short is two bytes in length so the ++ increases the pointer by 2 in order to point at the start of the next short rather than the start of the next byte.
long is four bytes in the length so the ++ increases the pointer by 4.
I found useful some years ago an explanation of strcpy, from Kernighan/Ritchie (I don't have the text available now, hope the code it's accurate): cpy_0, cpy_1, cpy_2 are all equivalent to strcpy:
char *cpy_0(char *t, const char *s)
{
int i = 0;
for ( ; t[i]; i++)
t[i] = s[i];
t[i] = s[i];
i++;
return t + i;
}
char *cpy_1(char *t, const char *s)
{
for ( ; *s; ++s, ++t)
*t = *s;
*t = *s;
++t;
return t;
}
char *cpy_2(char *t, const char *s)
{
while (*t++ = *s++)
;
return t;
}
First you have to understand what post increment does;
The post increment, increases the variable by one BUT the expression (p++) returns the original value of the variable to be used in the rest of the expression.
char data[] = "AX12";
char* p;
p = data;
char* a = p++;
// a -> 'A' (the original value of p was returned from p++ and assigned to a)
// p -> 'X'
p = data; // reset;
char l = *(p++);
// l = 'A'. The (p++) increments the value of p. But returns the original
value to be used in the remaining expression. Thus it is the
original value that gets de-referenced by * so makeing l 'A'
// p -> 'X'
Now because of operator precedence:
*p++ is equivalent to *(p++)
Finally we have the complicated one:
p = data;
char m = (*p)++;
// m is 'A'. First we deference 'p' which gives us a reference to 'A'
// Then we apply the post increment which applies to the value 'A' and makes it a 'B'
// But we return the original value ('A') to be used in assignment to 'm'
// Note 1: The increment was done on the original array
// data[] is now "BXYZ";
// Note 2: Because it was the value that was post incremented p is unchaged.
// p -> 'B' (Not 'X')
*p++
Returns the content, *p, an then increases the pointer's value (postincrement). For example:
int numbers[2];
int *p;
p = &numbers[0];
*p = 4; //numbers[0] = 4;
*(p + 1) = 8; //numbers[1] = 8;
int a = *p++; //a = 4 (the increment takes place after the evaluation)
//*++p would have returned 8 (a = 8)
int b = *p; //b = 8 (p is now pointing to the next integer, not the initial one)
And about:
(*p)++
It increases the value of the content, *p = *p + 1;.
(p++); //same as p++
Increases the pointer so it points to the next element (that may not exist) of the size defined when you declared the pointer.