How do char arrays and their pointers work in c++ exactly? - c++

I am a beginner student in c++ and there is one thing I cannot understand when working with character arrays: So, I know that pointers are essentially variables that "point" to the memory address of another variable, and that the name of an array(Ex: int a[20]) is a constant pointer to the values in that array. When working with different numeric types(int, float etc.) if we output through a message the name of that array it shows the address of the first element, but if we do the same with a char type, it doesn't show the address, but the value of the variable.
Example:
#include <iostream>
using namespace std;
int main()
{int a[]={1,2,3,4,5};
cout<<a<<endl; //through output, it shows the memory address of the first
element of the array;
char b[]={"Mountain"};
cout<<b; //It outputs the word "Mountain"
return 0;
}
Is the pointer from a char array automatically converted to its value when you output it?

There is no difference. char pointers aren't somehow magically different than int pointers. So what's going on, than?
std::cout << (or the older printf()) have overloads for char*. Meaning that the functions behave differently if the input is a char*: the pointer is iterated until a '\0' character is reached (see null terminated string).
char b[]={"Mountain"};
b does not contain
{'M', 'o', 'u', 'n', 't', 'a', 'i', 'n'}
but instead
{'M', 'o', 'u', 'n', 't', 'a', 'i', 'n', '\0'} <- '\0'
making the iterating and stopping possible.
This also explains why the array size of b is 1 larger than the number of characters inside the word.
To add, you should not use these char pointers. They are dangerous and are long replaced by modern utilites like std::string.
now int a[]={1,2,3,4,5}; is OK but std::array<int, 5> a = {1,2,3,4,5}; is even better.
the types are unique (std::array<int, 4> != std::array<int, 5>)
it has a .size() function.
you can therefore pass it to other functions without having to add a size argument
it's as fast as a normal array
std::array can be used by including <array>.
If you ever go for something like int* a = new int[5]; than stop right there and instead use std::vector
Fianally never ever say use namespace std; (here why)

It all depends on how you interpret the parameters. cout << operator will consider (sometype*) as an address, but particularly char* as a string.
If you write a function taking your own parameters, you can interpret what ever the way you like.
In this problem, if you want to get the address, you can do it so
std::cout << static_cast<const void*>(b);

In C, strings are represented as a pointer to char. for this reason, when you pass a char* to an ostream (such as std::cout) in C++, it will interpret it as a null-terminated string and print that string's content rather than the address. If you want to print the address, you'll have to cast that pointer to a different kind:
std::cout << (void*)b;

cout is an output stream. When we use output streams, and pass a char*, it treats it as a null terminated string (i.e. it prints all the characters till it find '\0') in the string. For any other pointer type, the address is printed.

Related

Why this c++ code is not returning address of each character in the array?

I am trying to get the addresses of each character in the array as follows:
#include <bits/stdc++.h>
using namespace std;
int main() {
char arr[] = {'a', 'b', 'c'};
cout<<&arr[0]<<endl;
cout<<&arr[1]<<endl;
cout<<&arr[2]<<endl;
return 0;
}
But the output I am getting is as follows:
abc0╒#
bc0╒#
c0╒#
Press any key to continue . . .
The output does not look like an address with hexadecimal digits, but just some random characters. Am I missing some concepts here? I want to get the address of each character in the array arr.
The type of &arr[i] is a char*.
The class of which cout is an instance has an overloaded << operator for a const char*. It treats the pointer as the start of a NUL-terminated string, and outputs the data as text.
You are observing the effects of undefined behaviour as a NUL-terminator is not reached. If you had written
char arr[] = {'a', 'b', 'c', 0};
then the program behaviour would be defined.
If you want to output addresses then use cout << (const void*)&arr[0] << endl; &c.
If you want to print out the address, you could cast them (from char*) to void* firstly.
cout<<static_cast<void*>(&arr[0])<<endl;
cout<<static_cast<void*>(&arr[1])<<endl;
cout<<static_cast<void*>(&arr[2])<<endl;
Otherwise, they will be considererd as c-style string, and the content of the string is trying to be printed out. Since arr doesn't have the null terminator '\0' at last, the behavior is undefined here.

Array of char pointers

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]);

Different ways to make a string?

