How is char* textMessages[] formatted in memory? - c++

As we know, multi-array like int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}}; is contiguous, so it is exactly the same as int array2[6] = { 0, 1, 2, 3, 4, 5 };
for (int *p = *array1, i = 0; i < 6; i++, p++)
{
std::cout << *p << std::endl;
}
0
1
2
3
4
5
Then, I have these codes:
char *textMessages[] = {
"Small text message",
"Slightly larger text message",
"A really large text message that ",
"is spread over multiple lines*"
};
I find that its layout is not the same as int[3][2]:
For every sub message, like "Small text message", every alpha is contiguous and offset is 1(sizeof(char) == 1).
However, the final element of "Small text message" -- e and the first element of "Slightly larger text message" -- S is not contiguous in memeary:
char *textMessages[] = {
"Small text message",
"Slightly larger text message",
"A really large text message that ",
"is spread over multiple lines*"
};
char *a = *(textMessages)+17, *b = *(textMessages + 1), *c = *(textMessages + 1) + 27, *d = *(textMessages + 2), *e = *(textMessages + 2) + 31, *f = *(textMessages + 3);
std::ptrdiff_t a_to_b = b - a, c_to_d = d - c, e_to_f = f - e;
printf("they(a b c d e f) are all messages's first or final element: %c %c %c %c %c %c\n", *a, *b, *c, *d, *e, *f);
printf("\n\naddress of element above: \n%p\n%p\n%p\n%p\n%p\n%p\n", a, b, c, d, e, f);
printf("\n\nptrdiff of a to b, c to d and e to f: %d %d %d\n", a_to_b, c_to_d, e_to_f);
they(a b c d e f) are all messages' first or final element: e S e A t i
address of element above:
002F8B41
002F8B44
002F8B5F
002F8B64
002F8B83
002F8B88
ptrdiff of a to b, c to d and e to f: 3 5 5
My question is:
What does 3 5 5 mean here?
Why 3 5 5, not 5 5 5
What's the layout here?
Edit:
I don't think this question duplicates of How are multi-dimensional arrays formatted in memory?, because what I ask is not the same as that question's doubt and the solution should not that's question's answers.

How is char* textMessages[] formatted in memory?
Just like other single dimensional arrays. Each element is stored in a consecutive memory location. Those elements are pointers to char object.
Each of those pointers point to the beginning of a string literal. String literals have static storage duration, and their memory location is implementation defined.
What does 3 5 5 mean here?
You've done pointer subtraction between pointers that do not point to the same array (each string literal is a separate array). The behaviour of the program is technically undefined because of this.
In practice, most of the time, what you get is the distance of the pointed values in memory. Since the location of those arrays is implementation defined, there isn't anything meaningful about those values.
Why 3 5 5, not 5 5 5
Because the behaviour is undefined
Because that happens to be the distance between the pointer character objects. The distance will depend on where the compiler chooses to store the string literals.
You can pick either explanation depending on your point of view.
PS. You are converting the string literals to a pointer to non-const char. This conversion has been deprecated ever since C++ was standardized and has been ill-formed since C++11.
PPS. Accessing int *p = *array1 beyond the bounds of array1[0] which has the size 2, as in your first code snippet, technically has undefined behaviour. Same applies to *(textMessages + 2) + 31 in the second.

String literals have Static storage duration meaning that they are allocated in memory when the program starts but they are not assured to be in contiguous memory from one another as, at this point, the program might not even know they are in an array.
When the array is then constructed the addresses of those strings are placed in contiguous memory (but, of course, not the string themselves)
P.S.
What I refer as "strings" in the above really means "string literal"

