How can a string be assigned to a const char*? - c++

How is it possible to assign a string (an array of chars, if I'm understanding this correctly) to a const char*? Any other pointer requires the new keyword followed by a type, but in this case the string is just assigned to a pointer. The pointer is a memory address, not an array of chars, but somehow it accepts the array of chars as a value.
(I really have tried finding an answer to this, but as I'm beginner I might have missed it, apologies if that's the case.)

Arrays can be implicitly converted to pointers to their first elements.
Most (but not all) operations on arrays perform this conversion, so arrays and pointers are often confused with each other. Good job figuring out the difference early on.
Any other pointer requires the new keyword
Not true, consider this:
int x;
int *y = &x;
While you should know what they do, the manual use of new and delete is discouraged in modern C++, unless you're writing your own container or smart pointer.

Related

Can I determent typename T* in template is a array or object? [duplicate]

I want to know whether a pointer is pointing to an array or single integer. I have a function which takes two pointer (int and char) as input and tell whether a pointer is pointing to an array or single integer.
pointer=pointer+4;
pointer1=pointer1+4;
Is this a good idea?
Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...
#define ARRAY_SENTINEL -1
int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};
pointer = &x_array[0];
if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}
pointer = &x;
if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}
That's not a good idea. Using just raw pointers there's no way to know if they point to an array or a single value.
A pointer that is being used as an array and a pointer to a single values are identical - they're both just a memory address - so theres no information to use to distinguish between them. If you post what you want to ultimately do there might be a solution that doesn't rely on comparing pointers to arrays and single values.
Actually pointers point to a piece of memory, not integers or arrays. It is not possible to distinguish if an integer is single variable or the integer is an element of array, both will look exactly the same in memory.
Can you use some C++ data structures, std::vector for example?
For C++ questions, the answer is simple. Do not use C-style dynamic arrays in C++. Whenever you need a C-style dynamic array, you should use std::vector.
This way you would never guess what the pointer points to, because only std::vector will be holding an array.

What real use does a double pointer have?

