Ti serve l'allocazione dinamica, altrimenti l'oggetto è perso appena esci dalla funzione.
Potresti modificare la stringa stessa di partenza
#include<stdio.h>
#include<ctype.h>
#define N 100
char *maiuscolo(char *stringa);
int main(){
char a[N], *b;
puts("Una frase o una parola: ");
fgets(a, N, stdin);
printf("\n");
b = maiuscolo(a);
printf("La nuova stringa: %s", b);
return 0;
}
char *maiuscolo(char *stringa){
for(int i=0; i<N; i++)
stringa[i] = toupper(stringa[i]);
return stringa;
}
Ma sarebbe una soluzione impropria e il return value sarebbe inutile.
Potresti usare variabili globali, ma sarebbe una soluzione impropria anche quella, perché faresti delle operazioni logicamente appartenenti a una funzione che in realtà stanno fuori