I'm new to c++ and I'd like to know right from the start,
Does any of these methods of making strings work exactly the same way and give the exact same results always in every case? is there any difference in the result in any of them?
1) char greeting [6] = { 'h','e','l','l','o','\0' };
2) char greeting[] = "hello";
3) #include <string>
string greeting = "hello";
1) and 2) work exactly the same. Both create a 6-element non-heap-allocated array, and copy the characters 'h', 'e', 'l', 'l', 'o', '\0' to the array at runtime or load time.
3) creates an instance of std::string and calls its constructor which copies the characters 'h', 'e', 'l', 'l', 'o'(, '\0')* to its internal memory buffer. (* The '\0' is not required to be stored in the memory buffer.)
There is another way to declare a string in C++, using a pointer to char:
const char* greeting = "hello";
This will not copy anything. It will just point the pointer to the first character 'h' of the null-terminated "hello" string which is located somewhere in memory. The string is also read-only (modifying it causes undefined behavior), which is why one should use a pointer-to-const here.
If you're wondering which one to use, choose std::string, it's the safest and easiest.
Do these methods of making strings work exactly the same way and give the exact same results always in every case?
The first two are array definitions:
char greeting [6] = { 'h','e','l','l','o','\0' };
char greeting [ ] = "hello";
"work the same" as in the second definition a '\0' is appended implicitly.
As for the third definition:
string greeting = "hello";
A string is a class type object and as such it is more complex than a simple array.
Is there any difference in the result in any of them?
There is a quantitative1 and qualitative2 difference between the first two and the third stemming from the fact that std::string is a class type object.
1. Quantitative: arrays occupy less memory space than string.
2. Qualitative: string provides resource management and many facilities for element manipulation.

Initialize char array to hold non-null-terminated string [duplicate]

This question already has answers here:
Non null-terminated string compiler option for gcc
(6 answers)
Closed 7 years ago.
I am trying to initialize a char array with a long string. However, I do not want it to be NULL terminated.
This:
const char s[] = "The actual string is much longer then this...";
is much easier to read (and to write) than this:
const char s[] = {'T', 'h', 'e', ' ', 'a', 'c', 't', 'u', 'a', 'l', ' ', 's', ...};
but the former gets NULL terminated. Is there a way to avoid the NULL on a string literal?
The reason for doing this is that there is the need to pack densely strings in memory of fixed size length known during development.
No.
A string literal is a C-string which, by definition, is null-terminated.
Either ignore the final character, revisit your requirements (why do you care about a final character?!) or … I dunno, something else. Perhaps generate the objects with xxd?
I would do:
size_t length = 45;
char s[] = "The actual string is much longer then this..";
s[length - 1] = ".";
See what you have there has a trade-off between readability and functionality and I think that you can get away easily with this, since you can not avoid the NULL terminating string in the "normal" initialization.
If I were in your shoes, I would re-consider my approach and use std::string.
No. If you want essy to write code, copy to a second array but miss off the last char. You can use a char pointer in the first case to perhaps save some memory
The terminating nul will be omitted if it doesn't fit. Since your strings are all fixed length, that's not a problem to arrange. For example:
#include <stdio.h>
char foo[3][4] = { "four", ".by." , "3333" };
int main(void)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
putchar(foo[i][j]);
putchar('\n');
}
}
There is no way to have a string literal not null terminated.
But you actually want to pack a number of strings densely and you know both the sizes and the strings at development time.
Assume:
"First"
"Second"
"Third"
to pack them you can safely do:
char const s[] = "First""Second""Third";
You only need to save lengths and properly reconstruct termination in case you want to print or use std string. That is easy though.
As a bonus you have saved from the excess pointer you would have to store for each and everyone string needed.

pointer to string and char catch 22

