-3

I attended my class of c++ last day and teacher told me that references must refer to valid memory while pointer may or may not. I was playing with references and suddenly this question came in my mind. When i declare a array_demo of size 10 and assign it values to 10 to 19 why the program is compiling and i'm getting a garbage number if i'm referring something outside array (index 11) which is not a valid memory !

#include <iostream>

using namespace std;


int main()
{
    int array_demo[10];
    int x= 10;
    for(int i=0; i<10; i++)
    {
        array_demo[i]= x; //assigning values to array_demo
        x++;
    }
    for(int j=0; j<10; j++)
    {
        cout<<array_demo[j]<<endl; //printing array values
    }
    cout<<endl;
    cout<<endl;


    int *p_x=array_demo;
    int &ref_x= array_demo[11];

    cout<< *(p_x+11)<< endl;
    cout << ref_x << endl;
}
Abdulla Nilam
  • 36,589
  • 17
  • 64
  • 85
  • I'd suggest reading over [this similar question](http://stackoverflow.com/questions/1239938/c-accesses-an-array-out-of-bounds-gives-no-error-why) – M.M Jul 07 '15 at 04:19
  • @Shiva disagree, that site is for review of working code. This code is broken. (It *appears* to work for OP but that is different to actually working). The question is appropriate here. – M.M Jul 07 '15 at 04:42

4 Answers4

1

References must refer to valid memory when they are bound. However the "punishment" for breaking this rule is undefined behaviour. The compiler does not have to detect or inform you that you have broken the rule.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • Pedantically true. Most all compilers I've worked with (a small list, but anyway ...) don't care and just access whatever memory is there. I'd love to see a counterexample. – PaulProgrammer Jul 07 '15 at 04:32
  • @PaulProgrammer A counterexample of what? Many compilers do not give a warning or error for OP's mistake. I don't see what part of my answer is "pedantic". – M.M Jul 07 '15 at 04:35
  • but my book "jumping into c++" have clearly written it: a reference, unlike pointer must always refer to a valid memory. I think that "punishment" thing is applicable on pointers, it should not be applicable on "reference". when we write differences between pointer and reference we write that pointer may or may not refer to valid memory but under reference we write reference **must** refer to valid memory ! – Prakhar Shukla Jul 07 '15 at 04:35
  • @PrakharShukla Yes, a reference must always refer to valid memory. That is why your code is wrong, since you attempted to form a reference to invalid memory. – M.M Jul 07 '15 at 04:36
  • @MattMcNabb that is contradicting ! but i did not referred it to valid memory !! OK so your answer is "does not matter if you are using **pointer** or **reference**, if you refer to unvalid memory, compiler will print a garbage number in both case. If this is it then it solves my question. thank you. – Prakhar Shukla Jul 07 '15 at 04:44
  • @PrakharShukla both of those things cause undefined behaviour: binding a reference to invalid memory, and accessing invalid memory. If you are not sure what undefined behaviour is then please read the link in my answer. – M.M Jul 07 '15 at 04:49
  • that solved it. I duplicated my question. many thanks . – Prakhar Shukla Jul 07 '15 at 04:57
0

That's not actually a reference. An array is a funny looking pointer.

The array_demo[11] is also representable as *(array_demo+11)

See: http://www.cplusplus.com/doc/tutorial/pointers/#arrays

I do not miss pointer arithmetic.

