0

So I saw this example:

int main()
{
  char *ls[] = {"ls", NULL};
  char *grep[] = {"grep", "pipe", NULL};
  char *wc[] = {"wc", NULL};
  char **cmd[] = {ls, grep, wc, NULL};

  loop_pipe(cmd);
  return (0);
}

And loop_pipe() is a function to manipulate the arguments for multiple pipes. But the variables on this code which are inserted into cmd are already defined. On my personal code I'm trying to do the opposite, create the variable, insert the arguments into the variable and then add it to cmd. But what isn't happening is the 'adding' need. For instance, the code look like this:

*(cmd[pipe_count]) = arg;

I guess there is something wrong ('cause it's not working) but isn't using an index to set the location of insertion sufficient to allocate a pointer of array inside my double pointer? If not can someone help me clear how to assign like this?

Edit1:

My code simplified is like this:

char* arg[100];
char** cmd[100] = {};
int pipe_count = 0;
int index = 0;
arg[pipe_count] = (char *) malloc(sizeof(char) * 100);
    for (int k = 0; params_vector[k][0] != '\0'; k++) {             // percorrer todos os parametros. exemplo: ls | less | sort
        if (strcmp(params_vector[k], "|") != 0) {
            arg[index] = params_vector[k];
            index++;
        } else {
            arg[index] = '\0';
            *(cmd) = arg;
            pipe_count++;
            arg[pipe_count] = (char *) malloc(sizeof(char) * TAM);
            index = 0;
        }
    }
11
  • 3
    "Isn't using an index to set the location of insertion sufficient to allocate a pointer of array inside my double pointer?" - Not at all. You cannot change the size of a statically allocated array. You should allocate the array dynamically with malloc() and then use realloc() to expand it. Commented May 28, 2018 at 20:51
  • @Dyz since my arg is allocated with malloc at the beggining of the program (code: arg[pipe_count] = (char *) malloc(sizeof(char) * 100); ), isn't it allocated enough for the insertion? Commented May 28, 2018 at 20:58
  • 2
    No, unless you plan to store more than 100 elements. Please provide a consistent code example. What you show us in the post now apparently is not what you really use. Commented May 28, 2018 at 21:03
  • 1
    char **cmd is a *** pointer. You just became a three star programmer!!!!!!! But it is not good - wiki.c2.com/?ThreeStarProgrammer My advice - reconsider your idea again, Commented May 28, 2018 at 21:44
  • 1
    @E.Akio it is a wrong idea. Extremely error prone, unmaintainable (I bet you will not remember those *** pointers were for after couple of days or even hours. Commented May 28, 2018 at 21:51

1 Answer 1

1

You can think of char **cmd[] as an array which contains char ** elements. So you can assign char ** elements to it.

cmd[i] = arg;

It's as simple as that. It's not much different from an array of integers.

// "foo" is a `const char[]`. So an array of them is a `const char *[]`
const char *ls[] = {"ls", NULL};
const char *grep[] = {"grep", "pipe", NULL};
const char *wc[] = {"wc", NULL};

// To store an array of `const char *[]` we need a `const char **[]`.
const char **cmd[10] = {NULL};

cmd[0] = ls;
cmd[1] = grep;
cmd[2] = wc;

In more detail...

For simplicity, the rest of this example will treat char *[] and char ** the same. There's some subtle differences, but for our purposes they don't matter. We'll treat ls, grep, and wc as char ** pointers and cmd as char ***.

char **cmd[10] allocates space for 10 char ** pointers on the stack. char ** are the same size as any other pointers. We'll assume 64 bit integers or 8 bytes. 10 of them means it allocates 80 bytes. cmd itself is a char *** pointer. That only has meaning to the compiler for type checking purposes. Ultimately all cmd contains is a 64 bit integer representing a location in memory.

Same with ls, grep, and wc. They are of type char ** which is just a 64 bit integer representing a location in memory.

cmd[0] = ls says to start at the address of cmd, advance by the size of 0 char ** pointers (so 0), and then assign the char ** pointer contained in the ls to that location. So if cmd is at memory location 100, this writes to 100 through 107.

cmd[1] = grep says to start at the address of cmd, 100. Advance by the size of 1 char ** pointers, 8. Then assign the char ** pointer contained in grep to that location. So 100 + 8 is 108. Then write 8 bytes to 108 through 115.

And cmd[2] = grep writes the 64 bit number in grep to memory location 100 + (2 * 8) or 116 through 123.

And so on. It works this way for any array of pointers. Or pointers to pointers. It's just a fancy array of integers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.