-2

I have a question to the following code:

#include <stdio.h>

int main() {
    int i;

    char char_array[5] = "abcde";
    int int_array[5] = {1, 2, 3, 4, 5};

    char *char_pointer;
    int *int_pointer;

    for(i=0; i < 5; i++) {
        printf("[integer pointer] points to %p, which contains the integer %d\n", int_pointer, *int_pointer);
        int_pointer = int_pointer + 1;
    }

    for(i=0; i < 5; i++) {
        printf("[char pointer] points to %p, which contains the char '%c'\n", char_pointer, *char_pointer);
        char_pointer = char_pointer + 1;
    }
}

I didn´t initialized any pointer, just set the pointer´s type. These two pointers are pointing to the right memory address of the array and starts at position [0].

Using Ubuntu 7.04 with gcc compiler.

If I run the code i get these results:

[integer pointer] points to 0xbffff7f0, which contains the integer 1
[integer pointer] points to 0xbffff7f4, which contains the integer 2
[integer pointer] points to 0xbffff7f8, which contains the integer 3
[integer pointer] points to 0xbffff7fc, which contains the integer 4
[integer pointer] points to 0xbffff800, which contains the integer 5
[char pointer] points to 0xbffff810, which contains the char 'a'
[char pointer] points to 0xbffff811, which contains the char 'b'
[char pointer] points to 0xbffff812, which contains the char 'c'
[char pointer] points to 0xbffff813, which contains the char 'd'
[char pointer] points to 0xbffff814, which contains the char 'e'

I know it is not the correct programming style and you should not let the pointers uninitialized, nonetheless I came across this and want to ask you, why does the pointer know to which address he has to point without initializing.

Also I put two more arrays into the code int_array2 and char_array2, first after int_array/char_array and second before int_array/char_array. But I still get the same results...

Maybe someone knows the magic behind this. Thanks in advance for taking your time to answer my question.