PaulProgrammer
  • 16,175
  • 4
  • 39
  • 56
  • so i just referred to a pointer using ref_x ? – Prakhar Shukla Jul 07 '15 at 03:51
  • 1
    Kinda ... `array_demo[11]` will locate the value of the 11th element in the array (which is outside the initial declaration), and the `ref_x` will be a reference to that value. – PaulProgrammer Jul 07 '15 at 03:56
  • @PrakharShukla also, accessing an out of bound array is undefined behavior, so anything unexpected can happen. – Ediac Jul 07 '15 at 04:06
  • @Ediac is right. Some (smarter) compilers will flag that, and some 3rd party malloc libraries will cause a failure in this case. If you're doing GCC you might try the `-Wall` option to catch this and lots of other error classes. You'll be rewarded now and in the afterlife for striving to eliminate warnings from your builds. – PaulProgrammer Jul 07 '15 at 04:10
  • Thanks, i use code blocks though. – Prakhar Shukla Jul 07 '15 at 04:18
  • Arrays are quite different to pointers . `X[Y]` meaning `*(X+Y)` is a syntax thing, there is no equivalence of memory layout or whatever. Also you seem to be mixed up about `sizeof(int)`; the equivalent expression is `*(array_demo+11)`. – M.M Jul 07 '15 at 04:19
  • You mean `11`, not `11 * sizeof(int)`. Or maybe you meant to cast `array_demo` to `char*`. (and then back to `int*` later) –  Jul 07 '15 at 04:20
  • @Ediac that is what my question is. If i was accessing something outside the array which as you say is undefined behavior, can be referred. But i studied that references must point to something valid. – Prakhar Shukla Jul 07 '15 at 04:21
  • @PaulProgrammer This is what i am noticing, tell me i'm right or wrong: when i used ref_x, it used the memory which was validated by array as an array is a funny pointer and it pointed to that block that was outside array and made it valid for ref_x to use it ? – Prakhar Shukla Jul 07 '15 at 04:26
  • Commenters are correct, that I should not have used `sizeof()`. I momentarily forgot that pointer math already accounts for the size of the object. – PaulProgrammer Jul 07 '15 at 04:29
  • @PrakharShukla yes , references must refer to something valid, that's why your code is wrong – M.M Jul 07 '15 at 04:32
  • @MattMcNabb Arrays are really funny looking pointers. You can `time_t * foo = malloc(sizeof(time_t) * 128)` and access elements as `foo[42]`, can you not? The first element could be accessed as `foo[0]` or `&foo` equally. – PaulProgrammer Jul 07 '15 at 04:35
  • @PaulProgrammer arrays are really not funny-looking pointers. For example arrays may be several gigabytes in size, but pointers are usually 4 or 8 bytes in size. I guess you could say that an elephant is a funny-looking ant! – M.M Jul 07 '15 at 04:37
  • I think you're talking about an array of pointers / references that refer to other large objects, rather than the array itself. Anyway, matters not. My crusty old ANSI C is probably not correct in C++ world anyway. – PaulProgrammer Jul 07 '15 at 04:39
  • You can use the pointer indexing operator to access an array , because you implicitly form a pointer to the array's first element and then index off that. In any case this is just a syntactical issue; e.g. the fact that you can use a hammer to break a window and to break an apple does not mean that a window is a funny-looking apple. I wasn't talking about an array of pointers. (There is no such thing as an array of references). – M.M Jul 07 '15 at 04:41
  • lol that is my HOME WORK question guys. Why can't we make a array of references. – Prakhar Shukla Jul 07 '15 at 04:47
  • @PrakharShukla the C++ standard says you cannot make an array of references. (Not related to this question though!) – M.M Jul 07 '15 at 04:47
0

Accessing array_demo[11] results in undefined behavior; anything can happen. Among those behaviors that fall in the category of "anything" is acting like nothing is wrong at all.

0

Looking at some of the comments, this kinda comes down to how much meaning different people try to put into the word "valid".

A pointer has a way to point at nothing: NULL. So you could say a NULL pointer is pointing to an "invalid" object or variable.

But a reference has no way to refer to nothing. So unless you go out of your way to violate other rules of the language that'll be a "valid" object or variable. So in simple conversation it would be easy to say that "a reference always points to a valid object" and mean that in comparison to pointers and NULL.

But if you do break the rules, then you can get dangling references or references to memory that shouldn't normally happen. It may still be "valid memory" in that it exists within the address space of the process but also not be any "valid" object or variable.

So is a bad reference valid or invalid? It depends on what exactly you're trying to say...

If you're getting hung up on that word, then take this way of rephrasing: A reference always refers to something.

And also remember that C++ doesn't have huge barriers to prevent you from breaking its rules. You can create weird and seemingly inconsistent situations through undefined behavior (such as accessing beyond the bounds of an array). The language won't and in many cases can't stop you from doing such things. You the developer have to ensure your logic is correct and/or use mechanisms built on top of the fundamental language to catch invalid situations (for example, vector::at).

TheUndeadFish
  • 8,058
  • 1
  • 23
  • 17
  • thanks you. yor answer clears many things for me. – Prakhar Shukla Jul 07 '15 at 04:52
  • There is a standard meaning for "valid" and "invalid" already. A null pointer is not invalid. An example of an invalid pointer would be a pointer that has been `delete`d. A valid reference may become invalid (dangling) if the memory it referred to gets deleted; and that doesn't break any language rules; but it must have been valid when it was bound. Techncially OP's code fails because of writing `array_demo[11]` ; it's moot whether he goes on to bind a reference to it. – M.M Jul 07 '15 at 04:56