3

If arrays in C are fixed in size, then how come this code is working properly? This code works but my teacher said I did it in a wrong way...

int main()
{
    int n,element,i;
    printf("Enter the size of Array : ");
    scanf("%d",&n);
    int a[n];

    for(i=0;i<n;i++){
        printf("Enter  %d no element : ",i+1);
        scanf("%d",&a[i]);
    }

    printf("Enter the new element to be inserted at the End: ");
    scanf("%d",&element);

    n=n+1;
    a[n-1]=element;

    for(i=0;i<n;i++){
        printf("%d\t",a[i]);
    }
}
klutt
  • 30,332
  • 17
  • 55
  • 95
  • But the array `a` *is* fixed in size, it's size will always be the number of elements you initially input for `n`, before you modified `n`. And we can't help you "fix" it if we don't know what's wrong with it. Perhaps you should ask your teacher for clarifications? Also know that C doesn't have any bounds-checking what so ever, if you go out of bounds of an array then you will have *undefined behavior* – Some programmer dude Jul 08 '19 at 06:19
  • 9
    Your teacher's right. The code has undefined behaviour since, after the array is created, the code writes past the end of it. You just happen to be getting lucky - or unlucky - if it seems to work for you. It is not guaranteed to work correctly (however you define "correctly") and could pass your testing today and fail tomorrow. – Peter Jul 08 '19 at 06:20
  • What happens if you set `i` to something different than `element` just before and output `i` right after `a[n-1]=element;` ? – Yunnosch Jul 08 '19 at 06:23
  • 4
    You got (un)lucky that the program didn't crash when you added one element. Add a dozen elements and your program is more likely to crash. – Jonathan Leffler Jul 08 '19 at 06:27
  • Why did you get (un)lucky? Say you entered `5` for `n`. A compiler is free to reserve some minimum storage size consistent with the alignment to be maintained at that time. So the compiler may very well have reserved `8, 16, 32, ...` total elements for the array, but you cannot validly use more than `5`. There is no guarantee that the compiler, with the next request for storage, won't assign the address of `&a[6]` for use in this case. So bottom line, by writing beyond the bounds of your array, you invoke *Undefined Behavior* and the defined execution of your code is over at that point. – David C. Rankin Jul 08 '19 at 06:44

3 Answers3

5

It does not work. At least not reliably. This is undefined behavior since you're accessing memory outside the array. If you don't go very far outside the array it often work, but it is very dangerous to do like that and the way you are handling it is not acceptable under any circumstances.

If you need to change the size, then use dynamic allocation like this:

int *a = malloc(n*sizeof(*a));
if (!a) { /* Handle error */ }

and then:

n=n+1;
// Using a void pointer, because this pointer should not be used for 
// dereferencing
void *tmp = realloc(a, n*sizeof(*a));
if (!tmp) { /* Handle error */ }
a = tmp;

Actually, I would prefer dynamic allocation instead of using VLA:s any day. Just the fact that they removed the requirement for compilers to support them in moderrn C standards is a good indication that it is a bad idea to use them. And since the support for them is not mandatory anymore, using them MAY break your code in the future.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • The fact that they removed the requirement for compilers to support them in moderrn C standards is a good indication of the politics in the standardization process – M.M Jul 08 '19 at 07:22
  • @M.M Well, maybe, but the fact that it is impossible to check for errors is a major drawback. – klutt Jul 08 '19 at 07:26
  • You can't check for errors in `int a[1000000];` either; and you can do some user validation of `n` before the array definition – M.M Jul 08 '19 at 07:28
  • @M.M True, but you would never write `int a[1000000];` if you have any knowledge about stacks. Besides, if you need to check available stack space, you're probably wrong in the first place. – klutt Jul 08 '19 at 07:38
  • What errors do you hope to check for in `int a[n];` then? – M.M Jul 08 '19 at 07:48
  • @M.M Don't get me wrong. I think this discussion is very interesting but I think this is the wrong place to have it. It's too broad to be discussed in comments. I rephrased the sentence a bit. – klutt Jul 08 '19 at 07:53
0

what if I want to free the assigned memory location to the last variable you have injected.

1 - will it be freed?

On a smaller level, it will work for you, think in a broader perspective where you have to use every single bit carefully it's not a good practice(think in this perspective). Instead of this will suggest you use dynamic memory allocation will improve your code quality.

dragon
  • 132
  • 6
  • 1
    This answer is really unclear. The question does not ask anything about freeing memory, for starters. Also nothing is "injected" anywhere here (in the usual meaning of for "injecting" in programming context). – hyde Jul 08 '19 at 07:38
  • 1
    @hyde answer to this question is already explained well in previous answers, and i think the above explanation is enough to understand the problem and solution. what I am here to explain this in another way in the context of memory utilization and developer who asked this query is still in learning phase so we need to guide him to have a better coding practice. – dragon Jul 10 '19 at 05:09
0

On the High Speed Rail you buy a ticket,and very lucky there is another empty site beside you,then you place your bag on it.It does not mean you own that site,just because does not have another one own the site now.

In fact to program,you does not declare you own this memory,you can fix it and do everything its ok until some program declare own the memory.Just like another own the High Speed Rail ticket guys stand beside you and show his ticket.

int a[n];//mean you own n size of int so you  own a[0]~a[n-1] this n mean in this line your n value,if next line n increase a's size will not increase
//------------------------------------------------------------
//Not legal because n is not const
int a[n];
//------------------------------------------------------------
//In fact this is legal
int *a;
a=(int*)malloc(sizeof(int)*n);//will alloc n of int for you
    //Do something you want
    //
free(a);//release your memory alloc
//------------------------------------------------------------
//Or just give a big enough for a like
int a[1000];
//------------------------------------------------------------
J CHEN
  • 494
  • 3
  • 9