Usually when you declare a pointer (such as an int) you'd have to assign a memory address to it:
int value = 123;
int* p = &value;
When you create a char pointer, you can assign a char array to it without the need of including an address:
char* c = "Char Array";
How does this work? Does it allocate memory and point to that? Why can't other type pointers do the same thing?
How does this work?
The string literal is stored in a read-only data section in the executable file (meaning it is initialized during compilation) and c is initialized to point to that memory location. The implicit array-to-pointer conversion handles the rest.
Note that the conversion of string literals to char* is deprecated because the contents are read-only anyway; prefer const char* when pointing to string literals.
A related construct, char c[] = "Char Array";, would copy the contents of the string literal to the char array at runtime.
Why can't other type pointers do the same thing?
This is a special case for string literals, for convenience, inherited from C.
Other type pointers can do this as well just fine. A string literal is array of chars, so you don't need to use address operator to assign to pointer.
If you have an integer array, either int * or int[] you can assign it to int pointer without using the address operator as well:
int intArray1[] = {0, 1, 2}; // fist array
int * intArray2 = new int[10]; // second array
// can assign without & operator
int * p1 = intArray1;
int * p2 = intArray2;
The char * is just specific that the string literal type is actually const char * and is is still allowed to assign (with a warning about deprecated conversion).
Related
Why does this work:
char foo[6] = "shock";`
while this does not work:
char* bar = "shock"; //error
Why does bar have to be const while foo doesn't? Arrays in C decay to pointers, so don't foo and bar technically have the same types?
Literals are held in reserved areas of memory that are not supposed to be changed by code. Changing the value held at the address storing that literal would mean that every time any other code tried to use that literal, it would find the wrong value in that memory. So it is illegal to modify that memory, and hence illegal to treat it as not constant.
Source
With this declaration:
char foo[6] = "shock";
Variable foo is type array of char and it containes 6 non-const chars. The string literal contains const chars which are copied into the array on initialization.
While with this declaration:
char* bar = "shock"; //error
Variable bar is type pointer to char. You are trying to make it point to the address of "shock" which is a string literal containing const char.
You can't point a pointer to non-const char at a const char.
So you must do this:
const char* bar = "shock";`
because "shock" is a constant, so a pointer to it must be const
for historical reasons C allows this (and causes many errors that lead to SO posts)
char* bar = "shock";
is roughly equivalent to
const char anonymousArray[6] = "shock";
char *bar = anonymousArray;
Arrays decays to pointers. That's not the same as actually being pointers.
May be my concepts about pointer are not clear but I have a doubt. For integer pointer
# include <stdio.h>
int main()
{
int a = 4;
int *b = &a;
*b = 6;
printf("%d", *b);
}
prints
6
but for character pointer
char *str = "Hello";
*str = "Hlw";
gives error
but
char *str = "Hello";
str = "Hlw";
Works. So, why does it work like this?
A string literal is a const char[] array, which decays into a const char* pointer to the string's 1st char.
char *str = "Hello"; is legal in C, and in C++ up to C++03, but is illegal in C++11 and later. Modern versions do not allow a const char* pointer to be assigned to a non-const char* pointer (without an explicit type-cast, anyay).
Just as *b in your int* example accesses a single int, so too does *str access a single char. So *str = "Hlw"; is trying to assign a const char* pointer to a single char, which it why it fails to compile.
str = "Hlw"; is simply assigning a const char* pointer to str, making it point at a different memory address (if that were legal). In terms of your int* example, that would be the same as doing this:
int a;
int *b = &a;
int c;
b = &c; // <--
When you indirect through an int*, you get lvalue to int. An int is an integer.
When you indirect through a char*, you get lvalue to char. A char is not a string. It is a single character (assuming fixed width character encoding rather than unicode).
The core difference here is that strings are arrays of characters, while integers are not arrays.
str = "Hlw";
This is ill-formed in C++ because string literal is an array of const char, and such array does not implicitly convert to a pointer to non-const char.
Pointers do not have an information whether they point to a single object or to a member of an array.
In this code snippet
int *b = &a;
*b = 6;
the pointer p points to an object of the type int, so dereferencing the pointer you will get an access to this object.
In this code snippet
char *str = "Hello";
*str = "Hlw";
the pointer str points to an object of the type char. It points to the first character of the string literal "Hello". So dereferencing the pointer you will get an access to the first character of the string literal pointed to by the pointer.
Hence instead of this incorrect assignment
*str = "Hlw";
where the left hand side operand has the type char while the right hand side operand has the type char[4] in C and const char[4] in C++ you should write something like
*str = 'G';
that is you may assign a character literal to an object of the type char. You may not assign a string literal to an object of the type char like for example
char c = "Hello";
and the expression *str indeed has the type char.
In this code snippet
char *str = "Hello";
str = "Hlw";
you are reassigning the pointer str itself instead of the pointed by it object.
After the declaration the pointer str points to the first character of the string literal "Hello" that is to the character 'H'.
In the following statement the pointer str is reassigned by the address of the first character of the string literal "Hlw". That ijs now it points to the character 'H' of this string literal.
*b can be replaced by b[0] because, in C, a pointer to anything is also an array of one element of that type. Doing this way helps to understand the issue :
int a = 4;
int *b = &a;
b[0] = 6; //<=== this is correct because b is an array of int
char *str = "Hello";
str[0] = "Hlw"; //<=== but this is not as explained by other answers
The value in a is copied to c pointer:
char a[] = "I am ok";
char *c = a;
Getting compilation error:
char *c = "I am ok";
char a[] = c;
Why?
An array can only be initialized using aggregate initialization (with a special-case for literals strings, as used in the first case).
The initialization-part in the second case is simply not correct according to the language.
Furthermore, literal strings (as is used in the initialization of c in the second case) are arrays of constant characters, meaning you can't make a non-constant pointer to a literal string. You must use const char*.
As for why it works in the first case, first of all the array a is not constant, so no need for a pointer to const. Secondly when using an array it can decay to a pointer to its first element.
So the definition:
char* c = a;
is really this:
char* c = &a[0];
because the
char *c
is a declaration of the pointer and not its content it can only be initialized by an Adress
This question already has answers here:
What is the type of string literals in C and C++?
(4 answers)
Closed 5 years ago.
How is this even possible?
const char *cp = "Hello world";
I am currently reading C++ primer and i found this example (I am a very beginner).
Why is it possible to initialize a char pointer with a string? I really can't understand this example, as far as I know a pointer can only be initialized with & + the address of the object pointed OR dereferenced and THEN assigned some value.
String literals are really arrays of constant characters (with the including terminator).
When you do
const char *cp = "Hello world";
you make cp point to the first character of that array.
A little more explanation: Arrays (not just C-style strings using arrays of char but all arrays) naturally decays to pointers to their first element.
Example
char array[] = "Hello world"; // An array of 12 characters (including terminator)
char *pointer1 = &array[0]; // Makes pointer1 point to the first element of array
char *pointer2 = array; // Makes pointer2 point to the first element of array
Using an array is the same as getting a pointer to its first element, so in fact there is an address-of operator & involved, but it's implied and not used explicitly.
As some of you might have noted, when declaring cp above I used const char * as the type, and in my array-example with pointer1 and pointer2 I used a non-constant plain char * type. The difference is that the array created by the compiler for string literals are constant in C++, they can not be modified. Attempting to do so will lead to undefined behavior. In contrast the array I created in my latter example is not constant, it's modifiable and therefore the pointers to it need not be const.
"Hello world" is a read-only literal with a const char[12] type. Note that the final element is the NUL-terminator \0 which the language exploits as an "end of string" marker. C and C++ allow you to type a literal using " surrounding the alphanumeric characters for convenience and that NUL-terminator is added for you.
You are allowed to assign a const char[12] type to a const char* type by a mechanism called pointer decay.
pointer can only be initialized with & + the address of the object pointed
int i = 0;
int *pointer = &i;
It's correct but it not the only way to initialized pointers. Look at below exmaple.
int *pointer;
pointer = (int*)malloc(100 * sizeof(int));
It is how you initialized pointers by allocating memory to it.
How is this even possible?
It works because "Hello World" is a string constant. You do not need to allocate this memory, it's the compiler's job.
By the way, always use smart pointer instead of raw pointer if you're using c++.
char * c = "world"; // works fine
but
int * p = 10; // throws an error
it needs to be done like
int * p = new int(10); // in C++
int * p = (int*) malloc(1 * sizeof(*int)); // in C
If pointer is to be allocated to some memory or it should be referencing to some address then why a string can be stored in a character pointer without allocating memory to it, why not a integer datatype ?
C and C++ happen to provide a syntax, the string literal, for creating a value of type array of char with a specified initial value.
In C, the string literal "world" is of type char[6] (5 for the length of the string plus 1 for the terminating '\0'). In C++, it's of type const char[6]. The difference is for historical reasons. In either language, string literals should always be treated as read-only.
And like any expression of array type, it's implicitly converted, in most contexts, to a pointer to its first element. That's why
const char *c = "world";
is valid. The string literal "world" itself creates an anonymous array object, and the initialization causes c to point to the array object's first element.
There doesn't happen to be such a built-in syntax for creating an object of type int.
Well, actually there is. C99 added compound literals, letting you write:
int *p = (int[]){ 10 };
which creates an array object of type int[1], with the same implicit conversion to int*. (C++ doesn't have compound literals.) (The lifetime of the array object depends on the context in which it appears; if it's inside a function body, the array ceases to exist when the enclosing block finishes. String literals, on the other hand, have static storage duration and exist for the entire execution of the program.)
Incidentally, this:
int * p = (int*) malloc(1 * sizeof(*int)); // in C
is incorrect; you want int*, not *int. But it's better written as:
int *p = malloc(sizeof *p));
Casting the result of malloc is unnecessary in C, and can hide errors in some cases. And using sizeof *p makes the code more robust; if you later change p from an int* to, say, a double*, you only have to change the type in one place.
Because by definition, string literals have the type char*, the pointer to the first character of the string.
A Pointer variable should store address .
char * c = "world"; // works fine
because , "world" is assigned memory in the read-only block of the program , hence "world" got some address and this address is stored in pointer c
int * p = 10; // throws an error
because 10 is constant integer and is not allocated any memory yet , hence it has no address . We cannot store constant 10 in the pointer p because its not an address .
Thats why we do
int * p = new int(10); // in C++
int * p = (int*) malloc(1 * sizeof(int)); // in C
This allocates memory with value 10 to integer , and the address of that integer is stored in p which is correct