Luca
  • 221
  • 2
  • 11
  • 5
    [Does “Undefined Behavior” really permit *anything* to happen?](http://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) and [Undefined, unspecified and implementation-defined behavior](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – kaylum Dec 07 '15 at 19:49
  • Your code is malformed and will not compile. Do you mean that `)` on line 7 to be an `=`? – John Bollinger Dec 07 '15 at 19:50
  • Sorry, this was due to copy&paste issues from my VM I guess. I will change it now. – Luca Dec 07 '15 at 19:51
  • line 6 and 7 are not used, but are also with problems. Main problem are the two pointers which are used uninitialized. – Michi Dec 07 '15 at 19:51
  • undefined behaviour means that the C programming language standard does not specify how the program should behave given a piece of source code. The result you will get will be dependent on the implementation of the language (compiler, linker,...) but in this case the pointer and arrays are stored right next to each other on the stack, so you are getting access to the arrays by pointer manipulation. – ForeverStudent Dec 07 '15 at 19:52
  • "These two pointers are pointing to the right memory address of the array and starts at position [0]" -- what makes you say that? – John Bollinger Dec 07 '15 at 19:52
  • Did this code run as it is? `Printf()` is `printf()`. Also, please indent it correctly. – Iharob Al Asimi Dec 07 '15 at 19:52
  • @JohnBollinger Where exactly in that code those two pointers are pointing to "the right memory address"? – Michi Dec 07 '15 at 19:54
  • @Michi, that's what I'm asking. I quoted the OP. – John Bollinger Dec 07 '15 at 19:55
  • @JohnBollinger OH, my bad Sir. Sorry about that. – Michi Dec 07 '15 at 19:55
  • While it is theoretically possible that your pointers will somehow acquire the values you described, I find it highly unlikely in practice. What compiler did you use? What compilation settings? – AnT stands with Russia Dec 07 '15 at 19:58
  • Updated my post with the results after running this code and my system/compiler – Luca Dec 07 '15 at 20:00
  • I just confirmed it to be very very sure, but it's impossible to reproduce this exact behavior. It has to be a very wierd coincidence. I compiled and executed this code, the pointers were pointing nowhere and the result was as unexpected as I expected. – Iharob Al Asimi Dec 07 '15 at 20:03
  • That's quite the compiler quirk. On Debian stable, gcc 4.9.2-10 I'm getting `8949ed31 89485ed1 e48348e2 495450f0 0610c0c7 01 00 00 00 00`. – Kenney Dec 07 '15 at 20:03
  • @Luca, there really is no useful answer other than dbush's. You could disassemble your program to see how the compiler wrote the machine code, which would explain the specific results you observed, but you cannot safely use that information to predict the behavior of your compiler or any other. – John Bollinger Dec 07 '15 at 20:04
  • Thank you for all your answers. @JohnBollinger, i will try to disassemble it and maybe find something, that can explain this strange result. – Luca Dec 07 '15 at 20:09
  • I've tested with a few different compilers, 4.4 and 4.8 4.9 , but this behavior is not really reproducible , even optimizations cause it to change. – g24l Dec 07 '15 at 21:27

2 Answers2

3

First, as you might know, this behavior is called undefined behavior in the standard.

From standard perspective, this program might remove your entire hard disk, launch nuclear missiles, or send your boss a very bad mail. However, usually it ends up in program failure.

Now back to your case - I think that it happened because one or more of this options:

  1. Your compiler groups memory of variables by types.
  2. Your compiler groups memory of variables by alignment size.

Now it still not good reasons, but maybe this grouping is because unnecessary line in the compiler code when variable isn't initialized. It may be possible that this variable of the compiler is uninitialized too :-)

Tal
  • 347
  • 2
  • 16
  • Seems that this is a proper answer w/o all the fuss. Adding some assembler code to it would make the case. – g24l Dec 07 '15 at 20:08
0

When a local variable is uninitialized, the contents of those variables is undefined.

That means the contents of those variables cannot be predicted. Attempting to read them might output something unexpected, or might appear to work. In the case of pointer variables, dereferencing will typically cause a core dump, but not necessarily.

That's why it's important to always initialize your variables before attempting to read (or dereference) them.

An example of how using uninitialized variables can come back to bite you is OpenSSL. They intentionally leave certain variables undefined as a source of randomness. But someone unfamiliar with the code later ran Valgrind on it, which reported the "issue". The "bug" was then fixed, which caused the random number generator to break. You can find more details here.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Em, do you mean to say pointers instead of variables? – g24l Dec 07 '15 at 19:53
  • 1
    @g24l Local vars as well - they are reserved on the stack. – Kenney Dec 07 '15 at 19:53
  • 1
    @Kenney yes ofcourse they are not initialized, but reading an initialized local (non pointer type ) does not cause core dump,right? – g24l Dec 07 '15 at 19:56
  • 1
    In this context it should be used the word pointer nut just variable (or local variable). – Michi Dec 07 '15 at 19:57
  • 1
    @g24l Reading an uninitialized variable *probably* won't cause a core dump, although dereferencing an uninitialized pointer variable is likely to do so. – dbush Dec 07 '15 at 19:57
  • @g24l Yes indeed - a non-initalized local variable doesn't produce a coredump, but it is still undefined. – Kenney Dec 07 '15 at 19:58
  • This is the first I time hear that readin an uninitialized e.g. int will cause a core dump. Ofcourse using that value the wrong way may actually cause WW3 in some specific applications, but just reading a local (non pointer type) does not cause core dump. – g24l Dec 07 '15 at 20:01
  • printing a local variable [int a](http://ideone.com/5YULld) which is not initialized , will print (0) or garbege, but printing an uninitialized pointer [int *a](http://ideone.com/0Hnkqk) will cause `Segmentation fault (core dumped)`. So like I said should be used the word Pointer in this context and not just =>> local variable. – Michi Dec 07 '15 at 20:01
  • 1
    The contents of uninitialized variables are *indeterminate*. You can do some things with them (including reading, under some circumstances, and even outputting if you're careful) without causing UB. – M.M Dec 07 '15 at 20:03
  • @M.M yes you can, have you tried *valgrind* on an *openssl* program? They intentionally use uninitialized bytes. – Iharob Al Asimi Dec 07 '15 at 20:04
  • @iharob openssl is terrible code, it wouldn't surprise me if it relies on incidental behaviour of common compilers – M.M Dec 07 '15 at 20:05