Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, why can't an integer value be assigned to an int* the same way a string value can be assigned to a char*?

Tags:

c

char

pointers

int

I've been looking through the site but haven't found an answer to this one yet.

It is easiest (for me at least) to explain this question with an example.

I don't understand why this is valid:

#include <stdio.h>

int main(int argc, char* argv[])
{
  char *mystr = "hello";
}

But this produces a compiler warning ("initialization makes pointer from integer without a cast"):

#include <stdio.h>

int main(int argc, char* argv[])
{
  int *myint = 5;
}

My understanding of the first program is that creates a variable called mystr of type pointer-to-char, the value of which is the address of the first char ('h') of the string literal "hello". In other words with this initialization you not only get the pointer, but also define the object ("hello" in this case) which the pointer points to.

Why, then, does int *myint = 5; seemingly not achieve something analogous to this, i.e. create a variable called myint of type pointer-to-int, the value of which is the address of the value '5'? Why doesn't this initialization both give me the pointer and also define the object which the pointer points to?

like image 509
sav0h Avatar asked Jul 21 '15 19:07

sav0h


2 Answers

In fact, you can do so using a compound literal, a feature added to the language by the 1999 ISO C standard.

A string literal is of type char[N], where N is the length of the string plus 1. Like any array expression, it's implicitly converted, in most but not all contexts, to a pointer to the array's first element. So this:

char *mystr = "hello";

assigns to the pointer mystr the address of the initial element of an array whose contents are "hello" (followed by a terminating '\0' null character). Incidentally, it's safer to write:

const char *mystr = "hello";

There are no such implicit conversions for integers -- but you can do this:

int *ptr = &(int){42};

(int){42} is a compound literal, which creates an anonymous int object initialized to 42; & takes the address of that object.

But be careful: The array created by a string literal always has static storage duration, but the object created by a compound literal can have either static or automatic storage duration, depending on where it appears. That means that if the value of ptr is returned from a function, the object with the value 42 will cease to exist while the pointer still points to it.

As for:

int *myint = 5;

that attempts to assign the value 5 to an object of type int*. (Strictly speaking it's an initialization rather than an assignment, but the effect is the same). Since there's no implicit conversion from int to int* (other than the special case of 0 being treated as a null pointer constant), this is invalid.

like image 145
Keith Thompson Avatar answered Oct 09 '22 08:10

Keith Thompson


When you do char* mystr = "foo";, the compiler will create the string "foo" in a special read-only portion of your executable, and effectively rewrite the statement as char* mystr = address_of_that_string;

The same is not implemented for any other type, including integers. int* myint = 5; will set myint to point to address 5.

like image 43
Colonel Thirty Two Avatar answered Oct 09 '22 07:10

Colonel Thirty Two