I have searched and searched for an answer to this but can't find anything I actually "get".
I am very very new to c++ and can't get my head around the use of double, triple pointers etc.. What is the point of them?
Can anyone enlighten me
Honestly, in well-written C++ you should very rarely see a T** outside of library code. In fact, the more stars you have, the closer you are to winning an award of a certain nature.
That's not to say that a pointer-to-pointer is never called for; you may need to construct a pointer to a pointer for the same reason that you ever need to construct a pointer to any other type of object.
In particular, I might expect to see such a thing inside a data structure or algorithm implementation, when you're shuffling around dynamically allocated nodes, perhaps?
Generally, though, outside of this context, if you need to pass around a reference to a pointer, you'd do just that (i.e. T*&) rather than doubling up on pointers, and even that ought to be fairly rare.
On Stack Overflow you're going to see people doing ghastly things with pointers to arrays of dynamically allocated pointers to data, trying to implement the least efficient "2D vector" they can think of. Please don't be inspired by them.
In summary, your intuition is not without merit.
An important reason why you should/must know about pointer-to-pointer-... is that you sometimes have to interface with other languages (like C for instance) through some API (for instance the Windows API).
Those APIs often have functions that have an output-parameter that returns a pointer. However those other languages often don't have references or compatible (with C++) references. That's a situation when pointer-to-pointer is needed.
It's less used in c++. However, in C, it can be very useful. Say that you have a function that will malloc some random amount of memory and fill the memory with some stuff. It would be a pain to have to call a function to get the size you need to allocate and then call another function that will fill the memory. Instead you can use a double pointer. The double pointer allows the function to set the pointer to the memory location. There are some other things it can be used for but that's the best thing I can think of.
int func(char** mem){
*mem = malloc(50);
return 50;
}
int main(){
char* mem = NULL;
int size = func(&mem);
free(mem);
}
I am very very new to c++ and can't get my head around the use of double, triple pointers etc.. What is the point of them?
The trick to understanding pointers in C is simply to go back to the basics, which you were probably never taught. They are:
Variables store values of a particular type.
Pointers are a kind of value.
If x is a variable of type T then &x is a value of type T*.
If x evaluates to a value of type T* then *x is a variable of type T. More specifically...
... if x evaluates to a value of type T* that is equal to &a for some variable a of type T, then *x is an alias for a.
Now everything follows:
int x = 123;
x is a variable of type int. Its value is 123.
int* y = &x;
y is a variable of type int*. x is a variable of type int. So &x is a value of type int*. Therefore we can store &x in y.
*y = 456;
y evaluates to the contents of variable y. That's a value of type int*. Applying * to a value of type int* gives a variable of type int. Therefore we can assign 456 to it. What is *y? It is an alias for x. Therefore we have just assigned 456 to x.
int** z = &y;
What is z? It's a variable of type int**. What is &y? Since y is a variable of type int*, &y must be a value of type int**. Therefore we can assign it to z.
**z = 789;
What is **z? Work from the inside out. z evaluates to an int**. Therefore *z is a variable of type int*. It is an alias for y. Therefore this is the same as *y, and we already know what that is; it's an alias for x.
No really, what's the point?
Here, I have a piece of paper. It says 1600 Pennsylvania Avenue Washington DC. Is that a house? No, it's a piece of paper with the address of a house written on it. But we can use that piece of paper to find the house.
Here, I have ten million pieces of paper, all numbered. Paper number 123456 says 1600 Pennsylvania Avenue. Is 123456 a house? No. Is it a piece of paper? No. But it is still enough information for me to find the house.
That's the point: often we need to refer to entities through multiple levels of indirection for convenience.
That said, double pointers are confusing and a sign that your algorithm is insufficiently abstract. Try to avoid them by using good design techniques.
A double-pointer, is simply a pointer to a pointer. A common usage is for arrays of character strings. Imagine the first function in just about every C/C++ program:
int main(int argc, char *argv[])
{
...
}
Which can also be written
int main(int argc, char **argv)
{
...
}
The variable argv is a pointer to an array of pointers to char. This is a standard way of passing around arrays of C "strings". Why do that? I've seen it used for multi-language support, blocks of error strings, etc.
Don't forget that a pointer is just a number - the index of the memory "slot" inside a computer. That's it, nothing more. So a double-pointer is index of a piece of memory that just happens to hold another index to somewhere else. A mathematical join-the-dots if you like.
This is how I explained pointers to my kids:
Imagine the computer memory is a series of boxes. Each box has a number written on it, starting at zero, going up by 1, to however many bytes of memory there is. Say you have a pointer to some place in memory. This pointer is just the box number. My pointer is, say 4. I look into box #4. Inside is another number, this time it's 6. So now we look into box #6, and get the final thing we wanted. My original pointer (that said "4") was a double-pointer, because the content of its box was the index of another box, rather than being a final result.
It seems in recent times pointers themselves have become a pariah of programming. Back in the not-too-distant past, it was completely normal to pass around pointers to pointers. But with the proliferation of Java, and increasing use of pass-by-reference in C++, the fundamental understanding of pointers declined - particularly around when Java became established as a first-year computer science beginners language, over say Pascal and C.
I think a lot of the venom about pointers is because people just don't ever understand them properly. Things people don't understand get derided. So they became "too hard" and "too dangerous". I guess with even supposedly learned people advocating Smart Pointers, etc. these ideas are to be expected. But in reality there a very powerful programming tool. Honestly, pointers are the magic of programming, and after-all, they're just a number.
In many situations, a Foo*& is a replacement for a Foo**. In both cases, you have a pointer whose address can be modified.
Suppose you have an abstract non-value type and you need to return it, but the return value is taken up by the error code:
error_code get_foo( Foo** ppfoo )
or
error_code get_foo( Foo*& pfoo_out )
Now a function argument being mutable is rarely useful, so the ability to change where the outermost pointer ppFoo points at is rarely useful. However, a pointer is nullable -- so if get_foo's argument is optional, a pointer acts like an optional reference.
In this case, the return value is a raw pointer. If it returns an owned resource, it should usually be instead a std::unique_ptr<Foo>* -- a smart pointer at that level of indirection.
If instead, it is returning a pointer to something it does not share ownership of, then a raw pointer makes more sense.
There are other uses for Foo** besides these "crude out parameters". If you have a polymorphic non-value type, non-owning handles are Foo*, and the same reason why you'd want to have an int* you would want to have a Foo**.
Which then leads you to ask "why do you want an int*?" In modern C++ int* is a non-owning nullable mutable reference to an int. It behaves better when stored in a struct than a reference does (references in structs generate confusing semantics around assignment and copy, especially if mixed with non-references).
You could sometimes replace int* with std::reference_wrapper<int>, well std::optional<std::reference_wrapper<int>>, but note that is going to be 2x as large as a simple int*.
So there are legitimate reasons to use int*. Once you have that, you can legitimately use Foo** when you want a pointer to a non-value type. You can even get to int** by having a contiguous array of int*s you want to operate on.
Legitimately getting to three-star programmer gets harder. Now you need a legitimate reason to (say) want to pass a Foo** by indirection. Usually long before you reach that point, you should have considered abstracting and/or simplifying your code structure.
All of this ignores the most common reason; interacting with C APIs. C doesn't have unique_ptr, it doesn't have span. It tends to use primitive types instead of structs because structs require awkward function based access (no operator overloading).
So when C++ interacts with C, you sometimes get 0-3 more *s than the equivalent C++ code would.
The use is to have a pointer to a pointer, e.g., if you want to pass a pointer to a method by reference.
What real use does a double pointer have?
Here is practical example. Say you have a function and you want to send an array of string params to it (maybe you have a DLL you want to pass params to). This can look like this:
#include <iostream>
void printParams(const char **params, int size)
{
for (int i = 0; i < size; ++i)
{
std::cout << params[i] << std::endl;
}
}
int main()
{
const char *params[] = { "param1", "param2", "param3" };
printParams(params, 3);
return 0;
}
You will be sending an array of const char pointers, each pointer pointing to the start of a null terminated C string. The compiler will decay your array into pointer at function argument, hence what you get is const char ** a pointer to first pointer of array of const char pointers. Since the array size is lost at this point, you will want to pass it as second argument.
One case where I've used it is a function manipulating a linked list, in C.
There is
struct node { struct node *next; ... };
for the list nodes, and
struct node *first;
to point to the first element. All the manipulation functions take a struct node **, because I can guarantee that this pointer is non-NULL even if the list is empty, and I don't need any special cases for insertion and deletion:
void link(struct node *new_node, struct node **list)
{
new_node->next = *list;
*list = new_node;
}
void unlink(struct node **prev_ptr)
{
*prev_ptr = (*prev_ptr)->next;
}
To insert at the beginning of the list, just pass a pointer to the first pointer, and it will do the right thing even if the value of first is NULL.
struct node *new_node = (struct node *)malloc(sizeof *new_node);
link(new_node, &first);
Multiple indirection is largely a holdover from C (which has neither reference nor container types). You shouldn't see multiple indirection that much in well-written C++, unless you're dealing with a legacy C library or something like that.
Having said that, multiple indirection falls out of some fairly common use cases.
In both C and C++, array expressions will "decay" from type "N-element array of T" to "pointer to T" under most circumstances1. So, assume an array definition like
T *a[N]; // for any type T
When you pass a to a function, like so:
foo( a );
the expression a will be converted from "N-element array of T *" to "pointer to T *", or T **, so what the function actually receives is
void foo( T **a ) { ... }
A second place they pop up is when you want a function to modify a parameter of pointer type, something like
void foo( T **ptr )
{
*ptr = new_value();
}
void bar( void )
{
T *val;
foo( &val );
}
Since C++ introduced references, you probably won't see that as often. You'll usually only see that when working with a C-based API.
You can also use multiple indirection to set up "jagged" arrays, but you can achieve the same thing with C++ containers for much less pain. But if you're feeling masochistic:
T **arr;
try
{
arr = new T *[rows];
for ( size_t i = 0; i < rows; i++ )
arr[i] = new T [size_for_row(i)];
}
catch ( std::bad_alloc& e )
{
...
}
But most of the time in C++, the only time you should see multiple indirection is when an array of pointers "decays" to a pointer expression itself.
The exceptions to this rule occur when the expression is the operand of the sizeof or unary & operator, or is a string literal used to initialize another array in a declaration.
In C++, if you want to pass a pointer as an out or in/out parameter, you pass it by reference:
int x;
void f(int *&p) { p = &x; }
But, a reference can't ("legally") be nullptr, so, if the pointer is optional, you need a pointer to a pointer:
void g(int **p) { if (p) *p = &x; }
Sure, since C++17 you have std::optional, but, the "double pointer" has been idiomatic C/C++ code for many decades, so should be OK. Also, the usage is not so nice, you either:
void h(std::optional<int*> &p) { if (p) *p = &x) }
which is kind of ugly at the call site, unless you already have a std::optional, or:
void u(std::optional<std::reference_wrapper<int*>> p) { if (p) p->get() = &x; }
which is not so nice in itself.
Also, some might argue that g is nicer to read at the call site:
f(p);
g(&p); // `&` indicates that `p` might change, to some folks

