0

I want to initialize an 16-cel-long array with 0, 1, 2 and 3 by blocks of four cels. So here is my first attempt at this:

int main(void) {
int t[16];
int i;
for (i = 0; i<=15; t[i++]=i/4)
{
    printf("%d \n", t[i]);
}

return 0;
}

However, here is what I get. I know I can do it differently by just getting the affectation into the for loop, but why does this not work?

EDIT: Please do note that the printf only serves to check what the loop did put in the array.

  • 1
    That is an unnecessarily cryptic way of initializing an array. I was about to type "because you're not initializing anything, you're printing uninitialized values"... and then I looked at your post loop expression. I am relatively experienced in C. If you confused me for even a second with what should be trivial code, something is wrong. – Ed S. Feb 04 '15 at 23:00
  • the code is (incorrectly) using a 'side effect' regarding the value of 'i'. In general, side effects should not be used in controlling variables. And the printf will be executed before the third parameter of the for loop is executed. – user3629249 Feb 04 '15 at 23:18

5 Answers5

5

The initialization works fine; you're just printing the cell before initializing it. Remember that the loop increment is done after each iteration. If you unroll the loop, you have:

i = 0;          /* i is now 0  */
print(t[i]);    /* prints t[0] */
t[i++] = i/4;   /* sets t[0]   */
                /* i is now 1  */
print(t[i]);    /* prints t[1] */
t[i++] = i/4;   /* sets t[1]   */
                /* i is now 2  */
print(t[i]);    /* prints t[1] */
/* etc. */
user1686
  • 13,155
  • 2
  • 35
  • 54
2

I do not understand what you are trying to accomplish, but please let me show you a similar piece of code, first.

int main(void) {
int t[16];
int i;
//edited the code; providing standard way to do the task
for (i = 0; i<=15; i++)
{
    t[i]=i/4;
    printf("%d \n", t[i]);
}

return 0;
}

EDIT:

The while loop should be written that way:

int i = 0;
while (i<=15){
    t[i] = i%4;
    i++;
}

Which means set t[i] equal to i%4 and then increment i.

Since you are a beginner, I've updated the for loop and it now provides a standard way to do your task. It's better to have a simple increment on the third for loop command; do the rest of the job inside the for loop, as described above.

codingEnthusiast
  • 3,800
  • 2
  • 25
  • 37
  • Have you tested it? I have, and it works as expected. – codingEnthusiast Feb 04 '15 at 23:43
  • In the `while` version you can't have `i++` and `i%4` within the same expression like that either (sorry, I should have picked up on this earlier); the loop body will have to be `{ t[i] = i%4; ++i; }`. – M.M Feb 05 '15 at 00:34
2

As well as the off-by-one errors with the loop begin/end that have been mentioned in other posts, this code:

t[i++]=i/4

causes undefined behaviour because i is read and written without a sequence point. "Undefined behaviour" means anything can happen: the value could be 3, or 4, or anything else, or the program could crash, etc.

See this thread for more in-depth discussion, and welcome to C..:)

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
1

@naltipar: Yeah, I just forgot to initialize the first cel, just like grawity pointed out. Actually, the version I wrote for myself was with i++ but even then, since the third expression is executed after each loop, it sent out the same result. But whatever, it is fixed now.

However, I've got another problem which I'm sure I'm missing on but still can't figure it out:

int i = 0;
while (i<=15)
    t[++i] = i%4;

This was first:

for(i = 0; i<=15; t[++i] = i%4);

but it resulted with an infinite loop. So in order to make sure that's not a problem specific to for, I switched to while andthe same thing still happens. That being said, it doesn't occur if i replace ++i by i++. I unrolled the whole loop and everything seems just fine...

I'm a beginner, by the way, in case you were wondering.

WIlopu
  • 47
  • 7
  • this is how that line: 'for(i = 0; i<=15; t[++i] = i%4);' should be written: 'for(i = 0; i<=15; i++) {t[i] = i%4);}' In other words, do not mix the actual code with the loop control – user3629249 Feb 04 '15 at 23:21
  • Huh, yes. But it doesn't hurt to know where that behavior stems from. In my opinion, the incrementation operands don't work in the "for" statement's control instructions the same way they do elsewhere, because when I also do this 'for (i = 0; i<=15; t[i++]=i/4);' my 16-cel-long array's last value ends up being 4, when the loop is supposed to stop at 15. So in theory, it should be t[15] = 3, then i = i+1=16. – WIlopu Feb 04 '15 at 23:30
  • You access out of bounds of the array on the last iteration (when `i` is `15`, `++i` takes it to `16` and then you write to `t[16]`). This causes undefined behaviour. The incrementation operators do work the same in the control instructions as they do elsewhere; if your loop does not have any `break` or `continue` statements then `for(a;b;c) d;` is the same as `a; while(b) { d; c; }` – M.M Feb 04 '15 at 23:52
  • Is "Wllopu" the same as the person asking the question? – M.M Feb 04 '15 at 23:53
  • Yes. I had to create an account to post on SO. And since I'll probably make a big use of it eventually, so why not. Thanks, anyway. But what about this case? 'for (i = 0; i<=15; t[i++]=i/4);' in my 16-cel-long array whose last value ends up being 4, when the loop is supposed to stop at 15. So in theory, it should be t[15] = 3, then i = i+1=16 – WIlopu Feb 05 '15 at 00:17
  • @WIlopu lol can't believe nobody picked up on that yet (including myself), will post answer – M.M Feb 05 '15 at 00:30
0

A clearer way to write this would be much less error-prone:

for (i = 0; i < 16; ++i)
  printf ("%d\n", (t[i] = i % 4));

Personally I'd code something that way, but I'd never recommend it. Moreover, I don't really see much benefit in condensing statements like that, especially in the most important category: execution time. It is perhaps more difficult to optimize, so performance could actually degrade when compared to simply using:

for (i = 0; i < 16; ++i)
  {
    t[i] = i % 4;
    printf ("%d\n", t[i]);
  }

Even if it is you reading your own code, you make it difficult for your future self to understand. KISS (Keep It Simple, Stupid), and you'll find code is easier to write now and just as easy to modify later if you need to.