I'm studying on pointers and I'm stuck when I see char *p[10]. Because something is misunderstood. Can someone explain step-by-step and blow-by-blow why my logic is wrong and what the mistakes are and where did I think wrong and how should I think. Because I want to learn exactly. Also what about int *p[10]; ? Besides, for example x is a pointer to char but just char not chars. But how come char *x = "possible";
I think above one should be right but, I have seen for char *name[] = { "no month","jan","feb" }; I am really confused.
Your char *p[10] diagram shows an array where each element points to a character.
You could construct it like this:
char f = 'f';
char i = 'i';
char l1 = 'l';
char l2 = 'l';
char a1 = 'a';
char r1 = 'r';
char r2 = 'r';
char a2 = 'a';
char y = 'y';
char nul = '\0';
char *p[10] = { &f, &i, &l1, &l2, &a1, &r1, &r2, &a2, &y, &nul };
This is very different from the array
char p[10] = {'f', 'i', 'l', 'l', 'a', 'r', 'r', 'a', 'y', '\0'};
or
char p[10] = "fillarray";
which are arrays of characters, not pointers.
A pointer can equally well point to the first element of an array, as you've probably seen in constructions like
const char *p = "fillarray";
where p holds the address of the first element of an array defined by the literal.
This works because an array can decay into a pointer to its first element.
The same thing happens if you make an array of pointers:
/* Each element is a pointer to the first element of the corresponding string in the initialiser. */
const char *name[] = { "no month","jan","feb" };
You would get the same results with
const char* name[3];
name[0] = "no month";
name[1] = "jan";
name[2] = "feb";
char c = 'a';
Here, c is a char, typically a single byte of ASCII encoded data.
char* ptr = &c;
ptr is a char pointer. In C, all it does is point to a memory location and doesn't make any guarantees about what is at that location. You could use a char* to pass a char to a function to allow the function to allow the function to make changes to that char (pass by reference).
A common C convention is for a char* to point to a memory location where several characters are stored in sequence followed by the null character \0. This convention is called a C string:
char const* cstr = "hello";
cstr points to a block of memory 6 bytes long, ending with a null character. The data itself cannot be modified, though the pointer can be changed to point to something else.
An array of chars looks similar, but behaves slightly differently.
char arr[] = "hello";
Here arr IS a memory block of 6 chars. Since arr represents the memory itself, it cannot be changed to point to another location. The data can be modified though.
Now,
char const* name[] = { "Jan", " Feb"..., "Dec"};
is an array of pointer to characters.
name is a block of memory, each containing a pointer to a null-terminated string.
In the diagram, I think string* was accidentally used instead of char*. The difference between the left and the right, is not a technical difference really, but a difference in the way a char* is used. On the left each char* points to a single character, whereas in the one on the right, each char* points to a null-terminated block of characters.
Both are right.
A pointer in C or C++ may point either to a single item (a single char) or to the first in an array of items (char[]).
So a char *p[10]; definition may point to 10 single characters or 10 arrays (i.e. 10 strings).
Let’s go back to basics.
First, char *p is simply a pointer. p contains nothing more than a memory address. That memory address can point to anything, anywhere. By convention, we have always used NULL (or, I hate this method, assigning it to zero – yeah, they are the same “thing”, but NULL has traditionally been used in conjunction with pointers, so when you’re eyes flit across the code, you see NULL – you think “pointer”).
Anyway, that memory address being pointed to can contain anything. So, to use within the language, we type it, in this case it is a pointer to a character (char *p). This can be overridden by type casting, but that’s for a later time.
Second, we know anytime we see p[10], that we are dealing with an array. Again, the array can be an array of characters, an array of ints, etc. – but it’s still an array.
Your example: char *p[10], is then nothing more than an array of 10 character pointers. Nothing more, nothing less. Your problem comes in because you are trying to force the “string” concept onto this. There ain’t no strings in C. There ain’t no objects in C. The concept of a NULL-terminated string can most certainly be used. But a “string” in C is nothing more than an array of characters, terminated by a NULL (or, if you use some of the appropriate functions, you can use a specific number of characters – strncpy instead of strcpy, etc.). But, for all its appearance, and apparent use, there are no strings in C. They are nothing more than arrays of characters, with a few supporting functions that happen to stop going through the array when a NULL is encountered.
So – char a[10] – is simply an array of characters that is 10 characters long. You can fill it with any characters you wish. If one of those is the NULL character, then that terminates what is typically called a “C-style string”. There are functions that support this type of character array (i.e. “string”), but it is still a use of a character array.
Your confusion comes in because you are trying to mix C++ string objects, and forcing that concept onto C arrays of characters. As ugoren noted – your examples are both correct – because you are dealing with arrays of character pointers, NOT strings. Again, putting a NULL somewhere in that character array is happily supported by several C functions that give you the ability to work with a “string-like” concept – but they are not truly strings. Unless of course, you want to phrase it that a string is nothing more than one character following another – an array.