Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The difference between char* and int*

What is the difference between char* and int*? Sure, they are of different types, but how is it that I can write

char* s1="hello world";

as

"hello world"

it is not a one character, it's an array of characters, and I cannot write

*s1

as

char* s1 = {'h','e','l','l','o',' ','w','o','r','l','d'};

and

int* a = {2,3,1,45,6};

What is the difference?

like image 212
Abdallah Moussawi Avatar asked Jul 21 '14 20:07

Abdallah Moussawi


2 Answers

It is quite simple: A string literal, i.e., "foobar" is compiled to an array of chars which is stored in the static section of your program (i.e., where all constants are stored) and null terminated. Then, assigning this to a variable simply assigns a pointer to this memory to the variable. E.g., const char* a = "foo"; will assign the address where "foo" is stored to a.

In short, a string constant already brings the memory where it is to be stored with it.

In contrast, initializing a pointer with an initializer list, (i.e., a list of elements inside curly braces) is not defined for pointers. Informally, the problem with an initializer list -- in contrast to a string literal -- is that it does not "bring its own memory". Therefore, we must provide memory where the initializer list can store its chars. This is done by declaring an array instead of a pointer. This compiles fine:

char s1[11]={'h','e','l','l','o',' ','w','o','r','l','d'}

Now, we provided the space where the chars are to be stored by declaring s1 as an array.

Note that you can use brace initialization of pointers, though, e.g.:

char* c2 = {nullptr};

However, while the syntax seems equal, this something completely different which is called uniform initialization and will simply initialize c2 with nullptr.

like image 148
gexicide Avatar answered Oct 29 '22 20:10

gexicide


In your first case, the string literal is decaying to a pointer to a const char. Although s1 really should be const char *, several compiler allow the other form as an extension:

const char* s1 = "hello world" ;

A sting literal is an array of const char, we can see this from the draft C++ standard section 2.14.5 String literals which says (emphasis mine going forward):

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).

The conversion of an array to pointer is covered in section 4.2 Array-to-pointer conversion which says:

[...] an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.[...]

Your other cases do not work because a scalar which can be an arithmetic type, enumeration types or a pointer type can only be initialized with a single element inside braces this is covered in the draft C++ standard section 5.17 Assignment and compound assignment operators 8.5.1 List-initialization paragraph 3 which says:

List-initialization of an object or reference of type T is defined as follows:

and then enumerates the different cases the only that applies to the right hand side for this case is the following bullet:

Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element; if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.

which requires the list to have a single element, otherwise the final bullet applies:

Otherwise, the program is ill-formed.

In your two cases even if you reduced the initializer to one variable, the types are incorrect h is a char and 2 is an int which won't convert to a pointer.

The assignment could be made to work by assigning the results to an array such as the following:

  char s1[] = { 'h', 'e', 'l', 'l', 'o',' ', 'w', 'o', 'r', 'l', 'd' } ;
  int  a[]  = { 2, 3, 1, 45, 6 } ;

This would be covered in section 8.5.1 Aggregates which says:

An array of unknown size initialized with a brace-enclosed initializer-list containing n initializer-clauses, where n shall be greater than zero, is defined as having n elements (8.3.4). [ Example:

int x[] = { 1, 3, 5 };

declares and initializes x as a one-dimensional array that has three elements since no size was specified and there are three initializers. —end example ] An empty initializer list {} shall not be used as the initializer-clause for an array of unknown bound.104

Note:

It is incorrect to say that a brace-init-list is not defined for pointers, it is perfectly usable for pointers:

int x   = 10 ;
int *ip =  &x ;
int *a  = {nullptr} ;
int *b  = {ip} ;
like image 34
Shafik Yaghmour Avatar answered Oct 29 '22 18:10

Shafik Yaghmour