It would be far easier to understand if you just rewrote the conditional not using as many logical nots.
e.g.
Code:
if (!(i == d - 1 && j == d - 1)) {}
you can then use DeMorgan's rules to rearrange it to your liking.
Anyway, looking at your expression you have if (i != d -1 && j != d -1). Now look at j != d - 1. This is going to be false at the end of every "row" making the whole conditional false at the end of every row. This is obviously not your intention.
Edit: Walk away from computer to get a drink without pressing submit and all of a sudden there are 2 answers before mine already
Edit 2: To @jjwooyoung Thank you for posting such a small snippet, it's always helpful. Even more helpful is if you reduce the small snippet to code that can be compiled and executed as below (note, that this is the corrected version. Also I used c89 and not for no particular reason... in hindsight I shouldn't have done that).
Code:
#include <stdio.h>
int main(void)
{
int i, j;
int d = 4;
int n = 0;
for(i = 0; i < d; i++) {
for(j = 0; j < d; j++) {
if (i != d - 1 || j != d - 1) {
printf("%2i ", n);
}
n++;
}
printf("\n");
}
return 0;
}