You check for primes by trying to divide with every number from sqrt(i) to 2. After that you check if you found any divisors (if !f() ) and if you didn't, you print the number.
The first thing is, you don't have to check for more divisors after you find one. As soon as i%j = 0, you can break the loop, like so: if(i%j==0) { f++; break;}. No matter what happens after you find that i%j=0, you will not print the prime, so you can stop searching.
The point about starting from 2 instead of sqrt(i). Every second number is even, i.e. divisible by two. So half of the time, when starting from 2, the loop would only do 1 operation ( i%2 == 0), and it's even, so it finds a divisor and stops). Then, if it isn't even, there is a 1/2 chance it is divisible by 3. So around two thirds of the time, a number is found to be not prime after 2 operations. However if you start from sqrt(i), there are very few divisors, so you often do thousands of operations until you get to a j so (i%j==0). With that in mind, doing the loop for(j=2;j<=sqrt(i);j++ ) is significantly faster than for(j=sqrt(i);j>1;j--).
Take 1,000,000,000 for example. If you go from 2, you find that 10^9 % 2 = 0, and you can stop. However if going from the square root, you have to go until 25,000 (from sqare root ~ 32,000), so 7000 operations, until you find that 10^9 % 25000 = 0.