0

My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?

Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.

int i,j,n,matrica[i][j],suma=0; srand(time(NULL)); printf("\nunesi prirodan broj N[3,20] = \n"); scanf("%d",&n); for(i=0;i<n;i++) { for(j=0;j<n;j++) { matrica[i][j]=rand()%100; printf("%d, %d = %4d ",i, j, matrica[i][j]); if(j==n-1) { printf("\n"); } } } printf("\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d, %d = %4d ", i, j, matrica[i][j]); if(j==n-1) { printf("\n"); } } } 

And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):

enter image description here

17
  • 10
    Two things: First of all C++ doesn't really have variable-length arrays, though some compilers add it as an extension of the language. Secondly, uninitialized variables really are uninitialized. Their value will be indeterminate and using them before explicit initialization leads to undefined behavior in C++. Now think about how and when the variables i and j will be used and when they are initialized... Commented Jan 2, 2018 at 8:34
  • 2
    if(j==n-1) { printf("\n"); } - Why not just put this after the for loop and remove the condition? Commented Jan 2, 2018 at 8:36
  • 1
    @Someprogrammerdude - It is tagged C, but your comment does apply Commented Jan 2, 2018 at 8:40
  • 4
    You have int i,j,n,matrica[i][j],…; what is the value of i when matrica is defined? You have no clue; I have no clue; no-one has a clue; the value of i is undefined and could be anything. Ditto j. You have to defer the allocation of matrica until you know how big it needs to be. This is just expanding on what @Someprogrammerdude said. You might use int matrica[n][n]; after the scanf() — and after checking that the scanf() succeeded and entered a number that's bigger than zero and not too big (for an ill-defined 'too big'; 64 or 100 might be suitable checks). Commented Jan 2, 2018 at 8:43
  • 2
    Since this seems to be C99 which supports VLAs, matrica[i][j] is allocated statically using whatever values i and j have at that moment (and they are undefined). It's possible the compiler just doesn't allocate anything. But it most certainly doesn't get resized when you assign values to it, there isn't such thing in C. Commented Jan 2, 2018 at 9:17

2 Answers 2

3

We need to use malloc to allocate the dynamic amount of memory.

After

 scanf("%d",&n) // PS You should check the return value - read the manual page 

Put

 matrica = malloc(sizeof(int) * n * n); 

And declare it as

int *matrica; 

Then replace

matrica[i][j] 

with

matrica[i * n + j] 

And after you have finished with matrica - use free i.e.

free(matrica); 
Sign up to request clarification or add additional context in comments.

2 Comments

Using malloc() is one option; it is not the only option. See also my comment
@JonathanLeffler - I concur
1
int i,j,n,matrica[i][j] 

At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.

Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...

I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:

#include <stdint.h> #include <stdio.h> #include <stdlib.h> int main(void) { size_t n; printf("Enter n, please: "); fflush(stdout); if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) { puts("Invalid input or arithmetic overflow..."); return -1; } int (*array)[n] = malloc(n * sizeof *array); if (!array) { puts("Allocation error..."); return -1; } /* now you can use array[0..(n-1)][0..(n-1)] as you might expect */ free(array); } 

This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...

... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.

4 Comments

As I said in my question, this is my cousin's high school project. They don't follow any textbook but instead have a subpar teacher that would have a third nested loop just to print out a newline character as I said in one of the comments. Me myself don't use C++ at all, and I focused on maybe finding an error like missing semicolon, wrongly opened/closed code block, or misspelled "i" or "j" somewhere in the loops or something like that and I completely overlooked the initialisation error.
@MarioPlantosar I've written some code to get you started (see the update in the answer). I can't guarantee that it'll work, but from a quick scan, seems like it should be good to go... Compile using -std=c99 or -std=c11 (preferably -std=c99 due to the VLA reliance) flag. Debug using valgrind, if you've never heard of it now is a good time to learn. It'll take five minutes, and one day save you two hours (at least, likely more).
@chux Thanks for the minor style tips. I look forward to the day when StackOverflow is so awash with noise and contrary stylistic arguments that you can't get anything else from it...
@chux Actually, you know, it all looks hideous... What do you think of my last paragraph? Did you read that part? Yeh... I could allocate memory, but can you tell me why I should do that when I could instead reseed my PRNG with the same time_t value as before, and iterate the same number of times, calling rand to generate the same sequence of values? Less memory usage, right? As a result, less manual optimisation necessary due to cache misses, register use, etc... Less failure modes... right? Less boilerplate... so why are we even talking about allocation?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.