14

I understand the basics of how pointers work, but the following example confuses me.

int *myNum = 10; // Produces an error

char *myChar = "Something"; // Works fine

Why does assigning char work but integer doesn't (Maybe cause char is treated as an array)?

As well what confuses me when directly assigning a pointer variable, does it automatically get an address?

char *myChar = "Something";

and

char myChar = "Something";
char *charAddr = &myChar;

What would be the difference here, or equals?

Nakilon
  • 34,866
  • 14
  • 107
  • 142
J. Doe
  • 905
  • 1
  • 10
  • 23
  • 3
    `char myChar = "Something";` does not work, because `"Something"` is not a char. – user253751 Mar 14 '16 at 00:43
  • What you're looking for is [Array to pointer conversion](http://en.cppreference.com/w/c/language/conversion) – hgiesel Mar 14 '16 at 00:48
  • @immibis ITYM `"Something"` is not implicitly convertible to `char`. `char myChar = 5.5;` is legal – M.M Mar 14 '16 at 00:53
  • I think you are simply confusing single quotes and double quotes. `int *myNum = 10; ` is wrong the same way as `char *myChar = 'A';`. Single quotes surround chars; double quotes surround constant arrays of chars, also known as C string literals. That said, `char *myChar = "Something";` is only half right, as others pointed out. Strict compilers will demand that you declare `const char *myChar`, since you cannot write to elements in the array pointed to by `myChar` on modern architectures. – Peter - Reinstate Monica Mar 14 '16 at 11:30

5 Answers5

22
"Something"

is essentially short for:

static const char some_hidden_array[] = {'S', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'};
some_hidden_array

That is, when you write "Something", the compiler generates an array behind the scenes, and gives you a pointer to the start of that array. Since this is already a pointer to a char, you'll have no problem assigning it to a variable of type "pointer to a char" (written as char*).

10

is not short for anything similar. It's just the number 10 - it's not a pointer to an array containing the number 10, or anything like that.

Note that a char is a single character, not a string, which is why the string syntax is unusual compared to most other types - a string is several chars, not just one. If you try to use a plain old char, you'll see the same thing:

char *myChar = 'a'; // error

or for any other type:

float *myFloat = 42.1f; // error

In other words, it's not strange that 10 gives an error - if anything, it's strange that "Something" doesn't. (At least, it's strange until you know how string literals work)

user253751
  • 57,427
  • 7
  • 48
  • 90
10

It's the same thing (no magic from the compiler is happening). By default, literals like 10 are int values, not int*.

You need to cast:

int *myNum = (int*)10; // Need to cast
char *myChar = "Something"; // No need to cast "..." is already a char*

Note that it's dangerous to reference a pointer to absolute value like this because you will end up with the address 10 in CPU memory.

Regarding your second question, "..." is treated as a contiguous sequence of char in memory similar to array and equivalent to char*.

For a thoughtful understanding of C, pointers and differences between arrays and pointers, you should read this: Expert C Programming: Deep C Secrets by Peter van der Linden.

John Difool
  • 5,572
  • 5
  • 45
  • 80
  • Thank you! As for second question, I meant more like if those 2 equal? Is first example a shorter way of getting the address? Thanks! – J. Doe Mar 14 '16 at 00:00
  • 1
    Remember to select this as your accepted answer if it answered your question. – Kent Kostelac Mar 14 '16 at 00:52
  • 4
    `"..."` is not a `char*`. And I wouldn't recommend a C book for learning C++; the idioms are entirely different. – Lightness Races in Orbit Mar 14 '16 at 10:56
  • @J.Doe No, the second example simply doesn't work. A string literal is *not* a `char`, it's a `char[]`. Changing that, taking the address of a `char[]` will give you a pointer to a pointer - in this case, a pointer to a stack variable, so only defined until the scope exits. This is quite important, since string literals are a bit of magic - they appear "local", but don't actually have a scope; the original pointer is valid everywhere, the pointer to a pointer isn't. – Luaan Mar 14 '16 at 11:31
3

Why does assigning char work but integer doesn't (Maybe cause char is treated as an array)?

You are right, "Something" is a string literal and can be treated as char array. After char *myChar = "Something"; the following thing happen: it is allocated length+1 bytes of memory where "Something" will be stored, myChar is pointed to the starting address of this memory. String literals are somewhat special.

Here is a general way of initializing array with constant values:

// valid initializations;
char s2[] = { 'a', 'b', 'c' };
int a[] = { 1, 2, 3 };
char s1[] = "123";

As well what confuses me when directly assigning a pointer variable, does it automatically get an address?

Yes.

Take a look at 8.5.2 Character arrays of c++ docs

Ivan Gritsenko
  • 4,166
  • 2
  • 20
  • 34
2

When you do char *myChar = "Something";, you create a read-only string literal somewhere in the memory, which ends in a null character. Now this is something special with the compiler, that it interprets a chunk of 'char' variables stored continuously and ending with a null character as string. So basically you created an array of characters, and when you do *myChar*, it returns the string.

In case of integers or any other data types, it differentiates between int *ptr as a pointer to an integer, and int ptr as an integer. You are getting an error probably because the address you entered may not be valid/available to you.

Also, doing

char myChar = "Something";  //this is an error, since char can hold one character
char *charAddr = &myChar;

Note that myChar and &myChar are the same, since myChar is a pointer!

Edit: Refer here about string literals: Is it possible to modify a string of char in C?

Community
  • 1
  • 1
Sahil Arora
  • 875
  • 2
  • 8
  • 27
  • Thank you for explanation, so does type *var = something, always create a read-only variable in memory? And as per second question, I more meant like if those 2 are equal (shorter way) :) Thanks! – J. Doe Mar 14 '16 at 00:03
  • @J.Doe Yes. Have a look at this: http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c – Sahil Arora Mar 14 '16 at 00:06
  • Thank you, this does help a lot. – J. Doe Mar 14 '16 at 00:20
  • 2
    @J.Doe no, `type *var = something` does not create a read-only variable. It is only the string literal `"Something"` which is read-only (and it is not a variable) – M.M Mar 14 '16 at 00:55
1

While theoretically the first int *myNum = 10 makes sense—especially if you know there is a useful int at address ten—in general it is rarely useful and potentially quite dangerous.

However, there are certain pointer assignments which are widely used and quite safe:

int *myNum = 0;

On 99.9+% of modern CPU architectures, this is the same as

int *myNum = NULL;

See the definition of NULL in <stddef.h> here.

As a general rule, assignment of pointer variables is best done by setting to the address of something else.

int k, *p = &k;
wallyk
  • 56,922
  • 16
  • 83
  • 148
  • 1
    Thanks! Hmm so basically, int *myNum = 10 // Pointer to an address "10" and not actually an address that contains a variable int with a value of 10? – J. Doe Mar 14 '16 at 00:06
  • 1
    `int *myNum = 0;` is the same as `int *myNum = NULL;` on all systems. It makes a null pointer. You're getting mixed up with the fact that null pointer might not be represented by all-bits-zero (which makes no difference to this code) – M.M Mar 14 '16 at 00:57
  • @J.Doe Yes, and your confusion is pretty much exactly why you need to add the explicit cast to make this compile - this is almost always a *mistake*, rather than the intended behaviour. On a modern desktop/server system, you really don't want to use pointers to manually picked addresses. It was useful in the past, though - for example, for direct access to graphics memory (or any other kind of device, really). With hardware abstraction, there's very few legitimate uses (outside of the rather obvious `0`/`NULL` case, which per C standard *always* works :)). – Luaan Mar 14 '16 at 11:26