Checking day number in a year
The compiler warns you

The gcc compiler doubles as a code analysis tool. Running on your code it found the following potential problems:

year.c:4:1: warning: return type defaults to ‘int’
 valid(int day, int month, int year)
 ^
year.c: In function ‘main’:
year.c:26:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &amp;day);
     ^
year.c:27:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &amp;month);
     ^
year.c:28:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &amp;year);
     ^


The last 3 warnings are no big deal in a toy like this, but the first is important: you forgot saying that the functions returns an int, greatly confusing the future reader of your code as he may not know by heart that unspecified return type defaults to int.

The (not)-boolean return antipattern

    if(day &lt; 1 ||  day &gt; st[month-1] || month &lt; 1 || month &gt; 12 || year &lt; 0)
        return 0;
    else
    return 1;


Means that if day &lt; 1 ||  day &gt; st[month-1] || month &lt; 1 || month &gt; 12 || year &lt; 0 is true you return 0 (false) otherwise (if it is false) you return true.


expression_value = true -> return_value = false
expression_value = false -> return_value = true


Just return the negation: !

return ! (day &lt; 1 ||  day &gt; st[month-1] || month &lt; 1 || month &gt; 12 || year &lt; 0);


The same in general applies when there is no negation, booleans shall be returned direclty, not after an if - else

Use a negative check to reduce nesting

If a pre-condition is not met, just abort early:

if(! valid(day, month, year)) {
    puts("\nInvalid date\n");
    return 1; // non-zero return code signals error.
}


puts

printf has a lot of power, when dealing with simple strings puts is preferred (see the example above).