Since all these ctype.h functions have the same format int func (int), you can take advantage of that to create a look-up table corresponding to all checks that need to be done. The advantage of a look-up table is that it's much easier to maintain than a fairly unreadable chain of &&.
First create a function typedef identical to the ctype functions: typedef int ctype_func_t (int);
Then make a struct to be used in the look-up table. Store string index, the true or false condition of the result, and the function itself:
typedef struct
{
  size_t         index;
  bool           cond;
  ctype_func_t*  check_func;
} check_t;
A look-up table can then be created as:
const check_t fmt_check [] =
{
  {0, true,  isupper },
  {1, false, isalpha },
  {2, false, isalpha },
  {1, false, isdigit },
  {2, false, isdigit }, 
  {3, true,  isdigit },
  {4, true,  isdigit },
  {5, true,  isdigit },
  {6, true,  isalpha },
  {7, true,  isalpha },
};
The order isn't important, add or remove format requirements as you please. The complete function for this would look like:
int ispwcorrect (const char pw[8])
{
  typedef int ctype_func_t (int);
  typedef struct
  {
    size_t         index;
    bool           cond;
    ctype_func_t*  check_func;
  } check_t;
  const check_t fmt_check [] =
  {
    {0, true,  isupper },
    {1, false, isalpha },
    {2, false, isalpha },
    {1, false, isdigit },
    {2, false, isdigit }, 
    {3, true,  isdigit },
    {4, true,  isdigit },
    {5, true,  isdigit },
    {6, true,  isalpha },
    {7, true,  isalpha },
  };
  
  for(size_t i=0; i<sizeof fmt_check/sizeof *fmt_check; i++)
  {
    unsigned char ch = pw[ fmt_check[i].index ];
    
    if((bool)fmt_check[i].check_func(ch) != fmt_check[i].cond)
    {
      return false;
    }
  }  
  return true;
}
This should be fairly self-explanatory, it calls ctype functions through a function pointer in a loop with a specific string index character as parameter. Then checks against a true/false condition. The check stops as soon as there is a mismatch.
The cast to bool after calling each ctype function is necessary, since they return zero or non-negative int. So comparing a bool against such a non-zero int won't work, since == will promote the bool parameter to an int.
This should vastly outperform regex, but will be slightly slower than the raw if-else.
Unrelated to your question, you also have a severe bug here: char pass[8];. There is no room for the null terminator, so you can't store "L$$222ee" inside pass.