I am a complete novice to pointers and discovered them about a week ago. This book I am reading introduced me a problem for me to solve and it took me a while without coming up with the correct solution, and so I cheated. Looked it up and came up with this:
#include <iostream>
void mystrcpy(char* str1, char* str2) {
while (*str1++ = *str2++);
}
int main() {
char str1[15] = "C++";
char str2[15] = "Pointers";
std::cout << str1 << std::endl << str2 << std::endl;
mystrcpy(str1, str2);
std::cout << str1 << std::endl << str2 << std::endl;
}
Question was me to fill in the blanks at the void function to solve the problem and the problem beneath at main() which printed out this:
C++
Pointers
C++
Pointers
and it wanted me to look like this:
C++
Pointers
Pointers
Pointers
So, basically I do not understand how while (*str1++ = *str2++); solves this? Been looking at it for a while still clueless how it sorst the strings out to output it like that
Pointers are like variables that point to a specific location in memory. You can dereference them to get the value that they point to with *str2, and increment them to make them point to the next value in memory (based on their datatype): str2++.
The precedence can be confusing. *str2++ works in this order:
get the value pointed to by str2, and then
increment str2 to point to the next character
while (*str1++ = *str2++);
This statement copies each char from str2 into str1 until it reaches a null pointer in str2. It works by:
*str2: get the character pointed to by str2
*str1 = *str2: write the character pointed to by str2 to the destination pointed to by str1
str1++, str2++: increment str1 and str2 for the next loop iteration. Now each pointer points to the next character in each string.
When str2 points to a null terminator, *str2 returns 0 (or '\0'), and *str1 = *str2 will write it to str1, and also return the 0 which will cause the while loop to complete.
str1 starts as C++, and str2 starts as Pointers. Then the mystrcopy function is called which copies the value of str2 into str1.
The copying is done by the line in question:
while (*str1++ = *str2++);
I agree that this line is relatively opaque, but here are some basics:
The * on each "de-references` each pointer. That means it is looking at the value stored at the given address, not the address itself.
The ++ is used to shift the pointer address from its current location to the next location in the array. It is placed after the pointer so that the pointer is incremented after we get/set it's value.
The while-loop here has only a condition, however the condition itself is an action. The action is executesd and the result is checked. When the end of the string is reached, the \0 char is found which terminates the loop.
So, in summary, the line copies a single char value from str2 into the value of str1, increments both pointers to point to the next char of each, then repeats until failure.
It is worth noting that, although the pointers are being changed within the function to point at new addresses, not just the start of each array, these pointer variables are not passed into the function by reference, and so the pointer variables outside the function remain unchanged, still containing the address of the first char. However, the data stored at those addresses has been modified.
Each iteration, the loop assigns the value of the second element of array to the first element of the array, after which it checks whether the left set value is equal to zero, and if not, the loop continues. At the end of the iteration, the loop increments both variables.
Related
How to reverse a string using pointers. I don't understand any of the answers online. I need it to be explained really slowly.
For an assignment, I need to use pointers to reverse a string (and to use that to test if something is a palindrome), and I cannot for the life of me understand any of the answers to similar questions online. In this question, for instance, the top answer is:
void rev_string(char *str)
{
char *p = str, *s = str + strlen(str) - 1;
while (p < s) {
char tmp = *p;
*p++ = *s;
*s-- = tmp;
}
}
This barely makes sense to me.
First of all, why is the input a char when we're looking to reverse a string? The * marks it as a pointer as well, right? Why is the input a pointer when we're looking to reverse a string?
I understand the first line of code with the variable initialization is meant to set pointer p equal to the start of the string, and pointer s to the tail of the string, but why?
I get the feeling that *p++ and *s-- are supposed to go to the next letter or the previous letter of the string, respectively, but why does that work?
Please assist.
I think the main problem with your example is that the coding style is bad.
Good code is readable (another good lesson to learn today).
The use of prefix and postfix ++, -- in the original code
while correct do also not help in making clear what the code is doing.
Another lesson is not to sacrifice readability for premature optimization like that. Compilers are smart and can optimize quite a bit of your input.
#include <iostream>
void reverse(char* input)
{
const std::size_t offset_of_last_character = strlen(input) - 1;
char* begin_pointer = &input[0]; // front_pointer now contains address of first character in string
char* end_pointer = &input[offset_of_last_character]; // end_pointer now contains address of last character in the string
while (begin_pointer < end_pointer) // as long as pointers don't cross-over in memory continue
{
// swap the characters pointed to
// first iteration this will be first and last character,
// second iteration this will be the second and the character and last but one character, etc...
std::swap(*begin_pointer, *end_pointer);
++begin_pointer; // move one address up in memory, this is where the next character is found
--end_pointer; // move on address down in memory, this is where the previous character is found
}
}
int main()
{
char input[] = "!dlrow olleH";
reverse(input);
std::cout << input;
return 0;
}
First of all, why is the input a char when we're looking to reverse a string? The * marks it as a pointer as well, right? Why is the input a pointer when we're looking to reverse a string?
The code is C. A string in C is a NUL-terminated array of chars. Thus a "hello" string is indeed a char str[6] = {'h', 'e', 'l', 'l', 'o', (char)0x00}; How do you pass this to a function? You pass the pointer char * to the very first element of a string.
I understand the first line of code with the variable initialization is meant to set pointer p equal to the start of the string, and pointer s to the tail of the string, but why?
Because the function considers the input pointer to point at the start of a char array with the aforementioned properties. Pointers p and s are meant to point inside the array. Pointer p is initially set at the start of the array, pointer s is initially set at a strlen(str) - 1 offset into the array. The offset is exactly where the last character in the array is.
I get the feeling that *p++ and *s-- are supposed to go to the next letter or the previous letter of the string, respectively, but why does that work?
The feeling is correct. These two are just pointers inside the array, they just travel along array's elements. This syntax used here says: "dereference the pointer, and right after the expression is done (may think compiler sees ;) increment/decrement the pointer".
To finish it up. I really recommend the "C Programming Language" book to read. Strings in C, passing arrays to functions, and pointer arithmentics are what the given code is about.
I am looking at some code I did not write and wanted help to understand an element of it. The code stores character arrays, creates pointers to these arrays (assigning the pointers the arrays addresses). It looks like it then creates an array to store these characters pointers addresses and I just wanted some clarification on what I am looking at exactly. I also am confused about the use of the double (**) when creating the array.
I have included a stripped down and simplified example of what I am looking at below.
char eLangAr[20] = "English";
char fLangAr[20] = "French";
char gLangAr[20] = "German";
char* eLangPtr = eLangAr;
char* fLangPtr = fLangAr;
char* gLangPtr = gLangAr;
char **langStrings [3]=
{
&eLangPtr,
&fLangPtr,
&gLangPtr
};
When using the array they pass it as an argument to a function.
menu (*langStrings[0]);
So the idea is that the character array value "English" is passed to the function but I'm having trouble seeing how. They pass the menu function a copy of the value stored in the langStrings function at location 0, which would be the address of eLandPtr? If someone could explain the process in English so I could get my head around it that would be great. It might be just because it has been a long day but its just not straight in my head at all.
You are correct that langStrings contains pointers to pointers of array of characters. So each langString[i] points to a pointer. That pointer points to an array. That array contains the name of a language.
As others point out, it looks a bit clumsy. I'll elaborate:
char eLangAr[20] = "English"; is an array of 20 chars and the name "English" is copied to it. I don't expect that variable eLangAr will ever contain something else than this language name, so there is no need to use an array; a constant would be sufficient.
char **langStrings [3]= ... Here, it would be sufficient to have just one indirection (one *) as there seems no need to ever have the pointer point to anything else (randomly shuffle languages?).
in conclusion, just having the following should be sufficient:
const char *langStrings [3]=
{
"English",
"French",
"German"
};
(Note the const as the strings are now read-only constants/literals.)
What the given code could be useful for is when these language names must be spelled differently in different languages. So
"English",
"French",
"German" become "Engels", "Frans", "Duits". However, then there still is one level of indirection too many and the following would be sufficient:
char *langStrings [3]=
{
aLangArr,
fLangAr,
gLangAr
};
Ok, here goes.
The **ptrToptr notation means a pointer to a pointer. The easiest way to think on that is as a 2D matrix - dereferencing one pointer resolves the whole matrix to just one line in the matrix. Dereferencing the second pointer after that will give one value in the matrix.
This declaration:
char eLangAr[20] = "English";
Declares an array of length 20, type char and it contains the characters 'E', 'n', 'g', 'l', 'i', 's', 'h' '\0'
so it is (probably) null terminated but not full (there are some empty characters at the end). You can set a pointer to the start of it using:
char* englishPtr = &eLangAr[0]
And if you dereference englishPtr, it'll give the value 'E'.
This pointer:
char* eLangPtr = eLangAr;
points to the array itself (not necessarily the first value).
If you look at
*langStrings[0]
You'll see it means the contents (the dereferencing *) of the pointer in langStrings[0]. langStrings[0] is the address of eLangPtr, so dereferencing it gives eLangPtr. And eLangPtr is the pointer to the array eLangAr (which contains "English").
I guess the function wants to be able to write to eLangAr, so make it point to a different word without overwriting "English" itself. It could just over-write the characters itself in memory, but I guess it wants to keep those words safe.
** represents pointer to pointer. It's used when you have to store pointer for another pointer.
Value of eLangPtr will be pointer to eLangAr which will has the value "English"
Here:
char eLangAr[20] = "English";
an array is created. It has capacity of 20 chars and contains 8 characters - word "English" and terminating NULL character. Since it's an array, it can be used in a context where pointer is expected - thanks to array-to-pointer decay, which will construct a pointer to the first element of an array. This is done here:
char* eLangPtr = eLangAr;
Which is the same as:
char* eLangPtr = &eLangAr[0]; // explicitly get the address of the first element
Now, while char* represents pointer to a character (which means it points to a single char), the char** represents a pointer to the char* pointer.
The difference:
char text[] = "Text";
char* chPointer = &ch[0];
char** chPointerPointer = &chPointer; // get the address of the pointer
std::cout << chPointer; // prints the address of 'text' array
std::cout << *chPointer; // prints the first character in 'text' array ('T')
std::cout << chPointerPointer; // prints the address of 'chPointer'
std::cout << *chPointerPointer; // prints the value of 'chPointer' which is the address of 'text' array
std::cout << *(*chPointerPointer); // prints the first character in 'text' array ('T')
As you can see, it is simply an additional level of indirection.
Pointers to pointers are used for the same reason "first-level" pointers are used - they allow you to take the address of a pointer and pass it to a function which may write something to it, modifying the content of the original pointer.
In this case it is not needed, this would be sufficient:
const char *langStrings [3]=
{
eLangPtr,
fLangPtr,
gLangPtr
};
And then:
menu (langStrings[0]);
I have learned that a pointer points to a memory address so i can use it to alter the value set at that address. So like this:
int *pPointer = &iTuna;
pPointer here has the memory address of iTuna. So we can use pPointer to alter the value at iTuna. If I print pPointer the memory address gets printed and if I print *pPointer then the value at iTuna gets printed
Now see this program
char* pStr= "Hello !";
cout<< pStr << endl;
cout<< *pStr << endl;
system("PAUSE");
return 0;
There are a lot of stuff I don't understand here:
In "Hello !" Each letter is stored separately, and a pointer holds one memory address. So how does pStr point to all the letters.
Also When I print out pStr it prints Hello !, not a memory address.
And when I print out *pStr it prints out H only not all what pStr is pointing too.
I really can't understand and these are my concerns. I hope someone can explain to me how this works ad help me understand
"Hello !" is an array of type char const[8] and value { 'H', 'e', 'l', 'l', 'o', ' ', '!', 0 }. pStr is a pointer to its first element; its last element has the value 0.
There is an overload in the iostreams library for a char const * argument, which treats the argument as a pointer to the first element of an array and prints every element until it encounters a zero. ("Null-terminated string" in colloquial parlance.)
Dereferencing the pointer to the first element of an array gives you the first element of the array, i.e. 'H'. This identical to pStr[0].
1-) Since pStr points to a char, it actually points to the beginning of an array of a null terminated string
2-) cout is overloaded with a char * argument. It will print out ever character in the string until it reaches the null character
3-) You are dereferencing the pointer to the first element of the character array.
1-) In "Hello !" Each letter is stored seperatly, and a pointer holds
one memory adress. So how does pStr point to all the letters.
The letters are stored in that order in each memory cell with an extra final cell
holding 0 to mark the end.
2-)Also When i print out pStr it prints Hello ! not a memory adress.
The cout << understands that you are pointing at a string and so prints the string.
3-)And when i print out *pStr it prints out H only not all what pStr
is pointng too.
The * means you are askign for the value at that address. cout << knows that the address holds a char and so prints the char.
Your understanding of pointers is correct in all respects.
Your problem is that the << operator has been overridden for various datatypes on a stream. So the standard library writers have MADE the operator << do something specific on any variable of the type char * (in this case the something specific means output the characters at that address until you get to the end of string marker) as opposed to what you expect it to do (print an address in decimal or hex)
Similarly the << operator has been overridden for char to just output a single character, if you think about it for a bit you will realise that *pStr is a dereferenced pointer to a character - that is it is a char - thus it just prints a single char.
You need to understand concept of strings as well. In C and C++, string is a few characters (char's) located one after another in a memory, basically, 'H','e','l','l','o','\0'. Your pointer holds memory address of the first symbol, and your C++ library knows that a string is everything starting this address and ending with '\0'.
When you pass char* to cout, it knows you output a string, and prints it as a string.
Construction *pStr means "give me whatever is located at address stored in pStr". That would be char - a single character - 'H', which is then passed to cout, and you get only one character printed.
A pointer, *pStr points to a specific memory address, but that memory address can be used not only as a single element, i.e. a char, but also as the beginning of an array of such elements, or a block of memory.
char arrays are a special type of array in C in that some operations handle them in a specific way: as a string. Hence, printf("%s", ... and cout know that when given a char * they should look for a string, and print all the characters until the terminating null character. Furthermore, C provides a string library with functions designed to manipulate such char * as strings.
This behavior is just as you'd expect from your own analysis: de-referencing pStr simply gives you the value at the memory address, in this case the first element of an array of chars in memory.
A pointer to an array (a C style string is an array of char) is just a pointer to the first element of the array.
The << operator is overloaded for the type char* to treat it as a C-style string, so when you pass it a char* it starts at the pointer you give it and keeps adding 1 to it to find the next character until it finds the null character which signals the end of the string.
When you dereference the pointer you the type you get is char because the pointer only actually points to the first item in the array. The overload of << for char doesn't treat it as a string, just as a single character.
Using strings like this is C-style code. When using C++ you should instead use std::string. It is much easier to use.
I have a small piece of code which does something funny, but I can't figure out how it does it.
int main(int argc, const char * argv[])
{
char text[] = "object";
for(char *ptr = &text[0]; *ptr != '\0'; ptr+=2)
{
cout << ptr << endl;
ptr--;
}
return 0;
}
What's happening is that it goes from [1], [2], [3] and so on, to the end of the string every time, printing the content out. I cant understand how it does that, as pointer never gets dereferenced, but right letters seems to get printed. I would assume that instead of the letters of the string, the pointer values would print as weird characters thats all, yet, that's not what happens.
This is undefined behavior. The first iteration, ptr points to "object". All good, prints that out, but then you do ptr--. So now, ptr points to memory you no longer own. As long as you don't dereference it or do pointer arithmetics on it, it's ok. But you do when you increment it in the loop - ptr+=2.
Why it's behaving like this:
At the first iteration, ptr points to "object", so it prints that. cout::operator << (const char*) prints a null-terminated string. No char needs dereferencing.
On the second iteration, ptr is decremented and then increased by 2, pointing to "bject". And so on...
Nothing really hacky here. There's an ostream::operator<<(const char *p) which prints a character string. The pointer is walked along the string and the program prints it starting from various positions. The only weird thing is the crazy +2, -1 pointer incrementing.
You are right, normally the address would be printed. Except there's a special overload for char *, which considers it as a C string and outputs all the characters, starting at ptr, up until it finds a zero (\0).
... or that would be what happens if your code was correct, because as it is now, it invokes UB by decrementing ptr on the first iteration (ptr moves out of range) and then incrementing it by 2 right after.
If you want to display the address of the pointer, cast it to void *:
cout << static_cast<void *>(ptr) << endl;
I am a bit confused when it comes to pointers.
Some sample code:
char str1[80];
char *p1;
cout <<"Enter a string"<<endl;
cin >> str1;
p1 = str1;
On the the last line of code, if str1 contains 'Test', how come p1 now contains 'Test'. Isn't p1 still a pointer? I thought pointers only contain addresses to other variables.
p1 doesn't contain Test. It contains the address of a byte in memory that is set to the ASCII value of the character T, followed by e, s, t, and a 0. That address is the address of the array str1, an 80 char array.
If you try to print str1 or p1, you'll get the output Test. This is because you cannot pass arrays to functions, so if you try to, the array name will decay into a pointer to the first element, just like p1. So str1 will decay to a pointer to the T and p1 is already a pointer to the T so you get the same output when printing either because they both point to the same address in memory.
p1 is a pointer.
That means that p1 contains the memory address of the first character of str1.
When you went to see what p1 "held", you probably did something like cout << p1, or cout << p1[3]. Either one of these will dereference p1, treating it as a pointer-to-array-of-characters.
To see the actual value of p1, try cout << (void*)p1. This will be the same as the actual value of str1 - a memory location which contains 'T', if you entered "Test".
Pointers hold address, nothing more. Sometimes you dereference pointers to get the data, other times you pass the pointer around to code that will dereference it.
For example :
p1 = 0; //Point to invalid memory address, but an address nonetheless
p1 = str1 //Point to a valid buffer. p1 now holds an new address, nothing else
if(*p1 == 'A') //Dereference the pointer (gives a character)
printf("The first character in str1 is A.\n");
You can emphasis the fact that p1 does not hold data other than the pointer by reorganizing your program like this :
char str1[80];
char *p1;
p1 = str1; //Point to un-initialized memory, your compiler might complain.
//but p1 is happy. It holds an address, it will never "hold" anything else.
//*p1 is valid (will not crash) but holds random garbage, do not use it!
cout <<"Enter a string"<<endl;
cin >> str1; //Now str1 was initialized
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("The first character in str1 is A.\n");
Now to emphasis the fact that p1 and str1 are the same thing (the same address in memory), add this to the program :
str1[0] = 'A'; //Put a capital A in str1
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("Now that we forced an A, this test is always true.\n");
What told you that p1 wasn't a pointer?
Functions and operators like cout::<< and printf are designed to print strings (as well as other data types) so they will appropriately dereference pointer arguments for you: give it a pointer to a string and it will print the string at that address. If you really want it to print the value of the pointer as an address, you have to cast it with (void *).
Do remember that, for array:
int array[N];
The usage of array would essentially mean &array[0], and therefore, following are same:
PrintAddress(&array[0]); // void PrintAddress(int*);
PrintAddress(array);
This way, when you do:
int *pAddress;
pAddress = &array[0];
PrintAddress(pAddress);
You can modify second line as:
pAddress = array;
And, just for completeness, following are same:
PrintAddress(&array[2]);
PrintAddress(array+2);
And so the following:
pAddress = array+5;
pAddress = &array[5];
printf("Address: %p\n", (void *)p1);
will print the address (from how to see address of a structure in printf).
printf("String: %s\n", p1);
will print the string.
The first is the actual content of p1, the second is what this content means in the context of your program: p1 is a pointer to char, which is the usual way in C to represent strings (ending with a 0 - '\0').