简体   繁体   中英

Difference between char* and char** (in C)

I have written this code which is simple

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

void printLastLetter(char **str)
{
    printf("%c\n",*(*str + strlen(*str) - 1));
    printf("%c\n",**(str + strlen(*str) - 1));
}

int main()
{
    char *str = "1234556";
    printLastLetter(&str);
    return 1;
}

Now, if I want to print the last char in a string I know the first line of printLastLetter is the right line of code. What I don't fully understand is what the difference is between *str and **str. The first one is an array of characters, and the second?? Also, what is the difference in memory allocation between char *str and str[10]? Thnks

char* is a pointer to char, char ** is a pointer to a pointer to char.

char *ptr; does NOT allocate memory for characters, it allocates memory for a pointer to char.

char arr[10]; allocates 10 characters and arr holds the address of the first character. (though arr is NOT a pointer (not char * ) but of type char[10] )

For demonstration: char *str = "1234556"; is like:

char *str;         // allocate a space for char pointer on the stack
str = "1234556";   // assign the address of the string literal "1234556" to str

As @Oli Charlesworth commented, if you use a pointer to a constant string, such as in the above example, you should declare the pointer as const - const char *str = "1234556"; so if you try to modify it, which is not allowed, you will get a compile-time error and not a run-time access violation error, such as segmentation fault. If you're not familiar with that, please look here .

Also see the explanation in the FAQ of newsgroup comp.lang.c .

char **x is a pointer to a pointer, which is useful when you want to modify an existing pointer outside of its scope (say, within a function call).

This is important because C is pass by copy, so to modify a pointer within another function, you have to pass the address of the pointer and use a pointer to the pointer like so:

void modify(char **s)
{
  free(*s); // free the old array
  *s = malloc(10); // allocate a new array of 10 chars
}

int main()
{
  char *s = malloc(5); // s points to an array of 5 chars
  modify(&s); // s now points to a new array of 10 chars
  free(s);
}

You can also use char ** to store an array of strings. However, if you dynamically allocate everything, remember to keep track of how long the array of strings is so you can loop through each element and free it.

As for your last question, char *str; simply declares a pointer with no memory allocated to it, whereas char str[10]; allocates an array of 10 chars on the local stack. The local array will disappear once it goes out of scope though, which is why if you want to return a string from a function, you want to use a pointer with dynamically allocated (malloc'd) memory.

Also, char *str = "Some string constant"; is also a pointer to a string constant. String constants are stored in the global data section of your compiled program and can't be modified. You don't have to allocate memory for them because they're compiled/hardcoded into your program, so they already take up memory.

The first one is an array of characters, and the second??

The second is a pointer to your array. Since you pass the adress of str and not the pointer (str) itself you need this to derefence.

printLastLetter( str ); 

and

printf("%c\n",*(str + strlen(str) - 1)); 

makes more sense unless you need to change the value of str.

You might care to study this minor variation of your program (the function printLastLetter() is unchanged except that it is made static), and work out why the output is:

3
X

The output is fully deterministic - but only because I carefully set up the list variable so that it would be deterministic.

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

static void printLastLetter(char **str)
{
    printf("%c\n", *(*str + strlen(*str) - 1));
    printf("%c\n", **(str + strlen(*str) - 1));
}

int main(void)
{
    char *list[] = { "123", "abc", "XYZ" };
    printLastLetter(list);
    return 0;
}

char** is for a string of strings basically - an array of character arrays. If you want to pass multiple character array arguments you can use this assuming they're allocated correctly.

char **x; *x would dereference and give you the first character array allocated in x. **x would dereference that character array giving you the first character in the array.

for your code snippet, *str holds address to a char and **str holds address to a variable holding address of a char. In another word, pointer to pointer.

Whenever, you have *str, only enough memory is allocated to hold a pointer type variable(4 byte on a 32 bit machine). With str[10] , memory is already allocated for 10 char .

**str is nothing else than (*str)[0] and the difference between *str and str[10] (in the declaration, I assume) I think is, that the former is just a pointer pointing to a constant string literal that may be stored somewhere in global static memory, whereas the latter allocates 10 byte of memory on the stack where the literal is stored into.

char * is a pointer to a memory location. for char * str="123456"; this is the first character of a string. The "" are just a convenient way of entering an array of character values. str[10] is a way of reserving 10 characters in memory without saying what they are.(nb Since the last character is a NULL this can actually only hold 9 letters. When a function takes a * parameter you can use a [] parameter but not the other way round.

You are making it unnecessarily complicated by taking the address of str before using it as a parameter. In C you often pass the address of an object to a function because it is a lot faster then passing the whole object.But since it is already a pointer you do not make the function any better by passing a pointer to a pointer. Assuming you do not want to change the pointer to point to a different string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM