Lee William
Lee William

Reputation: 125

what's the difference between char *s[] and char s[][20] in C?

Check this first code, If I write char *tracks[] instead of char tracks[][80], it seems still working same perfectly.

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

char tracks[][80] = { "I left my heart in Harvard Med School",
        "Newark, Newark - a wonderful town", "Dancing with a Dork",
        "From here to maternity", "The girl from Iwo Jima", };

void find_track(char search_for[]) {    //'char *search_for' is equivalent.
    int i;
    for (i = 0; i < 5; i++) {
        if (strstr(tracks[i], search_for))
            printf("Track %i(Line %i):'%s'\n", i, i + 1, tracks[i]);
    }
}

int main() {
    char search_for[80];
    printf("Search for: ");
    scanf("%79s", search_for);  //fgets(search_for,80,stdin);
    find_track(search_for);
    return 0;
}

But check this second code, If I try to use char juices[][20] instead of char *juices[] , the compiler give error, I want to know why?

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

void print_reverse(char *s) {
    size_t len = strlen(s);
    char *t = s + len - 1;
    while (t >= s) {
        printf("%c", *t);
        t = t - 1; //pointer arithmetic
    }
    puts("");
}

int main() {
    char *juices[] = { "dragonfruit", "waterberry", "sharonfruit", "uglifruit",
            "rumberry", "kiwifruit", "mulberry", "strawberry", "blueberry",
            "blackberry", "starfruit" };

    char *a;

    puts(juices[6]);
    print_reverse(juices[7]);
    a = juices[2];
    juices[2] = juices[8];
    juices[8] = a;
    puts(juices[8]);
    print_reverse(juices[(18 + 7) / 5]);

    puts(juices[2]);
    print_reverse(juices[9]);
    juices[1] = juices[3];
    puts(juices[10]);
    print_reverse(juices[1]);

    return 0;
}

This is quite strange, because if you check third code below, it will give error because pointer to a string literal can not be updated. If the thing is like this, then in second code char *juices[] is array of pointers to string literals, and then juices[2] is a pointer to "sharonfruit", how can it be updated?

#include <stdio.h>

int main()
{

char *cards = "JQK";  //you should use char cards[]="JQK";
char a_card = cards[2];

cards[2] = cards[1];
cards[1] = cards[0];
cards[0] = cards[2];
cards[2] = cards[1];
cards[1] = a_card;

puts(cards);

return 0;

}

Upvotes: 0

Views: 188

Answers (2)

Spikatrix
Spikatrix

Reputation: 20244

char tracks[][80] = { "I left my heart in Harvard Med School",
    "Newark, Newark - a wonderful town", "Dancing with a Dork",
    "From here to maternity", "The girl from Iwo Jima", };

Creates an array of array of char or in other words, creates a two dimensional array of char and initializes each index with each strings. The number of strings is determined by the compiler during compile-time and the maximum size of each string is 80.

char *tracks[] = { "I left my heart in Harvard Med School",
    "Newark, Newark - a wonderful town", "Dancing with a Dork",
    "From here to maternity", "The girl from Iwo Jima", };

declares an array of char pointers. Each pointer points to each string literal. The number of pointers is determined by the compiler during compile-time.

String Literals are immutable meaning that it cannot be changed.

In your first two programs using tracks, the first version(char tracks[][80]) and the second version(char* tracks[]) works as strings aren't changed and arrays are not assigned.

In the second two programs using juices, the first version works(char* juices[]) because pointers can be altered,i.e, the location where they point to can be changed, but the second version(char juices[][80]) doesn't because you assign arrays. Keep in mind that Arrays are not assignable.

To fix the problem, you can use the strcpy function from the string.h library to interchange the strings stored in char juices[][80]. Do note that memory needs to be allocated for variable a if you are going to attempt this.

Upvotes: 3

Marcus M&#252;ller
Marcus M&#252;ller

Reputation: 36346

In C, the "outermost" array (ie. the first []) are automatically type-converted to a pointer to the first element.

Thus,

char tracks[][80] 

declares a pointer to a char array (of length 80).

However

char *tracks[]

obviously is an array of char-pointers, which is something different. The compiler knows that and won't let you do that.

Also, these things are something different in memory: the array-compound definitely is linear in memory, the array of pointers might contain pointers that point anywhere in memory.

Upvotes: 0

Related Questions