Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointers and Strings C++

Tags:

c++

pointers

I'm teaching myself C++ and I'm a bit confused about pointers (specifically in the following source code). But first, I proceed with showing you what I know (and then contrasting the code against this because I feel as if there are some contradictions going on).

What I know:

int Age = 30;
int* pointer = &Age;

cout << "The location of variable Age is: " << pointer << endl;
cout << "The value stored in this location is: " << *pointer << endl;

Pointers hold memory addresses. Using the indirection (dereference) operator (the *), you can access what is stored in memory location of the pointer. Onto the code in this book I'm having trouble understanding...

cout << "Enter your name: ";
string name;
getline(cin, name); //gets full line up to NULL terminating character

int CharsToAllocate = name.length() + 1; //calculates length of string input
                          //adds one onto it to adjust for NULL character
char* CopyOfName = new char[CharsToAllocate];
// pointer to char's called CopyOfName, is given the memory address of the 
//beginning of a block
//of memory enough to fit CharsToAllocate. Why we added 1? Because char's need a 
//NULL terminating character (\0)

strcpy(CopyOfName, name.c_str()); //copies the string name, into a pointer?

cout << "Dynamically allocated buffer contains: " << CopyOfName << endl;
delete[] CopyOfName; //always delete a pointer assigned by new to prevent memory leaks

Output:

Enter your name: Adam
Dynamically allocated buffer contains: Adam

The comments in the above code are my comments. My problem begins with strcpy. Why is name.c_str() copied into a pointer CopyOfName? Does this mean that all strings are essential pointers? So like string testing = "Hello world"; Is actually a pointer pointing to the memory location where "H" is stored?

Next, why is it in the print out statement using CopyOfName and not *CopyOfName? Pointers hold memory addresses? Using *CopyOfName would print out the contents of the memory location. I tried this in Code::Blocks and if the input text was "Hello World." Using *CopyOfName in the print out statement would just give an "H". This makes sense since when I declared that I needed a memory block with the 'new' thing, this actually returns a pointer to the first part of the dynamically allocated memory block.

The only way I can reconcile this is if a string is actually a pointer.

string testing = "Confused";
cout << testing << endl;

would print out the word "Confused"

However, if I try to compile

string testing = "Confused";
cout << *testing; 

I get an error message.

Basically, to summarize my question, I'm trying to understand the code with strcpy and the cout statement.

like image 967
DWade64 Avatar asked Dec 27 '13 04:12

DWade64


People also ask

What is string and pointer in C?

String is a data type that stores the sequence of characters in an array. Every string terminates with a null character (\0), indicating its termination. A pointer to string in C can be used to point to the base address of the string array, and its value can be dereferenced to get the value of the string.

How do you access string through pointers?

Accessing string using pointer Using char* (character pointer), we can access the string.

How are strings represented in memory in C?

A string constant in C is represented by a sequence of characters within double quotes. Standard C character escape sequences like \n (newline), \r (carriage return), \a (bell), \0x17 (character with hexadecimal code 0x17), \\ (backslash), and \" (double quote) can all be used inside string constants.


2 Answers

It seems like you understand what C-style strings are, but to summarize, they are just arrays of characters in memory, by convention terminated by a nul character \0. Usually they are referenced via a char* pointing to the first letter in the string. When they are printed, typically the characters of the string are printed starting from the first, and printing (or copying, etc.) stops when the \0 terminator is reached.

An std::string is a class that (typically) wraps a C-style string. This means that a std::string object (typically) has a private C-style string that is used to implement its functionality. The function std::string::c_str() returns a pointer to this underlying C-style string.

Let's suppose that char *str; points to a C-style string. If you attempt to run cout << *str << endl;, you noticed that only the first character is printed. That is because of C++'s function overloading. The data type of *str is char, so the char version of cout is called and faithfully prints the single character *str. For compatibility with C-style strings, the version of cout that takes a char* as an argument treats the pointer as a C-style string for printing purposes. If you cout an int*, for example, the underlying int will not be printed.

Edit: Another comment:

The reason that your attempt to dereference an std::string object failed is that, indeed, it is not a pointer. You could dereference the return value of std::string::c_str(), and you would get back the first char of the string.

Related: How is std::string implemented?.

like image 174
Andrey Mishchenko Avatar answered Oct 08 '22 01:10

Andrey Mishchenko


In C, strings are simply arrays of characters. And arrays decay to pointers when used as the argument to a function.

In C++, std::string is a class. It includes a C-style character array within it, and this is what c_str() returns. But the string itself is not a pointer, so you can't dereference it; you have to use the c_str() method to get a pointer to the string contents.

like image 5
Barmar Avatar answered Oct 08 '22 01:10

Barmar