-1

Look at the following code Sample where i have deliberately copied a[2] to p[2] which does not exist (only p[1] and p[0] exist) This should i guess have no effect on array a .

But when i print array a referenced by 'r' the output is as follows

00  
34  

-133280  
34  

if i either remove completely

p[2]=a[2]   

or correct both statements

i.e

p[0]=a[0]  
p[1]=a[1]

then the error vanishes and i obtain the expected output

Here is the code for Scrutiny

 int a[2][2]={{1,2},{3,4}};
    int * p[2];
    int (*r)[2];
    p[1]=a[1];
    p[2]=a[2]
    r=a;

i expect the output of

 for(i=0;i<2;i++)
    {
    for(j=0;j<2;j++)
      printf("%d",p[i][j]);
      printf("\n");
    }
    printf("NExt\n");

    for(i=0;i<2;i++)
    {
     for(j=0;j<2;j++)
      printf("%d",r[i][j]);
      printf("\n");
     }

to be

00  
34  

12  
34  

Thanks in advance

  • Welcome to the world of Undefined Behavior! – Paul Ogilvie Aug 18 '19 at 11:11
  • *"i have deliberately copied a[2] to p[2] which does not exist"* - You've invoked *undefined behavior*. The words "I expect..." are wishful thinking at-best afterward. – WhozCraig Aug 18 '19 at 11:12
  • The only chance of turning this into an answerable question would be to describe what you are trying to achieve. Because intentionally breaking the rules which serve to make your code predicatable and then asking people to predict is not helpful. If your goal is to "predict the unpredicatable" then just stop. Otherwise explain what your goal is. – Yunnosch Aug 18 '19 at 12:00
  • the above program was just a result of an error but i wished to understand why array a got modified.I get it now its undefined behaviour – Zorman Tasky Aug 18 '19 at 12:34

1 Answers1

0

First of all, why did you expect the result of printing p to be

00
34

There are exceptions, but uninitialized memory is not guaranteed to start out containing 0. And more than that, random pointers (which is what p[0] is in your case) are most especially not guaranteed to point to memory containing 0! The result I would have expected would be

meaningless pseudo-random numbers
34

Secondly, when you write to memory you don't own, as in

p[2] = a[2];

this is a really bad thing to do, and almost anything can happen.

Here are two things that do not happen:

  1. The compiler detects that you are writing to memory you don't own, and gives you an error message.

  2. The compiler detects that you are writing to memory you don't own, and makes sure that nothing gets written anywhere.

No, what usually happens is that

  1. An attempt is made to write to the memory you don't own, with arbitrarily bad results.

You said, "This should I guess have no effect on array a." I'm not sure why you guessed that. What we have is two facts:

(a) The program is writing to some part of memory outside of array p. We don't know where it's actually writing; it could be almost anywhere.

(b) Array a is getting mysteriously written to.

Given these two facts, can you make a guess about where the bad write might actually be writing?

See also this answer to an unrelated question, and especially the paragraph that talks about "If there is memory and we do have permission and it's not being used for anything else, the program might seem to work -- for now".


Addendum: In a comment, you asked "but on successive compilations shouldn't the memory being overwritten be different". There are two ways of answering this question.

  1. As a C programmer (actually as any kind of programmer), it is extremely important to understand that when you engage in undefined behavior, anything can happen. Let me repeat that: anything can happen. Let me repeat that again: anything can happen! The results do not have to be reasonable. They do not have to make sense. They do not have to be limited to the things you might have expected to have gone wrong. They do not have to vary from run to run, if you thought they would be random. They do not have to stay the same from run to run, if you though they would be consistent. You just can't make any predictions, at all, about what might or might not happen. The best solution -- the only solution -- is to not engage in undefined behavior in the first place.

  2. Sometimes the results of undefined behavior are surprising. (Almost nothing surprises me any more, but sometimes some programmers are surprised.) Given enough knowledge about the compiler and the target architecture, given enough time and effort, one can usually come up with a satisfying explanation of why a particular result was observed. But since I don't know anything about your compiler and target architecture, and since (I'm sorry) I'm almost out of time for this answer, I'm not going to speculate abut why (in this case) they results weren't different as you expected.

I will close with my favorite analogy, although it works better when what you've just asked is why the results on successive runs were not the same, as you expected:

Yesterday I was working on my car. I took off the front wheel to work on the brakes, and when I put the wheel back on, I forgot to fasten the lugnuts. I went for a drive, and at 60 mph, the front wheel flew off, and the car veered to the side, and I crashed into the ditch at the side of the road.

Today when I went to repair the damage, I had to take the front wheel off again. When I put it back on, I forgot to fasten the lugnuts again. But this time, when I went for a drive and the front wheel flew off, the car veered to the other side, and I crashed head-on into a semi.

Why did I get different results? I expected them to be the same.

Now, this may seem like a ridiculous analogy, but really, to me and any experienced C programmer, this is just about exactly how ridiculous it sounds when someone asks why a program, after engaging in undefined behavior, either did or didn't generate predictable results. Yes, computers and computer programs are generally deterministic devices, but as I said before, when you engage in undefined behavior, anything can happen.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103