Pointer and char array confusion - c++

#include <iostream>
using namespace std;
int main()
{
char str[] {"TESTING"};
char *p {str};
cout << (p++, *++p);
cout << *p++;
cout << p;
return 0;
}
It returns "SSTING"
I know maybe this post isn't exactly for stackoverflow but I can't figure out what it does, and couldn't find any documentation about it
cout << (p++, *++p);
First time I saw round brackets with comma in cout... what's their function?
and shouldn't this line alone say "TESTING" but it seems to say only TING
cout << p;
Thank you!

Let's go line by line:
char str[] {"TESTING"};
This line defines a variable named str of type array of 8 chars, and initializes it with the characters TESTING plus a NUL char to mark the end.
char *p {str};
This one defines a variable named p of type pointer to char and initializes it to the address of the first char of the array str (the first T). This happens because the array automatically decays into a pointer in most uses.
cout << (p++, *++p);
This line does several things. The , operator first evaluates the left-hand operator p++, that increments the pointer, now points to the E; then it evaluates the right-hand operator *++p, but that is a pre-increment operator so it increments the pointer again (it points to S). Finally the * operator accesses to the memory pointed to by p, the result is a S. And that character is printed into STDOUT.
cout << *p++;
This one is easy. The * operator accesses the char pointed to by p (the S again) and prints it in STDOUT. Then it increments the pointer, because it is a post-increment operator. Now it points to the second T.
cout << p;
And at least, this line prints the string pointed to by p until it finds a NUL character. Since p is pointing to the second T of your array it will print TING.
Putting all those outputs together you get SSTING.

Not exactly an answer, but a breakdown of what was the code doing,
#include <iostream>
using namespace std;
int main()
{
char str[]{"TESTING"};
char *p{str}; // p points to: 'T'
p++; // p points to: 'E'
++p; // p points to: 'S'
cout << *p; // output a single char: 'S'
cout << *p; // ouptut a single char: 'S'
p++; // p points to: 'T'
cout << p; // output a (char *) type pointer, AKA a C-string, "TING";
return 0;
}

Related

Pointer printing first char of string

#include <iostream>
using namespace std;
char* input(char **S);
int main()
{
char **S = new char *;
char *K = input(S);
//cout << K << endl;
cout << *K << endl;
}
char* input(char **S)
{
cout << "Enter string: ";
cin >> *S;
cout << S << endl; // Prints address of S
cout << *S << endl; //Prints content of address stored in S
return *S;
}
I am failing to understand why when I print out *K, I just get the first character of the input string but if I print out the commented line(just K alone) I get the whole string. Any help with explaining what I am not able to see or understand is appreciated.
Let's understand how arrays work:
// Let's say I have one character array
char arr[] = {'a', 'b', 'c', 'd'};
In here, the name of the array i.e. arr acts as the pointer to the first element of the array. However, do note that it is NOT the pointer to the first element to avoid confusion, it just have an implicit conversion to pointer of element type. More details can be found here: https://stackoverflow.com/a/1641963/10821123
Now since array is contiguous, the rest of the elements can be determined.
// so ideally, the below two statements would print the same thing
cout << &arr << endl;
cout << (void*) &arr[0] << endl;
// the above line just takes out the address of the first pointer
Now coming to your question, I'll convert my example to a string one:
char *K = "abc";
cout << *K << endl; // a
cout << K << endl; // abc
Note that the above assignment of char *K = "abc"; will give you a warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
The pointer only holds the address of the first element of the array, so when you dereference the pointer, it prints the first element, i.e. *K is interpreted as K[0]
Now there's an overload of operator <<, so what it does is if it sees a character pointer i.e. char*, it prints the complete null-terminated string, that's why in your case too, it is printing the whole string.

Why strstr() - char pointer = number?

