0

I am trying to write a function that is given a string of text (which is to be a shell command) and now I just need to extract words, so delete spaces and save each word in a pointer to pointer to char. My idea was to do it this way, but gcc compilers gives back a warning that "return from incompatible pointer type"

Code:

char **getargs(char *command)
{                                                                                                  
  static char arguments[MAXARG][CMDLENGTH];                                                      
  int i = 0, word = 0, letter = 0, status = OUT;                                                 
                                                                                                 
  while(command[i] != '\0')                                                                      
  {                                                                                              
      if(isspace(command[i]) && status == IN)                                                    
      {                                                                                          
          arguments[word][letter] = '\0';                                                        
          letter = 0;                                                                            
          word++;                                                                                
          status = OUT;                                                                          
          i++;                                                                                   
      }                                                                                          
      else if(!isspace(command[i]) && status == OUT)                                             
      {                                                                                          
          arguments[word][letter] = command[i];
          status = IN;
          letter++;
          i++;
      }
      else if(!isspace(command[i] && status == IN))
      {
          arguments[word][letter] = command[i];
          letter++;
          i++;
      }
      else if(isspace(command[i]) && status == OUT)
          i++;
  }

  return arguments;                                                                              
  }

EDIT: Additionally, I have also figured out that in order to return a pointer that was declared locally it needs to be declared as static, why is that?

joe_chip
  • 2,468
  • 1
  • 12
  • 23
Damian Kowalski
  • 362
  • 2
  • 8
  • "I have also figured out that in order to return a pointer that was declared locally it needs to be declared as static, why is that?" -->Incorrect premise. That is one way, but it does not need to be that way. Code could allocate, the caller could pass in data places to save, global memory, could modify `char *command`, ... – chux - Reinstate Monica Dec 27 '20 at 22:30
  • 2
    You should dynamically allocate `arguments` https://stackoverflow.com/questions/11656532/returning-an-array-using-c#:~:text=You%20can't%20return%20arrays,%5D)%3B%20%2F%2Fis%20this%20correct%3F%20%7D – anotherOne Dec 27 '20 at 22:31

1 Answers1

0

Your function signature promises to return a char **, a pointer to pointer to char. That means if the returned value is r, then *r will have to be a pointer to some character(s) you have put somewhere. The calling function could define a char-pointer cp = *r, and then *cp would be the first character, and printf(cp); would print the first word your function found.

But this is not what you're actually returning: you're not returning a pointer to a pointer, and that is why the compiler warns.

What you are returning is a two-dimensional array - that is, MAXARG*CMDLENGTH chars, one after the other - and that array is automatically returned in the form of a pointer to its start. So r is a pointer to the start of the array, *r is the first item in the array, which is some character - but certainly not a pointer (chars are often a single byte, pointers are usually 4 or 8 bytes and contain some memory address). Usage in accordance with your function signature would go completely wrong: cp = *r would take 4 or 8 of your characters and interpret them as one memory address...

Solutions are in the post linked by Davide in the comments and other answers to that question. Your static array inside a function can also work, as long as the function signature makes clear it will return a pointer - for example

void *getargs(char *command)

which could then be called from somewhere else and put in a pointer-to-arrays-of-the-correct-size,

char (*r)[CMDLENGTH] = getargs("one two three"); // r = pointer to char[CMDLENGTH]
printf("first arg: %s\n", r[0]);
printf("second arg: %s\n", r[1]);
printf("third arg: %s\n", r[2]);

This gets a little ugly; personally I'd prefer solution #2 in the linked post.

Jim Danner
  • 535
  • 2
  • 13