What is the difference between char array and char pointer in C?

I am trying to understand pointers in C but I am currently confused with the following:

  • char *p = "hello"
    

    This is a char pointer pointing at the character array, starting at h.

  • char p[] = "hello"
    

    This is an array that stores hello.

What is the difference when I pass both these variables into this function?

void printSomething(char *p)
{
    printf("p: %s",p);
}

Solution 1:

char* and char[] are different types, but it's not immediately apparent in all cases. This is because arrays decay into pointers, meaning that if an expression of type char[] is provided where one of type char* is expected, the compiler automatically converts the array into a pointer to its first element.

Your example function printSomething expects a pointer, so if you try to pass an array to it like this:

char s[10] = "hello";
printSomething(s);

The compiler pretends that you wrote this:

char s[10] = "hello";
printSomething(&s[0]);

Solution 2:

Let's see:

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

int main()
{
    char *p = "hello";
    char q[] = "hello"; // no need to count this

    printf("%zu\n", sizeof(p)); // => size of pointer to char -- 4 on x86, 8 on x86-64
    printf("%zu\n", sizeof(q)); // => size of char array in memory -- 6 on both

    // size_t strlen(const char *s) and we don't get any warnings here:
    printf("%zu\n", strlen(p)); // => 5
    printf("%zu\n", strlen(q)); // => 5

    return 0;
}

foo* and foo[] are different types and they are handled differently by the compiler (pointer = address + representation of the pointer's type, array = pointer + optional length of the array, if known, for example, if the array is statically allocated), the details can be found in the standard. And at the level of runtime no difference between them (in assembler, well, almost, see below).

Also, there is a related question in the C FAQ:

Q: What is the difference between these initializations?

char a[] = "string literal";   
char *p  = "string literal";   

My program crashes if I try to assign a new value to p[i].

A: A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:

  1. As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values of the characters in that array (and, if necessary, its size).
  2. Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.

Some compilers have a switch controlling whether string literals are writable or not (for compiling old code), and some may have options to cause string literals to be formally treated as arrays of const char (for better error catching).

See also questions 1.31, 6.1, 6.2, 6.8, and 11.8b.

References: K&R2 Sec. 5.5 p. 104

ISO Sec. 6.1.4, Sec. 6.5.7

Rationale Sec. 3.1.4

H&S Sec. 2.7.4 pp. 31-2