是否可以将char **转换为C中的char *?

时间:2018-04-20 23:21:02

标签: c arrays char

当我创建一个遍历字符串的程序时,我使用了char *类型的变量。但是我发现我需要传递一个char **类型的变量。

如果我可以将char** line转换为char* line,那么一切都会完美无缺。有没有办法做到这一点?

编辑:这是我的代码的顶部。这适用于char *变量,但除非我可以传递char** line并将其转换为char*

,否则我无法使用我的最终产品
int exiting(char* line, int argcptr){
   printf("char* line = %s\n", line);
   int words = argcptr;
   char* linecpy = (char*) malloc(100); 
   char* arg1 = " ";
   char* arg2 = " ";
   strcpy(linecpy, line);

   char* bin = strtok(linecpy, " "); //obtain the first word

   if(words > 1){
      linecpy += (strlen(bin) + 1); 
      arg1 = strtok(linecpy, " ");  //the next word will be the first argument, if applicable
      printf("arg1 = %s\n", arg1);
      words--;
   }
   if(words > 1){
      linecpy += (strlen(arg1) + 1); 
      arg2 = strtok(linecpy, " "); //if applicable, grab the third argument
   }


   //***exit [value]*** :  exit the shell with the value. if no value given, exit with value 0.
   if(strcmp(bin, "exit") == 0){

      if(strcmp(arg1, " ") == 0){
         printf("exiting with 0\n");
         exit(0);
      }
      else{
         int exitNum = atoi(arg1);
         printf("exiting with %d\n", exitNum); 
         exit(exitNum);
      }
   }
   ...

2 个答案:

答案 0 :(得分:2)

当您取消引用时,char **指针变为char *

例如

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define N 10

int main(void) {

    char **ppchar = malloc(sizeof(char *) * N);

    *ppchar = malloc(100); // now it is a char *pointer and I allocate the memory for the chars

    strcpy (*ppchar, "Hello world"); 

    printf("the char string = %s\n", *ppchar);  // referenced char ** pointer is char * now
    printf("and the actual chars. First = %c and fourth = %c\n", *(*ppchar + 0), *(*ppchar + 3));
}

*(*ppchar + 0) === **ppchar

您可以自己玩https://ideone.com/qv6w7n

答案 1 :(得分:2)

当你有这样的功能时:

void doSomething ( char ** linePtr ) {
    // ...
}

然后linePtr是指向某个字符串指针的指针,因此调用者可能会这样调用它:

char * string = ...;
doSomething(&string);

如果你的函数需要一个字符串指针,你只需要读取指针指向的值:

void doSomething ( char ** linePtr ) {
    char * line = *linePtr;
    // ...
}

但请注意,char **也可能是指向字符串指针数组的指针:

char ** strings[] = {
    "String1", "String2", "String3", "String4", NULL
};
doSomething(strings);

在这种情况下,您需要知道数组长度:

void doSomething ( char ** linePtr, size_t arrayLength ) {
    for (size_t i = 0; i < arrayLength; i++) {
        char * line = linePtr[i];
        // ...
    }
}

或者数组必须如上所示以NULL结尾,然后你可以通过检查NULL找到它的结尾:

void doSomething ( char ** linePtr ) {
    for (size_t i = 0; linePtr[i]; i++) {
        char * line = linePtr[i];
        // ...
    }
}

这里还有一些指针魔法:

char c = 5;
char * cptr = &c; // `cptr` is the address of `c`
char ** cptrptr = &cptr; // `cptrptr` is the address of `cptr`

char * anotherCptr = *cptrptr; // `anotherCptr` is the address of `c`
char anotherC = *anotherCptr; // `anotherC` is now 5.

*cptr = 8; // Now `c` is `8`

char c2 = 12;
cptr = &c2;
*cptr = 16; // `c2` is now `16` but `c` has not changed again.
**cptrptr = 2; // `c2` is now 2. Why? As `cptrptr` still points to `cptr`,
// the fact that `cptr` points elsewhere now won't influence `cptrptr`.

char * aString = calloc(sizeof(char), 100); // 100 characters in memory
char ** aStringPtr = &aString;
char * anotherString = *aStringPtr; // `anotherString == aString`
// They both point to the same piece of memory now. When changing
// `anotherString[0]`, `aString[0]` changes as well.

另请注意,指针和数组在C中通常是可以互换的,因为C中的数组没有元数据,因此内存中只有单个值的数组实际上只是一个值:

char ca = 5;
char cb[1] = { 5 }; // The memory of `ca` and the one `cb` points to look identical!
char * captr = &ca;
char * cbptr = cb; // No `&`, as an array reference is a pointer.
char c = *captr; // Works.
c = captr[0]; // Works, too, albeit `ca` is no array!
c = cbptr[0]; // Works.
c = *cbptr;   // Works, too, albeit `cb` is an array!

事实上,C中的数组订阅是语法糖。您可以随时写x[n]而不是*(x+n),它将具有相同的效果。请注意,指针上的+不会将指针移动n个字节,它会将指针移动 n倍于x <addr> + (n * sizeof(x)))的大小。所以char *指针可以是指向单个char的指针,也可以是指向char值数组(char[])的指针,你无法用C语言告诉。