On a language lawyer point of view, this:
int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};
for (int *p = *array1, i = 0; i < 6; i++, p++)
{
std::cout << *p << std::endl;
}
is undefined per standard, because array1 is an array of 3 arrays of size 2. So 0 and 1 are is same array, but not 1 and 2 so incrementing the pointer is correct at first time but the second incrementation makes it point past the first array (which is correct) so dereferencing it is formally UB.
Of course, any current and past implementation do accept it.
But this is a quite different animal:
char *textMessages[] = {
"Small text message",
"Slightly larger text message",
"A really large text message that ",
"is spread over multiple lines*"
};
Here textMessages is an array of pointers and not a 2D array. But it is even worse. It is an array of 4 char * pointers pointing to string litterals, and it is undefined behaviour to modify a string litteral. That means that textMessages[0][0] = 'X'; is likely to crash the program.
But once we know we have an array of pointers to string litterals, all becomes clear: the compiler has stored the string litterals in memory the way it wanted, and has just given pointers to that memory. So the 3,5,5 are just padding values because your compiler has decided to store text litteral that way.

3 5 5 means nothing here, as well as 5 5 5 .
char *textMessages[] is an char* array, the elements of it are pointers. And they (the pointers) are contiguous in the array. But the value of these pointers are not that related. The strings in your code may existed in different places.
The result on my compiler is: 243 309 1861

Related

How does C++ find the size of an array?

Difference From Other Questions
I am not asking how to find the size, but how the computer finds the size.
Goal
I want to find out how C++ finds the size of an array (using sizeof(array)), and a 2D array (using sizeof(array)).
When I ran the code, I thought the output would be 3 and 6. But it was 12 and 24!? How do I make the the output 3 and 6?
I don't know how to calculate the size of an array, so when I say "an output of three/six", I mean the amount of numbers in the array.
Code
#include <iostream>
using namespace std;
int main()
{
int oneDArray [3] = {1, 2, 3};
int twoDArray [2][3] = {{1, 2, 3}, {1, 2, 3}};
cout << sizeof(oneDArray) << "\n" << sizeof(twoDArray);
return 0;
}
The sizeof operator returns the size in bytes, not elements.
For single dimensional arrays (not passed as a function argument, which would cause decay to a pointer), you can get the element count by dividing the size of the array by the size of the first element, e.g.
sizeof(oneDArray) / sizeof(oneDArray[0]) // Gets 3
For multidimensional arrays, that would tell you the size of the first dimension, not the number of elements total, so you'd need to drill down deeper:
sizeof(twoDArray) / sizeof(twoDArray[0]) // Gets 2 (first dimension of array)
sizeof(twoDArray) / sizeof(twoDArray[0][0]) // Gets 6 (number of elements)
You can of course explicitly name the type of an element to avoid nested indexing (sizeof(twoDArray) / sizeof(int) get 6 just fine), but I avoid it as a rule; it's too common for an array to change types during development (say, it turns out you need to use int64_t because you have values into the trillions), and if the whole expression isn't in terms of the array, it's easy to overlook it and end up with broken code.
sizeof returns bytes, if you expect number of elements, divide by the size of each element
cout << sizeof(oneDArray)/sizeof(int) << "\n" << sizeof(twoDArray)/sizeof(int);
Output:
3
6

Why do you have to specify an index number when assigning a value to the first element in an array?

