Where can I find weird C syntax rules?

I will take an exam and my teacher asks weird C syntax rules. Like:
<code>
int q=5;
for(q=-2;q=-5;q+=3) { //assignment in condition part??
printf("%d",q); //prints -5
break;
}

Or

int d[][3][2]={4,5,6,7,8,9,10,11,12,13,14,15,16};
int i=-1;
int j;
j=d[i++][++i][++i];
printf("%d",j); //prints 4?? why j=d[0][0][0] ?

Or

extern int a;
int main(){
do{
do{
printf("%o",a); //prints 12
}while(!1);
}while(0);
return 0;
}
int a=10;

<code/>
I could not find it rules any site or book. Really absurd and uncommon. Where can I find?
Your teacher comes up with idiotic examples. The first would be a coding error in real life. The second is TOTALLY UNDEFINED AND MEANINGLESS! (Your teacher does not understand the finer points of the language.) The third is as moronic as the first. You teacher is basically just lazy and ill-informed.
assignments return the value assigned as a boolean. eg x =3 returns 3 which is true. x = 0 returns 0 which is false. 0 is false, else true in C. This may even be undefined and something all compilers do the same way (see below). I dunno, I know what it does in my compilers and I wouldn't ever do it anyway (this is usually a mistake where you meant ==, and when it compiles and runs, this is what it does).

The others are not worth the time to unravel.

I agree with TPB.
If your teacher insists on asking things like this, drop the class if possible.
if you have a compiler handy, drop the code in and let the computer tell you what it did.

if you have to unravel it, you are going to need to be able to know all the many, many edge cases of undefined behaviors... and I doubt I know 10-20% of those (!!!). There are a LOT of them. To get *those* you need to study the language standard definition documents, which are massive and difficult reading. As noted, a couple of these examples (trusting TPB here) are not legal.

The trouble with undefined behavior is that almost all compilers support certain illegal things. My favorite example is the union... you can use a union to serialize anything and every compiler I have ever seen allows you to union a char array with something else to accomplish this. But it isnt legal: you can only access a union one way per variable. Something I did for 2 decades was technically undefined behavior but well defined in all compilers!



Last edited on
You are right. I studied hard but I couldn't. Do you know any site or book that mentions specific and detailed syntax rules?
There are no "syntax rules" for the second example It is UNDEFINED. It is an illegal construct. It is garbage. It has no definite value. Different compilers may give different results since the language specification itself does not define what to do in such idiotic circumstances. You are not allowed to modify the same variable more than once between sequence points. You can't even use a variable that you modified within the same sequence point. So even this is illegal and ultimately meaningless:
 
a[i] = i++;


Last edited on
if you want the details you need to get the standard. Just google c++ standard. Or C, if you wanted C (Unclear). Someone probably has a reference book you could get, but I don't know of one. I just use the web, but I know what I am looking for and thankfully modern compilers warn about MOST of the undefined/idiotic code (even when it works) so in PRACTICE you can just fix your code or research a warning when you accidentally hit one.

another one to look at is the 'vexing parse' which is not exactly a syntax rule but something to watch out for. basically sometimes angle brackets <> can scramble a compiler (usually, it just won't compile, once in a while, you may be able to force it to compile and misbehave, I forget, its another thing you don't see too often and adding a space fixes it).
BeginnerP wrote:
Do you know any site or book that mentions specific and detailed syntax rules?

cppreference.com, despite the name, has a C language reference (in addition to the C++ language reference)

BeginnerP wrote:
for(q=-2;q=-5;q+=3) { //assignment in condition part??

see https://en.cppreference.com/w/c/language/for - any expression can be used there, as long as it has a result that can be compared with zero (the result of q=-5 is -5)

BeginnerP wrote:
1
2
j=d[i++][++i][++i]; 
printf("%d",j); //prints 4?? why j=d[0][0][0] ? 


It doesn't. An attempt to increment the same variable twice with no sequencing renders the entire program totally meaningless. That "4" is random garbage.
See http://en.cppreference.com/w/c/language/eval_order and turn up your compiler warnings:

gcc: https://wandbox.org/permlink/d5Re1PMoQkxGecfo
prog.c: In function 'main':
prog.c:7:11: warning: operation on 'i' may be undefined [-Wsequence-point]
  j=d[i++][++i][++i];
           ^~~
prog.c:7:11: warning: operation on 'i' may be undefined [-Wsequence-point]

clang: https://wandbox.org/permlink/4Bk6lt2SPa9tYKfY
rog.c:7:7: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
 j=d[i++][++i][++i]; 
      ^   ~~
1 warning generated.

(note how garbage output the two demos above happened to print was different: 4 for gcc, -1178831928 for clang. They are both correct)

BeginnerP wrote:
printf("%o",a); //prints 12

for %o see http://en.cppreference.com/w/c/io/fprintf
for the meaning of extern int a; and int a = 10;, see http://en.cppreference.com/w/c/language/extern
for do-while see http://en.cppreference.com/w/c/language/do

Last edited on
Sounds dreadful. I personally would very much dislike your teacher.

1
2
3
4
5
int q=5; 
for (q=-2; q=-5; q+=3) { //assignment in condition part?? 
    printf("%d",q); //prints -5 
    break;
}


A for loop works like this:
for (initialization; condition; iteration) { }
First, the initialization happens. Then, the condition is checked. If the condition evaluates to false, the inside of the loop is not entered. Otherwise, the inside of the loop is entered.
In your example, your initialization set q to be -2, but then your condition sets q to be -5. Any non-zero value in C or C++ is evaluated to be true. So you're loop is entered with q being -5.

1
2
3
4
5
int d[][3][2]={4,5,6,7,8,9,10,11,12,13,14,15,16}; 
int i=-1; 
int j; 
j=d[i++][++i][++i]; 
printf("%d",j); //prints 4?? why j=d[0][0][0] ? 

First, look at something simpler.

int d[3] = {1};
This will make an array initialized with the first element being 1, and the 2nd and last element being 0.
int d[] = {3, 4};
This will make an array of size 2, with the elements in it being initialized to 3 and 4.

int d[2][2] = {1, 2, 3, 4};
Is valid, and equivalent to doing int d[2][2] = { {1, 2}, {3, 4} };

When you don't give the size of the outer-most array, the size of the array will become the minimum possible to hold the values that you supply it with in the initialization.

In your example, let's look at the initialization of the array. The outer-most dimension of the array is not given, but the inner-two dimensions are 3 and 2. This means that the total size of the array will be a multiple of 6, and this also means that the outer-most dimension's size will be the number of elements you initialized it with, divided by (3*2).

{4,5,6,7,8,9,10,11,12,13,14,15,16} becomes equivalent to
1
2
3
{ { {4,5},  {6,7},    {8,9}  },
  { {10,11},{12,13}, {14,15} },
  { {16,0},  {0,0} ,   {0,0} } };


j=d[i++][++i][++i];
This, simply put, is undefined behavior. You are trying to increment i three times within one sequence point. There's no point trying to make sense of this part of the code, because you simply have undefined behavior. It's not clever, it's just wrong. In general, avoid ever using i++ at the same time as you reference i in a different place on the same line.

It sounds like you want more examples beyond what you were given. I don't know the scope of your exam, but function pointers have one hell of a messy syntax if you want to look into that.
https://www.geeksforgeeks.org/function-pointer-in-c/


Last edited on
Topic archived. No new replies allowed.