开发者

C++: What's wrong on int *j; *j=50; ?

开发者 https://www.devze.com 2023-03-24 06:07 出处:网络
This is a newbie C++ pointer question. I have no clue on why this happen... I found that if i write this code. It is totally valid.

This is a newbie C++ pointer question. I have no clue on why this happen...

I found that if i write this code. It is totally valid.

Code1

int *j;    //create an pointer j
*j = 50;   //assign 50 to the *j, meaning value pointed by address 50 is xxx

However, when I wanna try to make it more simple. The compiler give me this error message.

Code2

开发者_StackOverflow
int *j = 50; //i guess this should be the same with Code1...

Compile error

error: invalid conversion from ‘int*’ to ‘int’

So why would be like that?


There's a bit of ambiguity in the C syntax there.

int *j = 50;

is equivalent to

int *j;
j = 50;

Actually, what you're doing in the first snippet of code is dangerous because you haven't allocated any memory for j before assigning a value to it yet. You'll need to make memory for it like so:

in C:

int *j = (int*) malloc(sizeof(int));
*j = 50;

in C++

int *j = new int;
*j = 50;

Or point the pointer at some other block of memory that's already valid:

int k;
int *j = &k;
*j = 50;
printf("%d", k); // 50

Edit: It's worth pointing out that the ambiguity has to do with the '*' symbol. In the declaration, int *j; the *j means "a pointer named j". But when you're using it in the second line "*j = 50", * becomes the dereference symbol that means "the value at address j".


They have different meanings altogether.

The first one declares a pointer, and sets the int pointed to by the address currently in j to 50. Without other context, this is already bad; the address in j is not initialized and you'd most likely cause a segmentation fault by writing a value to a random place in memory.

The second piece of code declares a pointer, and defines the address stored in it to 50. If you separate it, it's exactly like writing (note the lack of an asterisk in the second statement):

int *j; j = 50;


After you declare int *j; a space of type int * is allocated on the stack (in this case) which has some address addr_stk and with contents which we do not know, ie. garbage.

 +--------+          +--------+
 |  ???   |----+     |  xxx   |     trying to store 50 here
 +--------+    |     +--------+
 |   j    |    |     |        |
 +--------+    |     +--------+
 |addr_stk|    +---->|  ???   |     have no permission to access this location
 +--------+          +--------+

When you use *j = 50; the contents of the pointer variable (object) j is used as the address to store the value 50 in there. Therefore you do an attempt to store the value 50 in some address location which has a garbage address value, which means it could be anywhere. Whenever you will try to access the memory locations which are not allocated to you will not be able to store or access the location, the operating system will stop you from it and throw some error.

What you need to do is first initialize the pointer variable j with some address which is valid. This can be done by first allocating some memory with malloc and then using it. Or initializing the j with the address of some other variable (local or global). like

int *j, i;
j = &i;
*j = 50;

or

int *j;
j = malloc (sizeof (int));
*j = 50;

in both the case when accessing *j we have a valid address inside j, therefore using the contents of j as address (pointer access), is valid, as *j resolves to a valid memory access.

Important thing is that when you allocate memory with malloc you should always free the memory. This is a good habit, or else in large programs it will lead to memory leaks.


Both of your examples are wrong.

The first:

int *j;
*j = 50;

stores 50 to the address j. However, you never initialized j, so you are simply storing to an unknown address. Sometimes this will "succeed", sometimes this will make your application crash, and sometimes it will merely corrupt your application state without causing an error; it's never what you actually want to do.

The second:

int *j = 50;

tries to initialized a variable of type "pointer-to-int" with a value of type "int", which is an error.

Instead, you want to do something like:

int i = 50;
int *j = &i; // j is now a pointer to i.

or:

int i;
int *j;
j = &i;  // note: no * before j.  j now contains a valid address.
*j = 50; // store 50 to the address j.  After this, i == 50.


The * is a part of the variable's type, not its name.

int* j means "I have a variable named j, which is a pointer to an int".

int* j = 50 (code 2) means "I have a variable named j, which is a pointer to an int, and which shall be initialized with a value of 50". This is not allowed; pointers may not be initialized with an integer value other than 0 without an explicit cast. Explicitly casting to get around this is a very, very bad idea if you don't know what you are doing, and if you are asking these questions then it is absolutely certain that you don't know what you're doing well enough to try.

You're supposed to be able to figure this out from the error message. An invalid conversion is just that: your code tries to convert from one type to the other (via the assignment), and that is not valid. The thing you're assigning to is not of a compatible type for what you're assigning. It tells you what the types involved are, too.

*j = 50 (second line in code 1) means "write the value 50 at the location that j points at". This is bad, because j hasn't been initialized yet. This is called "undefined behaviour" and is exactly that - it may fail in any number of ways, or not, but it is always wrong even if it seems to be working. But it will compile, and most compilers will not even try to warn you about this sort of thing unless you ask them for really high warning levels - if at all.


int *j = 50

Is actually equal to

int *j;
j = 50;

Because assigment on initialization assigns the variable itsel no matter what.

In both cases it's a very bad idea because the pointer is invalid.

0

精彩评论

暂无评论...
验证码 换一张
取 消