Why do you have to specify an index number when assigning a value to the first element in an array?
Let's say we had this array:
int childer[] = {10, 30, 50};
then both childer and childer[0] would be accessing the first element of the array, so why can't you dochilder = 15;?
Arrays are similar to pointers. For example an array decays to a pointer when passed to a function, or even when the operators [] and the unary * are applied to them (Thanks StoryTeller). So
childer[0]
is equivalent to
*childer
and you can do
*childer = 15;
to set the first element to 15.
childer
on the other hand is the same as
&childer[0]
childer[0] and childer have two different meanings. childer[0] is the first element of the array while childer is a pointer to the first element. In order to get the first element using the pointer, you have to use *childer.
so,
*childer = 15;
can be used for assignment.
you could dereference the name of the array, but just trying to do
childer = -999;
is completely wrong...
see the example below:
int main() {
int childer[] = { 10, 30, 50 };
cout << childer[0] << endl;
cout << *childer << endl;
//now write
childer[0] = 200;
cout << childer[0] << endl;
cout << *childer << endl;
//now write again
*childer = -999;
cout << childer[0] << endl;
cout << *childer << endl;
return 0;
}
First of all
int childer[] = { 10, 20, 30 };
...
childer = ....; <--- THIS WILL NOT COMPILE, as childer is not an lvalue.
you cannot say childer = 20;, you can say childer[0] = 20; or *childer = 20;, or even more *(childer + 1) = 20; (to access other elements than the first), but you cannot use childer as the whole array in an assignment. Simply, neither C nor C++ allow this.
Arrays and pointers are very different things. What confuses you, is that neither C, nor C++ have a way to reference the array as a whole, and the array identifier, by itself, means the address of the first element (and not a pointer but a reference). What I mean by a reference, and I don't use the word pointer for just now, is that a pointer normally refers to a variable of pointer type, and as a variable, can be modified (mainly because the array position cannot be changed at runtime). You cannot write something like array = something_else;, when array is an array. Array names cannot be used by themselves as lvalues, only as rvalues. This can be done with pointers, like
int childer[] = { 10, 20, 30, };
int *pointer = childer;
and then
pointer = some_other_place_to_point_to;
because pointer is a pointer and childer isn't.
The meaning that both languages attribute to the array name is just a pointer rvalue pointing to the address of the first element (and typed as the cell type, continue reading for an explanation on this). And this is not the same as the address of the array (both are different things, demonstrated below) as the first (the array name is a pointer to cell type, while the array address &childer is a pointer to the whole array type). This can be illustrated with the next program, which tries to show you the difference in sizes for the array element, the whole array, the array pointer and the cell pointer:
#include <stdio.h>
#include <sys/types.h>
#define D(x) __FILE__":%d:%s: " x, __LINE__, __func__
#define P(fmt, exp) do { \
printf(D(#exp " == " fmt "\n"), (exp)); \
} while(0)
#define TR(sent) \
sent; \
printf(D(#sent ";\n"))
int main()
{
int i = 1;
TR(double a[10]);
P("%p", a);
P("%p", &a);
P("%d", sizeof a);
P("%d", sizeof &a);
P("%d", sizeof *a);
P("%d", sizeof *&a);
return 0;
}
which executes into (I selected double as the type of cell to make evident the differences while trying to be more architecture independent):
$ pru
pru.c:16:main: double a[10]; <-- array of ten double's (a double is 8 bytes in many architectures)
pru.c:18:main: a == 0xbfbfe798 <-- address values are
pru.c:19:main: &a == 0xbfbfe798 <-- equal for both.
pru.c:20:main: sizeof a == 80 <-- size of whole array.
pru.c:21:main: sizeof &a == 4 <-- size of array address (that's a pointer to array)
pru.c:22:main: sizeof *a == 8 <-- size of pointed cell (first array element)
pru.c:23:main: sizeof *&a == 80 <-- size of pointed array.
But you are wrong when saying that you cannot use an expression to access the other elements, as you can, use array + 1 to mean the address of the second element, and array + n to access the address of the n + 1 element. Evidently array + 0 is the same as array (the 0 number is also neutral in pointer addition), so you can get on it easily. Some people like to write it for fun also as 0+array (to abuse of the commutativity of the + operator) and go further, to write something like 0[array], to refer to the first element of the array (this time the access being to the element, and not to its address) I don't know if this continues to be valid with the new standards, but I'm afraid it continues, perhaps, to allow for legacy code to be compilable (adding to the controversy of what should be conserved and what can be eliminated on standard revisions)

Multi-dimensional arrays and pointers in C++

Let's say I declare and initialize the following multi-dimensional array in C++:
unsigned a[3][4] = {
{12, 6, 3, 2},
{9, 13, 7, 0},
{7, 4, 8, 5}
};
After which I execute this code:
cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4
I just don't understand what is happening here.
a is the address of the first element, right? In single-dimensional arrays, *a should be the value of the first element, but instead it's the same as a?! What does *a even mean in this context?
Why is a + 1 different from *a + 1?
You should try and find some good documentation about pointers, arrays, and array-to-pointer decay. In your case, unsigned a[3][4] is a bi-dimensional array of type unsigned [3][4]. Whenever you refer to it as a, it decays to a pointer to unsigned[4], so the decayed type of a is unsigned (*)[4]. Therefore dereferencing it gives you an array, so *a is the array [12, 6, 3, 2] (technically it's the pointer to the first element into the array).
Now, a+1 means "increment the pointer to unsigned[4] by 1", in your case it "jumps" 4 unsigneds in the memory, so now a+1 points to the "row" indexed by 1 in your example. Dereferencing it *(a+1) yields the array itself ([9,13,7,0]) (i.e. the pointer to the first element of it), and dereferencing again gives you the first element, i.e. **(a+1) equals 9.
On the other hand, *a+1 first dereferences a, so you get the first row, i.e. [12,6,3,2] (again, technically the pointer to the first element of this row). You then increment it by one, so you end up pointing at the element 6. Dereferencing it again, *(*a+1), yields 6.
It may be helpful to define a equivalently as
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it's a bit more clear how dereferencing works
Two dimensional array is array of array.
You can visualize a as
a = { a[0], a[1], a[2]}
and a[0], a[1], a[2] as
a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};
Analysis of your first question
a is the address of the first element, right?
Yes a is the address of the first element, and first element of a is a[0] which is the address of the first element of a[0][0].
*a should be the value of the first element, but instead it's the same as a?
Yes *a should be the value of the first element that refer a[0]. And we see a[0] is the address of a[0][0] so as a . Thus *a have same value as a which is the address of a[0][0].
What does *a even mean in this context?
Previously answered, *a is the address of first arrays first element a[0][0], and *(a+1) is the address of second arrays first element a[1][0].
And analysis of your second question
Why is a + 1 different from *a + 1?
At this time perhaps you can answer your owns question.
a is the address of a[0] then
a+1 is the address of a[1] which hold address of a[1][0].
You can print the value by
cout<<**(a+1)<<endl; // 9
Other way *a is the value of a[0] which is the address of a[0][0].
So *a+1 is the address of a[0][1]. You can print the value as
cout<<*(*a+1)<<endl; // 6

Two- and one-dimensional arrays equivalence in C++

It is known that two- and one-dimensional arrays can be used equivalently, by simple coordinate conversion. Is such equivalence guaranteed by the C++ standard, or maybe it's the most convenient way of organizing data, but doesn't have to be obeyed everywhere?
For example, is the following code compiler-independent?
std::ofstream ofbStream;
ofbStream.open("File", std::ios::binary);
char Data[3][5];
for(int i=0; i<3; ++i)
for(int j=0; j<5; ++j)
{
Data[i][j] = (char) 5*i+j;
}
ofbStream.write(&Data[0][0], 15);
ofbStream.close();
The program is expected to write the numbers: 0, 1, 2, ..., 14 to a file.
In practice, this is just fine. Any compiler that doesn't do that would have countless problems with existing code.
Very strictly speaking, though, the pointer arithmetic needed is Undefined Behavior.
char Data[3][5];
char* p = &Data[0][0];
p + 7; // UB!
5.7/5 (emphasis mine):
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that that difference of the subscripts of the resulting and original array elements equals the integral expression. ... If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
The Standard does guarantee that all the array elements are adjacent in memory and are in a specific order, and that dereferencing a pointer with the correct address (no matter how you got it) refers to the object at that address, but it doesn't guarantee that p + 7 does anything predictable, since p and p + 7 don't point at elements of the same array or past-the-end. (Instead they point at elements of elements of the same array.)
In his book The C++ Programming Language, Bjarne Stroustrup mentions (C.7.2; p. 838 of the Special Edition, 2000):
... We can initialize ma like this:
void int_ma() {
for(int i=0; i<3; i++)
for(int j=0; j<5; j++) ma[i][j] = 10 * i + j; }
...
The array ma is simply 15 ints that we access as if it were 3
arrays of 5 ints. In particular, there is no single object in memory
that is the matrix ma - only the elements are stored. The dimensions 3
and 5 exist in the compiler source only.
(emphasis mine).
In other words, the notation [][]...[] is a compiler construction; syntactical sugar if you will.
For entertainment purposes, I wrote the following code:
#include<cstdlib>
#include<iostream>
#include<iterator>
#include<algorithm>
int main() {
double ma[5][3]; double *beg = &ma[0][0]; // case 1
//double ma[3][5]; double *beg = &ma[0][0]; // case 2
//double ma[15]; double *beg = &ma[0]; // case 3
double *end = beg + 15;
// fill array with random numbers
std::generate(beg, end, std::rand);
// display array contents
std::copy(beg, end, std::ostream_iterator<double>(std::cout, " "));
std::cout<<std::endl;
return 0;
}
And compared the assembly generated for the three cases using the compilation command (GCC 4.7.2):
g++ test.cpp -O3 -S -oc1.s
The cases are called c1.s, c2.s, and c3.s. The output of the command shasum *.s is:
5360e2438aebea682d88277da69c88a3f4af10f3 c1.s
5360e2438aebea682d88277da69c88a3f4af10f3 c2.s
5360e2438aebea682d88277da69c88a3f4af10f3 c3.s
Now, I must mention that the most natural construction seems to be the one-dimensional declaration of ma, that is: double ma[N], because then the initial position is simply ma, and the final position is simply ma + N (this is as opposed to taking the address of the first element of the array).
I find that the algorithms provided by the <algorithm> C++ Standard Library header fit much more snuggly in this case.
Finally, I must encourage you to consider using std::array or std::vector if at all possible.
Cheers.
C++ stores multi-dimensional arrays in row major order as a one-dimensional array extending through memory.
As other commenters have indicated, the 2-dimensional array will be mapped to 1-dimensional memory. Is your assumption platform independent? I would expect so, but you should always test it to be sure.
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
char Data[3][5];
int count = 0;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 5; ++j)
Data[i][j] = count++;
std::copy(&Data[0][0], &Data[0][0] + 15, std::ostream_iterator<int>(std::cout,", "));
}
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html
How are multi-dimensional arrays formatted in memory?
Memory map for a 2D array in C
Quote
It follows from all this that arrays in C++ are stored row-wise (last subscript varies fastest) and that
the first subscript in the declaration helps determine the amount of storage consumed by an array but plays
no other part in subscript calculations.
C++ ISO standard

How to use pointers in for loops to count characters?

I was looking through the forums and saw a question about counting the numbers of each letter in a string. I am teaching myself and have done some research and am now starting to do projects. Here I have printed the elements of the array. But I do so without pointers. I know I can use a pointer to an array and have it increment for each value, but I need some help doing so.
Here is my code without the pointer:
code main() {
char alph [] = {'a', 'b', 'c'};
int i, o;
o = 0;
for(i=0; i < 3; i++)
{ cout << alph[i] << ' '; };
};
Here is my bad code that doesn't work trying to get the pointer to work.
main() {
char alph [] = {'a', 'b', 'c'};
char *p;
p = alph;
for (; p<=3; p++);
cout << *p;
return 0;
};
I hope that it's not too obvious of an answer; I don't mean to waste anyone's time. Also this is my first post so if anyone wants to give me advice, thank you.
Very good try. There's just one tiny thing wrong, which is this:
p <= 3
Pointers are just some number which represents a memory address. When you do p = alph, you're not setting p to 0, you're setting it to point to the same address as alph. When looping over an array with pointers, you have to compare the current pointer with a pointer that is one past the end of the array. To get a pointer to one element past the end of the array, you add the number of elements to the array:
alph + 3 // is a pointer to one past the end of the array
Then your loop becomes
for (; p < alph + 3; ++p)
You may think that getting a pointer to one past the end of the array is going out of bounds of the array. However, you're free to get a pointer to anywhere in memory, as long as you don't dereference it. Since the pointer alph + 3 is never dereferenced - you only use it as a marker for the end of the array - and everything is fine.
Here are some rough correlations for the different versions:
/-----------------------------------\
| Pointer Version | Index Version |
-------------------------------------
| p | i |
| p = alph | i = 0 |
| *p | alph[i] |
| alph + 3 | 3 |
| p < alph + 3 | i < 3 |
\-----------------------------------/
Also note that instead of doing alph + 3, you may want to use sizeof. sizeof gives you the number of bytes that an object occupies in memory. For arrays, it gives you the number of bytes the whole array takes up (but it doesn't work with pointers, so you can do it with alph but not with p, for example). The advantage of using sizeof to get the size of the array is that if you change the size later, you do not have to go and find all the places where you wrote alph + 3 and change them. You can do that like this:
for (; p < alph + sizeof(alph); ++p)
Additional note: because the size of char is defined to be 1 byte, this works. If you change the array to an array of int, for example (or any other type that is bigger than 1 byte) it will not work any more. To remedy this, you divide the total size in bytes of the array with the size of a single element:
for (; p < alph + sizeof(alph) / sizeof(*alph); ++p)
This may be a little complicated to understand, but all you're doing is taking the total number of bytes of the array and dividing it by the size of a single element to find the number of elements in the array. Note that you are adding the number of elements in the array, not the size in bytes of the array. This is a consequence of how pointer arithmetic works (C++ automatically multiplies the number you add to a pointer by the size of the type that the pointer points to).
For example, if you have
int alph[3];
Then sizeof(alph) == 12 because each int is 4 bytes big. sizeof(*alph) == 4 because *alph is the first element of the array. Then sizeof(alph) / sizeof(alph) is equal to 12 / 4 which is 3, which is the number of elements in the array. Then by doing
for (; p < alph + sizeof(alph) / sizeof(*alph); ++p)
that is equivalent to
for (; p < alph + 12 / 4; ++p)
which is the same as
for (; p < alph + 3; ++p)
Which is correct.
This has the good advantage that if you change the array size to 50 and change the type to short (or any other combination of type and array size), the code will still work correctly.
When you get more advanced (and hopefully understand arrays enough to stop using them...) then you will learn how to use std::end to do all this work for you:
for (; p < std::end(alph); ++p)
Or you can just use the range-based for loop introduced in C++11:
for (char c : alph)
Which is even easier. I recommend understanding pointers and pointer arithmetic well before reclining on the convenient tools of the Standard Library though.
Also good job SO, you properly syntax-highlighted my ASCII-Art-Chart.
The pointer loop should be:
for (char * p = alph; p != alph + 3; ++p)
{
std::cout << *p << std::endl;
}
You can get a bit more fancy by hoisting the end of the array out of the loop, and by inferring the array size automatically:
for (char * p = alph, * end = alph + sizeof(alph)/sizeof(alph[0]); p != end; ++p)
In C++11, you can do even better:
for (char c : alph) { std::cout << c << std::endl; }
Your problem (apart from compilation issues noted in my comment to the question) is that pointers are not as small as 3. You need:
for (p = alph; p < alph + sizeof(alph); p++)
for the loop. Note that sizeof() generates a compile-time constant. (In C99 or C2011, that is not always the case; in C++, it is always the case, AFAIK). In this context, sizeof() is a fancy way of writing 3, but if you add new characters to the array, it adjusts automatically, whereas if you write 3 and change things, you have to remember to change the 3 to the new value too.
Ruminations on the use of sizeof()
As Kerrek SB points out, sizeof() returns the size of an array in bytes. By definition, sizeof(char) == 1, so in this context, it was safe to use sizeof() on the array. There are also times when it is not safe - or you have to do some extra work. If you had an array of some other type, you can use:
SomeType array[] = { 2, 3, 5, 7, 11, 13 };
then the number of elements in the array is (sizeof(array)/sizeof(array[0])). That is, the number of elements is the total size of the array, in bytes, divided by the size of one element (also in bytes).
The other big gotcha is that if you 'pass an array' as a function argument, you can't use sizeof() on it to get the correct size - you get the size of a pointer instead. This is a good reason for not using C-style strings or C-style arrays: use std::string and std::vector<SomeType> instead, not least because you can find their actual size reliably with a member function call.
I recommand you the following revised code.
char alph [] = {'a', 'b', 'c', 0};
char *p;
p = alph;
while(*p)
{
std::cout << *p++;
}
0 marks the end of a string in both c and c++.