Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
120 views
in Technique[技术] by (71.8m points)

c - Why does a 2D array get changed on copying one of its rows to a previously undefined location?

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("
");
    }
    printf("NExt
");

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

to be

00  
34  

12  
34  

Thanks in advance

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...