2013-04-10 15 views
5

Dlaczego nie mogę wskazać znaku ** na tablicę ciągów C?char ** vs char * c [] dla dostępu do tablicy łańcuchów

int main(int argc, char *argv[]) { 

    char* c1[] = {"Hey","Hello"}; 
    printf("%s",c1[1]); 

} //works fine 

vs

int main(int argc, char *argv[]) { 

    char** c1 = {"Hey","Hello"}; 
    printf("%s",c1[1]); 

} //error 
+6

Wskaźniki nie są tablicami. –

Odpowiedz

6

Myślę, że zamieszanie wynika z przekonania, że ​​{"Hey","Hello"} jest tablicą. To nie jest. To wcale nie jest obiekt. Jest to po prostu specjalna składnia inicjalizacyjna, która może być użyta do zainicjowania tablicy. Nie można go użyć do zainicjowania char**, ponieważ char** jest wskaźnikiem, a nie tablicą. Nie tworzy on automatycznie obiektu tablicy, który można przekonwertować na wskaźnik.

Być może myślisz o tym jak o liście [...] w Pythonie lub obiekcie { ... } w JavaScript. Wcale tak nie jest. Wyrażenia te faktycznie tworzą obiekty tego typu i mogą być używane w dowolnym miejscu wyrażenia, które może przyjmować te obiekty.Składnia, której używamy w C++, jest składnią inicjującą.

Na przykład mógłby to zrobić:

const char* array[] = {"Hey","Hello"}; 
const char** p = array; 

Ty, jednak nie mogą zrobić coś głupiego takiego:

std::cout << {"Hey", "Hello"}[1]; 

Tutaj mamy faktycznie utworzony obiekt array, w którym wskaźniki będą przechowywane. Tylko wtedy możemy przekonwertować tę tablicę na const char**.

+0

Bardzo wyraźne ... .thxxx – tez

1

Dlaczego nie mogę litera a char** do tablicy ciągów C?

Tak jak powiedziałeś, c1 jest tablicą. Tak więc musisz zadeklarować ją jako tablicę wskaźników do char.

Od "Hey" i "Hello"strunowe litterals każdy c1[i] ciąg jest wskazując anonimowego ciąg. Dlatego można używać wskaźników do char zamiast tablic z char.

Aby utworzyć tablicę wskaźników do char, nie można jednak użyć urządzenia char **.

2

zmiana

char** c1 = (char *[]){"Hey","Hello"};

0

"char ** c1", informuje kompilator, że jest to wskaźnik do wskaźnika do typu char, to typ skalarny (jedna wartość).

Inicjalizacja z listą wartości działa tylko dla typów agregatów.

+0

Nie ma dwuznaczności w 'char ** c1'. Jest to wskaźnik do wskaźnika "char". (Oczywiście, oba wskaźniki w powyższym mogą być pierwszym elementem tablicy.) –

+0

@ James Kanze, tak, mój błąd. Usunąć to. – Arun

0
int main(int argc, char *argv[]) { 

    char** c1 = {"Hey","Hello"}; 
    printf("%s",c1[1]); 

} //error 

W powyższym kodzie próbujesz ustawić wskaźnik na wskaźnik na zestaw dwóch ciągów. Gdzie jest miejsce na dwa wskaźniki zawierające odpowiednio adres "Cześć" i "Cześć"? Nigdzie.

Można zrobić:

char *a = "Hey"; 
char *b = "Hello"; 
char *c[] = { a, b };  // This MAY not compile due to a and b not being compile time constants. 
char **c1 = c; 

(mam podzielić go na więcej zmiennych poszczególnych niż faktycznie potrzebuje, ale myślę, że to wyjaśnia, co to jest „nie tak” z kodem dość wyraźnie).

Innym przykładem może być, jeśli zmienimy char * int:

const int a = 1; 
const int b = 2; 

int c[] = { a, b }; 

int *c = { a, b }; // Doesn't work, there is nowhere to store a copy of a and b. 

To samo, tylko z liczb całkowitych.