Error: cannot convert ‘std::string (*)[3]' to ‘std::string** in return [duplicate]

I'm trying to understand the nature of type-decay. For example, we all know arrays decay into pointers in a certain context. My attempt is to understand how int[] equates to int* but how two-dimensional arrays don't correspond to the expected pointer type. Here is a test case:
std::is_same<int*, std::decay<int[]>::type>::value; // true
This returns true as expected, but this doesn't:
std::is_same<int**, std::decay<int[][1]>::type>::value; // false
Why is this not true? I finally found a way to make it return true, and that was by making the first dimension a pointer:
std::is_same<int**, std::decay<int*[]>::type>::value; // true
And the assertion holds true for any type with pointers but with the last being the array. For example (int***[] == int****; // true).
Can I have an explanation as to why this is happening? Why doesn't the array types correspond to the pointer types as would be expected?
Why does int*[] decay into int** but not int[][]?
Because it would be impossible to do pointer arithmetic with it.
For example, int p[5][4] means an array of (length-4 array of int). There are no pointers involved, it's simply a contiguous block of memory of size 5*4*sizeof(int). When you ask for a particular element, e.g. int a = p[i][j], the compiler is really doing this:
char *tmp = (char *)p // Work in units of bytes (char)
+ i * sizeof(int[4]) // Offset for outer dimension (int[4] is a type)
+ j * sizeof(int); // Offset for inner dimension
int a = *(int *)tmp; // Back to the contained type, and dereference
Obviously, it can only do this because it knows the size of the "inner" dimension(s). Casting to an int (*)[4] retains this information; it's a pointer to (length-4 array of int). However, an int ** doesn't; it's merely a pointer to (pointer to int).
For another take on this, see the following sections of the C FAQ:
6.18: My compiler complained when I passed a two-dimensional array to a function expecting a pointer to a pointer.
6.19: How do I write functions which accept two-dimensional arrays when the width is not known at compile time?
6.20: How can I use statically- and dynamically-allocated multidimensional arrays interchangeably when passing them to functions?
(This is all for C, but this behaviour is essentially unchanged in C++.)
C was not really "designed" as a language; instead, features were added as needs arose, with an effort not to break earlier code. Such an evolutionary approach was a good thing in the days when C was being developed, since it meant that for the most part developers could reap the benefits of the earlier improvements in the language before everything the language might need to do was worked out. Unfortunately, the way in which array- and pointer handling have evolved has led to a variety of rules which are, in retrospect, unfortunate.
In the C language of today, there is a fairly substantial type system, and variables have clearly defined types, but things were not always thus. A declaration char arr[8]; would allocate 8 bytes in the present scope, and make arr point to the first of them. The compiler wouldn't know that arr represented an array--it would represent a char pointer just like any other char*. From what I understand, if one had declared char arr1[8], arr2[8];, the statement arr1 = arr2; would have been perfectly legal, being somewhat equivalent conceptually to char *st1 = "foo, *st2 = "bar"; st1 = st2;, but would have almost always represented a bug.
The rule that arrays decompose into pointers stemmed from a time when arrays and pointers really were the same thing. Since then, arrays have come to be recognized as a distinct type, but the language needed to remain essentially compatible with the days when they weren't. When the rules were being formulated, the question of how two-dimensional arrays should be handled wasn't an issue because there was no such thing. One could do something like char foo[20]; char *bar[4]; int i; for (i=0; i<4; i++) bar[i] = foo + (i*5); and then use bar[x][y] in the same way as one would now use a two-dimensional array, but a compiler wouldn't view things that way--it just saw bar as a pointer to a pointer. If one wanted to make foo[1] point somewhere completely different from foo[2], one could perfectly legally do so.
When two two-dimensional arrays were added to C, it was not necessary to maintain compatibility with earlier code that declared two-dimensional arrays, because there wasn't any. While it would have been possible to specify that char bar[4][5]; would generate code equivalent to what was shown using the foo[20], in which case a char[][] would have been usable as a char**, it was thought that just as assigning array variables would have been a mistake 99% of the time, so too would have been re-assignment of array rows, had that been legal. Thus, arrays in C are recognized as distinct types, with their own rules which are a bit odd, but which are what they are.
Because int[M][N] and int** are incompatible types.
However, int[M][N] can decay into int (*)[N] type. So the following :
std::is_same<int(*)[1], std::decay<int[1][1]>::type>::value;
should give you true.
Two dimensional arrays are not stored as pointer to pointers, but as a contiguous block of memory.
An object declared as type int[y][x] is a block of size sizeof(int) * x * y whereas, an object of type int ** is a pointer to an int*

C++ char pointer to char variable

I'm given a method header as so:
char* thisMethod(char* input){}
is it possible to say,
char var = input[0];
? I know that "input" will be in the form of a char array.
I'm obviously new to C++ pointers are throwing me off. I tried researching how to work with char pointer function arguments but couldn't find anything specific enough to help. Thanks for the help.
There is a misconception that may lead you into further troubles:
I know that "input" will be in the form of a char array.
NOPE: By the scope of that function, input is a pointer to a character. The function has no way to know where such a pointer comes from.
If it has been taken from an array upon calling the function than it will be a pointer to the first element of that array.
Because pointer have an arithmetic that allows to add offsets and because the [] operator applied to pointers translates as a[b] = *(a+b) by definition, in whatever code, if a is a pointer, *a and a[0] are perfect synonymous.
Think to an array as a sequence of boxes and a pointer as your hand's index finger
adding an offset to a finger (like finger+2) means "re-point it aside" and de-referencing it (like *finger) means "look inside what it points to".
The [] operator on pointers is just a shortcut to do both operations at once.
Arrays are another distinct thing. Don't think to them when dealing with pointers, since -in more complex situations, like multidimensional array or multi-indirection pointers - the expression a[b][c] won't work anymore the same way.
There are two ways to get a value from a pointer, * and []. The following are equivalent:
char var1 = *input;
char var2 = input[0];
Using the brackets is more common when you know you were passed an array, since it allows you to supply an index. You need some way of knowing where the end of the array is so that you don't attempt any access past it, your function is missing that important detail.
As long as it's inside the function and input points to something valid ( not NULL/nullptr and not a garbage location ) then doing char var = input[0]; is just fine. It's the same as char var = *input.
P.S If it's supposed to be a string I recommend using std::string.

assign a char array to a literal string - c++

char arr[3];
arr="hi";// ERROR
cin>>arr;// and at runtime I type hi, which works fine.
1)can someone explain to me why?
2)and what's exactly is the type of "hi", I know it's called literal string. but is it just an array of chars too?
3) isn't cin>>arr; will be just like assign arr to what you type at runtime?
Arrays in C++ are not actual types, just a structured representation of a series of values, and not pointers if you should find that anywhere (they decay into pointers). You can't use them like you would use other types, including assignment. The choice was to either add lots of support for arrays, or to keep them as simple and fast as possible. The latter was chosen, which is one of the distinctions C++ has from some other languages.
To copy an array, copy each element one at a time.
In C++11, there is an STL container std::array. It was designed to fit in as a plain array with operator overloading, as well as relating to the rest of the STL.
A better alternative is std::string. It incorporates the behaviour you want and more, and is specifically designed for holding arrays of characters.
"hi" is, as Konrad Rudolph points out, a const char [3].
As for cining a raw array, it is not possible by standard means because there is no overload provided for cin with arrays. It is possible to create your own overload though. However, I'm not sure how you would account for the different sizes of arrays that get passed unless you define it for a container that knows its size instead of a raw array.
If you'd like, you can declare:
char array[] = "hi!";
Creates an array and 'initializes' it to 4 bytes long, "hi!"
char const *array2 = "hey!";
Creates a pointer to read-only memory, a string literal
array2 = array;
You can now use the array2 pointer to access array one. This is called pointer decay; array and array2 are not of the same type, even though they can cooperate here. An array of type char "decays" to a pointer-to of type char.
array = array2; // ERROR
An array is not a pointer. You're thinking like an array is a pointer, when really, it is pre-allocated. You're attempting to assign an address, but array[] already has one "hard-coded" when it was created, and it cannot be changed.