Search code examples
cc-stringsstring-literalsstrcmpequality-operator

What are Strings in C if not Simply Char Arrays?


I'm new to the C programming language, and I was under the impression that strings are just arrays of characters. However, when I tried the following code below (among some other tests):

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

int main(int argc, char **argv)
{
    char apple1[] = { 'a', 'p', 'p', 'l', 'e', '\0' };
    char *apple2 = "apple";
    char apple3[] = "apple";

    printf("%i\n", apple1 == apple2); // 0
    printf("%i\n", apple2 == apple3); // 0
    printf("%i\n", apple3 == apple1); // 0
    printf("%i\n", "apple" == apple1); // 0
    printf("%i\n", "apple" == apple2); // 1
    printf("%i\n", "apple" == apple3); // 0
    printf("%i\n", !strcmp(apple1, apple2)); // 1

    for (size_t i = 0; i < strlen(apple) + 1; i++)
    {
        printf("%i", apple1[i] == apple2[i]);
    } // 111111

    return 0;
}

I got some unexpected results. Is there any reason for these, at least for me, counterintuitive results? Thank you very much.


Solution

  • In these declarations

    char apple1[] = { 'a', 'p', 'p', 'l', 'e', '\0' };
    char *apple2 = "apple";
    char apple3[] = "apple";
    

    there are declared two arrays apple1 and apple3 that contain the string "apple".

    In this declaration

    char *apple2 = "apple";
    

    there is declared a pointer to the string literal "apple".

    In these calls of printf

    printf("%i\n", apple1 == apple2); // 0
    printf("%i\n", apple2 == apple3); // 0
    printf("%i\n", apple3 == apple1); // 0
    printf("%i\n", "apple" == apple1); // 0
    printf("%i\n", "apple" == apple2); // 1
    printf("%i\n", "apple" == apple3); // 0
    

    there are compared addresses of first characters of different arrays that occupy different extents of memory. Arrays used in expressions with rare exceptions are converted to pointers to their first elements. So the result of the expressions is the integer value 0 except this call

    printf("%i\n", "apple" == apple2); // 1
    

    because in this case there are compared pointers to the same string literal (its first character) because it seems the compiler allocated one character array to store the string literal "apple" used in this call and in this declaration of a pointer

    char *apple2 = "apple";
    

    You can represent the above declaration and the call of printf the following way

    char *apple2 = &"apple"[0];
    //...
    printf("%i\n", &"apple"[0] == apple2); // 1
    

    However in general even if you will write for example

    printf("%i\n", "apple" == "apple");
    

    then the output can be either 0 or 1 depending on how the compiler stores identical string-literals: either as different character arrays or as one character array (it depends on compiler options).

    To compare character arrays that contain strings you need to use standard C string function strcmp.