The short answer to your question of storing a list of strings in a char** is "yes". But, as usual there is more to the story. The line of code that you have above where you define "testRights" is correct, but then the responsibility is on you as the programmer as what to do with that information.
If you just evaluate the value of "testRights" what you probably are viewing is the memory address of the first character array (e.g. "VIEW"). You need to treat "testRights" like an array of address pointers which is basically what it is.
Following is a snippet of code to illustrate how you might drill down to get the character/string information that you are storing in your character arrays.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* rightArray[3] = {"VIEW", "EDIT", "EXTRACT"};
char** testRights = rightArray;
printf("Array #0: %s\n", *(testRights));
printf("Array #1: %s\n", *(testRights + 1));
printf("Array #2: %s\n", *(testRights + 2));
printf("-----------------------------\n");
printf("Array #0: %s\n", testRights[0]);
printf("Array #1: %s\n", testRights[1]);
printf("Array #2: %s\n", testRights[2]);
printf("-----------------------------\n");
printf("rightArry[0] memory address: %p\n", rightArray[0]);
printf("rightArry[1] memory address: %p\n", rightArray[1]);
printf("rightArry[2] memory address: %p\n", rightArray[2]);
printf("-----------------------------\n");
printf("Array address #0 via testRights pointer: %p\n", *(testRights));
printf("Array address #1 via testRights pointer: %p, Offset: %ld\n", *(testRights + 1), (*(testRights + 1) - *(testRights)));
printf("Array address #2 via testRights pointer: %p, Offset: %ld\n", *(testRights + 2), (*(testRights + 2) - *(testRights + 1)));
return 0;
}
First off, the character array is set up with your three literals. Then, as in your sample code, "char**" "testRights" is defined and references your array of literal strings. Subsequently, access to the list of character arrays via the "testRights" variable is executed first using pointer incrementing followed by treating "testRights" like an indexed array. And, to illustrate the relationship between the values within "testRights" and the corresponding memory address values assigned to each "rightArray" character array, those values are printed out showing their relationship.
Following is the output from running this proof-of-principle code.
@Una:~/C_Programs/Console/StringArray/bin/Release$ ./StringArray
Array #0: VIEW
Array #1: EDIT
Array #2: EXTRACT
-----------------------------
Array #0: VIEW
Array #1: EDIT
Array #2: EXTRACT
-----------------------------
rightArry[0] memory address: 0x5567fd286004
rightArry[1] memory address: 0x5567fd286017
rightArry[2] memory address: 0x5567fd28602a
-----------------------------
Array address #0 via testRights pointer: 0x5567fd286004
Array address #1 via testRights pointer: 0x5567fd286017, Offset: 19
Array address #2 via testRights pointer: 0x5567fd28602a, Offset: 19
FYI, the "offset" value printed is just for additional information to illustrate how the code might allocate additional bytes for each literal character array. That value may be different on your system depending upon the compiler and operating system.
Just to add some caveats, working with arrays of pointers, the responsibility is on you to ensure that your code does not go out-of-bounds when working with those values. That's when things such as segmentation faults occur, or worse undefined behavior occurs. So ensure your code has proper "guardrails".
That should give you enough to chew on.