I have this program:
#include <iostream>
#include <conio.h>
#include <string.h>
using namespace std;
int main()
{
char char1[30] = "ExtraCharacter", char2[30] = "Character", *p;
p = strstr(char1, char2);
cout << "p: " << p << endl;
cout << "char1: " << char1 << endl;
cout << "(p-char1): " << (p-char1) << endl;
return 0;
}
When I run it, I get:
p: Character
char1: ExtraCharacter
(p-char1): 5
as expected.
But this is not the problem, I'm not sure why "Character" - "ExtraCharacter" is an integer (5)? Perhaps not an integer, but a number/digit anyways.
Actually I don't understand why is "Character" stored in p, and not the memory address.
If I understood well from a book, strstr() returns a memory address, shouldn't it be more like a strange value, like a hex (0x0045fe00) or something like that? I mean, it's cout << p not cout << *p to display the actual value of that memory address.
Can someone explain me how it works?
P.S.: I apologize if the title is not that coherent.
But this is not the problem, I'm not sure why "Character" - "ExtraCharacter" is an integer (5)?
You subtract one pointer from another and result - number, distance from char char1 points to to char p points to. This is how pointer arithmetic works.
Note: this subtraction is only valid when both pointers point to the same array (or behind the last element), which is the case in your code, but you need to be careful. For example if strstr() does not find susbtring then it would return nullptr and your subtraction will have UB. So at least check p before subtracting (and passing nullptr to std::cout would have UB as well)
If I understood well from a book, strstr() returns a memory address, shouldn't it be more like a strange value, like a hex (0x0045fe00) or something like that? I mean, it's cout << p not cout << *p to display the actual value of that memory address.
Yes p is a pointer aka memory adress. std::ostream has special rule how to print pointers to char - as strings, because strings in C stored that way. If you want to see it as a pointer just cast it:
std::cout << static_cast<void *>( p );
then you will see it as an address.
To display address, you have to cast char* to void*:
std::cout << "p: " << static_cast<const void*>(p) << std::endl;
Demo
For std::basic_ostream (type of cout), character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<< which are being treated as strings. char[30] will be decayed to const char* argument and basic_ostream will output the null terminated string at the address of the pointer.
As for (p-char1), the result of subtracting two pointers is a std::ptrdiff_t. It is an implementation-defined signed integer. That's why the output is 5

Why doesn't a pointer to an element in a c-string return just the element?

I'm trying to understand how pointers work here. The findTheChar function searches through str for the character chr. If the chr is found, it returns a pointer into str where the character was first found, otherwise nullptr (not found). My question is why does the function print out "llo" instead of "l"? while the code I wrote in main return an "e" instead of "ello"?
#include <iostream>
using namespace std;
const char* findTheChar(const char* str, char chr)
{
while (*str != 0)
{
if (*str == chr)
return str;
str++;
}
return nullptr;
}
int main()
{
char x[6] = "hello";
char* ptr = x;
while (*ptr != 0)
{
if (*ptr == x[1])
cout << *ptr << endl; //returns e
ptr++;
}
cout << findTheChar("hello", 'l') << endl; // returns llo
}
A C-string is a character buffer that is terminated by a '\0' character. Passing them around involves just passing a pointer to the first element.
All the library routines know that they may read characters starting at the address they are given, until they reach '\0'. Since that's how operator<< for std::cout is designed, it assumes you pass it the starting address of a C-string. That's the contract.
If you want to print a single character, you'll need to dereference that pointer.
cout << findTheChar("hello", 'l') << endl; //returns llo
Return type of findTheChar is const char *. When you try to print a const char * with std::cout it would print the character array pointed by the address upto terminating \0 character.
str -> +---+---+---+---+---+---+
| h | e | l | l | o | \0|
+---+---+---+---+---+---+
^
|
findTheChar(str, 'l')
If you want just one character, dereference the address (If it is not null). If you want to print the return address, you can typecast it to void *.
while the code i wrote in main return an "e" instead of "ello"
cout << *ptr << endl; //returns e
Here you are explicitly dereferencing the ptr as *ptr and thus you are printing a char and not const char *.
As you are using C++, you would be better with std::string and iterators.
// Returns offset of first occurance if found
// Returns -1 if not found
int findTheChar(const std::string& str, char chr );
My question is why does the function print out "llo" instead of "l"?
Because you are asking it to, when you print what the function returns.
The return value of your function is a string: const char*.
As a result, cout will start printing the string, starting from where the pointer points to (a char), until it meets a null-C-string-terminator ('\0').
If you wanted just the character, you should dereference the returned pointer during the printing phase, like this:
const char* ptr = findTheChar("hello", 'l');
if(ptr)
cout << *ptr << endl; //prints l
else
cout << "Character not found" << endl;
BTW, unrelated to your question, did you compile your code with warnings enabled (e.g. by using Wall and Wextra flags)?
In function 'int main()':
21:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
if (*ptr == x[1])
^~
23:13: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
ptr++;
^~~
It comes from this part:
if (*ptr == x[1])
cout << *ptr << endl; //returns e
ptr++;
A pointer of type char* points to a memory location and the content is interpreted as a single character. So if you write
char* x = "Hallo";
x points to 'H'. If you write
std::cout << *x << std::endl;
the output operator of std::cout is called with the single char.
But if you write
std::cout << x << std::endl;
you have the special case, where the output operator of std::ostream interprets the char* as a pointer to a C like string which is null terminated. So x points to a single char but ostream operator for char* interprets this as a pointer to the first character of a string.
Return *str and change the function return type. This should work just fine.

