address of first string element yields unexpected result - c++

The goal is to write a function that outputs the address of the first element of a string that is equal to a character, however I am confused by the result.
When evaluating the function with a string that contains said character in the first place, I get a difference of 2 bytes between the address of the beginning of the string and the address of the first element. E.g. 0x7ffe559716d0 and 0x7ffe559716e0.
Shouldn't the address be the same?
#include <iostream>
#include <string>
using namespace std;
const char* first_char(const char* str, const char ch)
{
for (int i = 0; str[i] != 0; ++i)
{
if (str[i] == ch)
return (i+str);
}
return 0;
}
int main() {
string str1 = "jasdfgjhk";
const char ch1 = 'j';
cout << &str1 << endl;
//should be the same address as above?
cout << (void*)first_char(&str1[0], ch1) << endl;
return 0;
}

Change this:
cout << &str1 << endl;
to this:
cout << (void*)str1.data() << endl;
and you will get the same address as the one returned by your function.
The reason is that std::string is not just an array of characters, it's a class, who has a data member that is an array and stores the characters of the string.
By using data(), you are getting that array. When you print its address it gives you the actual address of the array, and of the class as before

Please note that
&str
is the starting address of 'string' object. The string object is not the string itself. It contains a (hidden) dynamic pointer that points to the string itself. So by the above you get "something" like a pointer to a pointer to the string.
But with:
&str1[0]
you really get a pointer to the first character in the string.

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 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.

char array/string is empty when sent to function

I have a function that at the moment doesn't do anything because the char array I send as parameter has no value. I can write out the data before the function and get the expected output but if I write out in the function nothing come out even if It's the first thing I do.
I first write out the string and then convert it to a char array. I have also tried with just a normal string as parameter with the same result.
std::cout << block;
block = this->removeNullCharacters(block.c_str());
Output of the first cout is : "0/"
The output of the function below is nothing. Nothing at all is shown up in the console.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; i < 512; ++i){
std::cout << i << ": " << input[i];
/*if(input[i] == '\0'){
return out;
}
else{
out += input[i];
}*/
}
return out;
}
Not clear at all what you try to achieve or, in other words, you question is not complete.
input is a pointer to char and points to the first element of an array of chars of size 512.
out is an empty string and returned at the end of the function.
block is schizophren, a pointer to char and a std::string at the same time i guess. You need to fix this one really.
Try this. I think you want to pass a pointer to a sequence of chars to the function and concatenate each char to the string until the end of the sequence (which is terminated by \0). Forget about the size completely and simply use the null termination as a loop condition.
std::string FileSystem::removeNullCharacters(const char * input){
std::string out = "";
for(int i = 0; input[i] != '\0'; ++i){
std::cout << i << ": " << input[i];
out += input[i];
}
return out;
}
But you gotta make sure you pass in an array of chars or a valid pointer to char (which is the beginning of a sequence of chars and the last element is \0).

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

how to print char array in c++

how can i print a char array such i initialize and then concatenate to another char array? Please see code below
int main () {
char dest[1020];
char source[7]="baby";
cout <<"source: " <<source <<endl;
cout <<"return value: "<<strcat(dest, source) <<endl;
cout << "pointer pass: "<<dest <<endl;
return 0;
}
this is the output
source: baby
return value: v����baby
pointer pass: v����baby
basically i would like to see the output print
source: baby
return value: baby
pointer pass: baby
You haven't initialized dest
char dest[1020] = ""; //should fix it
You were just lucky that it so happened that the 6th (random) value in dest was 0. If it was the 1000th character, your return value would be much longer. If it were greater than 1024 then you'd get undefined behavior.
Strings as char arrays must be delimited with 0. Otherwise there's no telling where they end. You could alternatively say that the string ends at its zeroth character by explicitly setting it to 0;
char dest[1020];
dest[0] = 0;
Or you could initialize your whole array with 0's
char dest[1024] = {};
And since your question is tagged C++ I cannot but note that in C++ we use std::strings which save you from a lot of headache. Operator + can be used to concatenate two std::strings
Don't use char[]. If you write:
std::string dest;
std::string source( "baby" )
// ...
dest += source;
, you'll have no problems. (In fact, your problem is due to the fact
that strcat requires a '\0' terminated string as its first argument,
and you're giving it random data. Which is undefined behavior.)
your dest array isn't initialized. so strcat tries to append source to the end of dest wich is determined by a trailing '\0' character, but it's undefined where an uninitialized array might end... (if it does at all...)
so you end up printing more or less random characters until accidentially a '\0' character occurs...
Try this
#include <iostream>
using namespace std;
int main()
{
char dest[1020];
memset (dest, 0, sizeof(dest));
char source[7] = "baby";
cout << "Source: " << source << endl;
cout << "return value: " << strcat_s(dest, source) << endl;
cout << "pointer pass: " << dest << endl;
getchar();
return 0;
}
Did using VS 2010 Express.
clear memory using memset as soon as you declare dest, it's more secure. Also if you are using VC++, use strcat_s() instead of strcat().