-2

I have read

Directly assigning values to C Pointers

However, I am trying to understand this different scenario...

int *ptr = 10000;
printf("value: %d\n", ptr);
printf("value: %d\n", *ptr);

I got a segmentation fault on the second printf.

Now, I am under the impression that 10000 is a memory location because pointers point to the address in the memory. I am also aware that 10000 could be anywhere in the memory (which might already be occupied by some other process)

Therefore, I am thinking so the first print is just saying that "ok, just give me the value of the address as some integer value", so, ok, I got 10000.

Then I am saying "ok, now deference it for me", but I have not put anything in it so (or it is uninitialized) so I got a segmentation fault.

Maybe my logic is already totally off the track and this point.

UPDATED::::

Thanks for all the quick responses.. So here is my understanding.

First, int *ptr = 10000; is UB because I cannot assign a pointer to a constant value.

Second, the following is also UB because instead of using %p, I am using %d. printf("value: %d\n", ptr)

Third, I have given an address (although it is UB), but I have not initialized to some value so, the following statement got seg fault. print("value: %d\n", *ptr)

Is my understanding correct now ?

thanks.

Community
  • 1
  • 1
  • `**ptr = 10;` shouldn't be compiled with a error `error: invalid type argument of unary '*' (have 'int')`. What did you do? – MikeCAT Sep 27 '15 at 00:50
  • 2
    possible duplicate of [Directly assigning values to C Pointers](http://stackoverflow.com/questions/17665793/directly-assigning-values-to-c-pointers) – too honest for this site Sep 27 '15 at 00:51
  • @MikeCAT, you are right.. I have rephrased my question.. Just want to make sure the first part of my understanding is correct.. – user2001996 Sep 27 '15 at 00:53
  • You are also using the wrong format specifier printing a pointer. This is also UB. Enable compiler warnings. If it still does not complain, delete the compiler from your drive and get a proper one, e.g. gcc or clang. – too honest for this site Sep 27 '15 at 00:56
  • @Olaf: The proposed duplicate [Directly assigning values to C pointers](http://stackoverflow.com/questions/17665793/directly-assigning-values-to-c-pointers) is not a good duplicate; that is dealing with an uninitialized pointer, not a pointer initialized with an (integer) constant address. That's not to say this question isn't a duplicate (it probably is); it just isn't a duplicate of that question. – Jonathan Leffler Sep 27 '15 at 00:58
  • 1
    It appears that your runtime system disagrees with you; 10000 is not an address it is going to allow you to dereference — hence the crash. You're invoking undefined behaviour multiple times, so almost anything is possible, but a crash is a strong indication that what you're doing is not sanctioned by the runtime system. – Jonathan Leffler Sep 27 '15 at 01:02
  • @JonathanLeffler: You are right. Quick google shows http://stackoverflow.com/questions/12108160/assigning-casting-integers-to-pointers. You might find a better one. – too honest for this site Sep 27 '15 at 01:15
  • "I cannot assign a pointer to a constant value" you do the opposite. – too honest for this site Sep 27 '15 at 01:29
  • @Olaf: It's not really a duplicate of that one either. The program in that question uses a cast: `p=(int *)5`; the code in this question attempts to initialize a pointer with an integer constant without a cast, which is a constraint violation. – Keith Thompson Sep 27 '15 at 01:31
  • @KeithThompson: I did not state it is. That's just what I found quickly. Actually OP should gave gotten a compiler warning at least. I have retracted my close-vote. Still think it is a badly researched question. – too honest for this site Sep 27 '15 at 01:33

3 Answers3

2
int *ptr = 10000;

This is not merely undefined behavior. This is a constraint violation.

The expression 10000 is of type int. ptr is of type int*. There is no implicit conversion from int to int* (except for the special case of a null pointer constant, which doesn't apply here).

Any conforming C compiler, on processing this declaration, must issue a diagnostic message. It's permitted for that message to be a non-fatal warning, but once it's issued that message, the program's behavior is undefined.

A compiler could treat it as a fatal error and refuse to compile your program. (In my opinion, compilers should do this.)

If you really wanted to assign ptr to point to address 10000, you could have written:

int *ptr = (int*)10000;

There's no implicit conversion from int to int*, but you can do an explicit conversion with a cast operator.

That's a valid thing to do if you happen to know that 10000 is a valid address for the machine your code will run on. But in general the result of converting an integer to a pointer "is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation" (N1570 section 6.3.2.3). If 10000 isn't a valid address (and it very probably isn't), then your program still has undefined behavior, even if you try to access the value of the pointer, but especially if you try to dereference it.

This also assumes that converting the integer value 10000 to a pointer type is meaningful. Commonly such a conversion copies the bits of the numeric value, but the C standard doesn't say so. It might do some strange implementation-defined transformation on the number to produce an address.

Addresses (pointer values) are not numbers.

printf("value: %d\n", ptr);

This definitely has undefined behavior. The %d format requires an int argument. On many systems, int and int* aren't even the same size. You might end up printing, say, the high-order half of the pointer value, or even some complete garbage if integers and pointers aren't passed as function arguments in the same way. To print a pointer, use %p and convert the pointer to void*:

printf("value: %p\n", (void)ptr);

Finally:

printf("value: %d\n", *ptr);

The format string is correct, but just evaluating *ptr has undefined behavior (unless (int*)10000 happens to be a valid address).

Note that "undefined behavior" doesn't mean your program is going to crash. It means that the standard says nothing about what will happen when you run it. (Crashing is probably the best possible outcome; it makes it obvious that there's a bug.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • thanks for the explanation. So the fact, that I was able to get the output of 10000 with printf("value %d", ptr) in itself is already UB and just so it got printed ? – user2001996 Sep 27 '15 at 01:47
  • @user2001996: Yes, the fact that `printf("value %d\n", ptr);` appeared to work was just a matter of luck. To be precise, it was *bad* luck; a crash would have told you that there was something wrong. I've added a bit more information to my answer. – Keith Thompson Sep 27 '15 at 01:59
1

No, the definition int *ptr = 10000 does not give undefined behaviour.

It converts the literal value 10000 into a pointer, and initialises ptr with that value.

However, in your example

int *ptr = 10000;
printf("value: %d\n", ptr);
printf("value: %d\n", *ptr);

both of the printf() statements give undefined behaviour.

The first gives undefined behaviour because the %d format tells printf() that the corresponding argument is of type int, which ptr is not. In practice (with most compilers/libraries) it will often happily print the value 10000, but that is happenstance. Essentially (and a little over-simplistically), for that to happen, a round-trip conversion (e.g. converting 10000 from int to pointer, and then converting that pointer value to an int) needs to give the same value. Surviving that round trip is NOT guaranteed, although it does happen with some implementations, so the first printf() might APPEAR well behaved, despite involving undefined behaviour.

Part of the problem with undefined behaviour is that one possible result is code behaving as the programmer expects. That doesn't make the behaviour defined. It simply means that a particular set of circumstances (behaviour of compiler, operating system, hardware, etc) happen to conspire to give behaviour that seems sensible to the programmer.

The second printf() statement gives undefined behaviour because it dereferences ptr. The standard gives no basis to expect that a pointer with value 10000 corresponds to anything in particular. It might be a location in RAM. It might be a location in video memory. It might be a value that does not correspond to any location in memory that exists on your computer. It might be a logical or physical memory location that your operating system deems your process is not allowed to access (which is actually what causes an access violation under several operating systems, which then send a signal to the process running your program directing it to terminate).

A lot of C compilers (if appropriately configured) will give a warning on the initialisation of ptr because of this - an initialisation like this is easier for the compiler to detect, and usually indicates problems in subsequent code.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

This may cause undefined behavior since the pointer converted from 10000 may be invalid.

Your OS may not allow your program to access the address 10000, so it will raise Segmentation Fault.

int *x = some numerical value (i.e. 10, whatever)

may be for microcomputers or low-level (example: creating OS).

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • @Olaf. However, is my understanding correct though that I am able to print ptr because it is simply a value that I have given and nothing else ? – user2001996 Sep 27 '15 at 00:56
  • @user2001996: Printing a pointer initialized with an invalid type is already UB. – too honest for this site Sep 27 '15 at 00:58
  • 2
    @user2001996: UB is defined by the C standard as **§3.4.3 undefined behavior** _behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements. NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message)._ – Jonathan Leffler Sep 27 '15 at 01:05
  • @user2001996 Memorise that phrase! You will soon become archenemies. – too honest for this site Sep 27 '15 at 01:30