pointers *char and &char

I have doubt on below programme
#include "stdafx.h"
#include "stdio.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char *chr = "hello";
cout<<chr; //hello
cout<<endl;
cout<<*chr; //h
cout<<endl;
cout<<*(&chr); //hello
system("pause");
return 0;
}
why second cout prints h where as third one prints hello when represents the same
To be a little bit more explicit. chr is a pointer pointing to a chunk of memory where the characters 'h','e','l','l' and 'o' are stored. After the last character of chr is a terminating \0. This is needed to signal that the chunk pointed by chr is now over.
When passing chr to cout, cout will read (not cout it self but the underlying function wich is called by using the << operator) this chunk up to the terminating \0. When passing *chr to cout you dereference the pointer and simply pass the first character pointed by chr to cout ('h').
*(&chr) is the same thing as just chr because the adress-of operator gives you the adress of chr wich is a pointer to a pointer to character. Dereferencing it using * will then give you the pointer pointing to the chunk of memory starting with 'h' and coutwill again read up to the terminating \0.
EDIT
As birdypme pointed out correctly, the * operator (dereferencing operator) is the inverse to the address-of operator. It is like + and -. Therefore something like this
cout << *(&(*(&chr))) << endl;
will still be the same as
cout << chr << endl;
You can do this to infinity if you like to.
cout << *(&(*(&(*(&(*(&(*(&(*(&(*(&chr))))))))))))) << endl; // I hope i didn't miss a ')'
Because in the second case, you are passing to cout a single char, the one pointed by chr, that is the first of the C-string "hello".
In the second example you are dereferencing the pointer. This is the same as using chr[0] and in this case it is h.
In the last example you are taking the address of chr and then dereferencing:
&chr --> char**
*(&chr) --> char*
So at the and you again have a char*
Your statement
cout<<*chr; is same as cout<<chr[0];
because the pointer is dereferenced and passes only the first character pointed by chr
In case of cout<<*(&chr); , if i convert it into words, it would be, print the value present at the address of chr. Now since chris a pointer, you will get a pointer to a pointer by this statement &chrand the again you are dereferencing it, which gives you hello.

Pointer to character array in C++

I do not understand the following:
int main() {
char ch[13] = "hello world";
function(ch);
return 0;
}
void function( char *ch) {
cout << ch;
}
This outputs "hello world". But if I derefference the pointer ch the program outputs the first letter i.e. "h". I cannout figure out why.
cout << *ch;
As someone stated in the comments section the result of derefferencing the pointer to an array is a plain char.
Let me explain why:
Your ch pointer indicates the adress of the start of the char array, so when you call cout<<ch it will show on the screen all you have in the memory starting from the ch adress and goes secquentially till a first NULL value appears and stops.
And when you call cout<<*ch it will take the value that you have stored on the start adress of the array which is h.
Derefferencing means that you take the value from a specific adress.
Hope it helped! :)
When you pass an array into a function, either directly or with an explicit pointer to that array, it has decayed functionality, in that you lose the ability to call sizeof() on that item, because it essentially becomes a pointer.
So it's perfectly reasonable to dereference it and call the appropriate overload of the stream << operator.
More info: https://stackoverflow.com/a/1461449/1938163
Also take a look at the following example:
#include <iostream>
using namespace std;
int fun(char *arr) {
return sizeof(arr);
}
int fun2(char arr[3]) {
return sizeof(arr); // It's treating the array name as a pointer to the first element here too
}
int fun3(char (&arr)[6]) {
return sizeof(arr);
}
int main() {
char arr[] = {'a','b','c', 'd', 'e', 'f'};
cout << fun(arr); // Returns 4, it's giving you the size of the pointer
cout << endl << fun2(arr); // Returns 4, see comment
cout << endl << fun3(arr); // Returns 6, that's right!
return 0;
}
or try it out live: http://ideone.com/U3qRTo