To round a float in C, there are 3 <math.h> functions to meet the need.  Recommend rintf().
float nearbyintf(float x);
The nearbyint functions round their argument to an integer value in floating-point format, using the current rounding direction and without raising the ‘‘inexact’’ floating point exception. C11dr §7.12.9.3 2
or
float rintf(float x);
The rint functions differ from the nearbyint functions (7.12.9.3) only in that the rint functions may raise the ‘‘inexact’’ floating-point exception if the result differs in value from the argument.  C11dr §7.12.9.4 2
or
float roundf(float x);
The round functions round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction. C11dr §7.12.9.6 2
Example
#include <fenv.h>
#include <math.h>
#include <stdio.h>
void rtest(const char *fname, double (*f)(double x), double x) {
  printf("Clear inexact flag       :%s\n", feclearexcept(FE_INEXACT) ? "Fail" : "Success");
  printf("Set round to nearest mode:%s\n", fesetround(FE_TONEAREST)  ? "Fail" : "Success");
  double y = (*f)(x);
  printf("%s(%f) -->  %f\n", fname,x,y);
  printf("Inexact flag             :%s\n", fetestexcept(FE_INEXACT) ? "Inexact" : "Exact");
  puts("");
}
int main(void) {
  double x = 8.5;
  rtest("nearbyint", nearbyint, x);
  rtest("rint", rint, x);
  rtest("round", round, x);
  return 0;
}
Output
Clear inexact flag       :Success
Set round to nearest mode:Success
nearbyint(8.500000) -->  8.000000
Inexact flag             :Exact
Clear inexact flag       :Success
Set round to nearest mode:Success
rint(8.500000) -->  8.000000
Inexact flag             :Inexact
Clear inexact flag       :Success
Set round to nearest mode:Success
round(8.500000) -->  9.000000
Inexact flag             :Exact
What is weak about OP's code?
(int)(num < 0 ? (num - 0.5) : (num + 0.5))
- Should - numhave a value not near the- intrange, the cast- (int)results in undefined behavior.
 
- When - num +/- 0.5results in an inexact answer.  This is unlikely here as- 0.5is a- doublecausing the addition to occur at a higher precision than- float.  When- numand- 0.5have the same precision, adding- 0.5to a number may result in numerical rounded answer.  (This is not the whole number rounding of OP's post.) Example: the number just less than 0.5 should round to 0 per OP's goal, yet- num + 0.5results in an exact answer between 1.0 and the smallest- doublejust less than 1.0.  Since the exact answer is not representable, that sum rounds, typically to 1.0 leading to an incorrect answer.  A similar situation occurs with large numbers.
 
OP's dilemma about "The above line always prints the value as 4 even when float num =4.9." is not explainable as stated.  Additional code/information is needed.  I suspect OP may have used int num = 4.9;.
// avoid all library calls
// Relies on UINTMAX_MAX >= FLT_MAX_CONTINUOUS_INTEGER - 1
float my_roundf(float x) {
  // Test for large values of x 
  // All of the x values are whole numbers and need no rounding
  #define FLT_MAX_CONTINUOUS_INTEGER  (FLT_RADIX/FLT_EPSILON)
  if (x >= FLT_MAX_CONTINUOUS_INTEGER) return x;
  if (x <= -FLT_MAX_CONTINUOUS_INTEGER) return x;
  // Positive numbers
  // Important: _no_ precision lost in the subtraction
  // This is the key improvement over OP's method
  if (x > 0) {
    float floor_x = (float)(uintmax_t) x;
    if (x - floor_x >= 0.5) floor_x += 1.0f;
    return floor_x;
  }
  if (x < 0) return -my_roundf(-x);
  return x; //  x is 0.0, -0.0 or NaN
}
Tested little - will do so later when I have time.