2016-07-28 13 views
3
#include <stdio.h> 

    int main() 
    { 
     char str[3][15] = {"Pointer to","char","program"}; 
     char (*pt)[15] = str; // statement A 
     char *p = (char *)str; // statement B 
     printf("%s\n",p[3]); // statement C - Seg Fault in this line 
     printf("%s\n",p); // working properly displaying "Pointer to" 
     printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to" 
     printf("%s\n",pt+1); // printing properly "char" as expected 
     int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 
     int (*nm)[3] = num[1]; 
     int *n = num; 
     printf("n - %d\n",n[10]); // statement D 
     printf("nm - %d\n",nm[0][0]); 
     return 0; 
    } 

Meine Fragen:Was ist der Unterschied zwischen Zeiger auf 2D-Char-Array und Zeiger auf 2D-Int-Array?

  1. Bitte helfen Sie mir klare Vorstellung über die Daten zu erhalten, in Fall von char-Array und Int-Array Speichermechanismus

  2. In oben Programm Ich verstehe, dass, wenn die Maus zu Char-Array wird auf 2D-Array von Zeichen wie in Anweisung A gezeigt, es ist ordnungsgemäß angezeigt, aber wenn es von normalen Char-Zeiger gezeigt wird und versuchen, das Zeichen in Anweisung C zu drucken, erhält es Se gFault, stattdessen sollte es 'n' (3. Nummer Zeichen im ersten Array "Zeiger to") so mit der Verwirrung, warum im Fall Array ich bekomme richtig Element n = 11 in Anweisung D und warum in diesem Fall (Anweisung C) es wird nicht ordnungsgemäß gedruckt.

  3. Wie werden die Daten im Falle eines char-Array gespeichert wird es in dieser Form unter


char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o'}, 
        {'c','h','a','r'}, 
        {'p','r','o','g','r','a','m'}}; 

wenn es so gespeichert wird, dann sollte es funktionieren wie gezeigt gespeichert werden Array des Integer-Zeigers in Anweisung D Bitte helfen Sie mir, zu diesem Problem zu führen und das Problem zu klären, das ich im Falle von char und int Array-Speicher habe.

+0

'char str [3] [15] = {{'P', 'o', 'ich', 'n', 't', 'e', ​​'r', '', 't', '0', {'c', 'h', 'a', 'r', '\ 0'}, {'p', 'r', 'o', 'g ',' r ',' a ',' m ',' \ 0 '}}; ' – LPs

+0

Anweisung D funktioniert, weil' num' als einzelnes Array zugewiesen wird, auf das der Compiler mit der folgenden Formel zugreift: num [row] [col] 'dann ist es das gleiche wie' * ((int *) num + row * 4 + col) '. – miravalls

+0

'printf ("% s \ n ", p [3]);' -> 'printf ("% s \ n ", &p[3]);' – LPs

Antwort

2

Ihr segfault ist aufgrund der Tatsache, dass Sie den falschen Typ an printf übergeben.

Schreiben p[3] Sie deaktivieren den Zeiger auf die 4. char der ersten Zeile der Matrix str. Gleich wie *(p+3)

Wenn Sie das dritte Zeichen drucken möchten, sollten Sie

printf("%c\n",p[3]); 

Wenn Sie die erste C-String (Zeile 0 der Matrix) müssen Sie drucken möchten:

printf("%s\n",&p[3]); 

weil %s ein char * will.

Wenn Sie hinzufügen, zumindest für gcc, -Wall Option auf Ihren Befehl, wird Compiler zeigen Ihnen eine gute und nützliche Warnung:

test.c:8:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=] 
     printf("%s\n",p[3]); // statement C - Seg Fault in this line 

Über Frage 3 Sie nehmen zur Kenntnis, muss, dass die richtige Lagerung ist:

char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o','\0'}, 
        {'c','h','a','r','\0'}, 
        {'p','r','o','g','r','a','m','\0'}}; 

aufgrund der Tatsache, daß C-String null beendet werden, so zum Beispiel die Zeichenkette "Pointer to"11 Zeichen besetzt


Letzte Sache ist über die int Zeiger.Es funktioniert gut, weil der %d Formatspezifizierer einen int Wert, keine Adresse, wünscht. So schreibt:

printf("n - %d\n",n[10]); 

völlig korrekt ist, weil n[10] ist das 11. Element der num Matrix dereferencing, bedeutet, dass dritte Element der 3. Reihe. Wie *(n+10)

+0

* Writing p [3] Sie den Zeiger auf den 3. char * deaktivieren Das ist nicht korrekt – 2501

+0

Verwenden von 'p', um aus den Grenzen des inneren Array, wie' p [10] 'zeigen, ist undefiniertes Verhalten. – 2501

+0

@ 2501 Ok für den ersten Kommentar, den ich bearbeitet habe, aber ich versteh dich nicht über den zweiten – LPs

3

Lets schauen Sie Ihren Code Schritt für Schritt.

char str[3][15] = {"Pointer to","char","program"}; 

Hier haben Sie eine Reihe von drei Reihen von fünfzehn char ‚s erstellt. Und Sie initialisieren jedes der char Arrays mit Zeichenfolgenliteralen. Wenn Literale sind kürzer als Array - letzten Elemente werden mit Nullen aufgefüllt, so ist es das gleiche wie:

char str[3][15] = { 
    {'P', 'o', 'i', 'n', 't', 'e', 'r', ' ', 't', 'o', 0, 0, 0, 0, 0}, 
    {'c', 'h', 'a', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {'p', 'r', 'o', 'g', 'r', 'a', 'm', 0, 0, 0, 0, 0, 0, 0, 0} 
}; 

Dann

char (*pt)[15] = str; // statement A 

Hier erstellen Sie pt als Zeiger auf Array von fünfzehn char ‚s , und Sie initialisieren es mit der Adresse str[0], dh pt Punkte zu ersten char[15] Array von str.

Weiter

char *p = (char *)str; // statement B 

Es ist nicht in Ordnung. So weit ich sehe - Sie versuchen, auf den ersten char im Speicher, der str besetzt. Ausdruck str hat Typ von char (*)[15], dh es ist ein Zeiger auf Array von Zeichen, nicht Zeiger auf char (und aus diesem Grund sind Sie gezwungen, Cast zu verwenden) Und unabhängig davon, dass str wirklich auf Zelle zeigt, wo die 'P' gespeichert ist - Sie können es in mehr typsichere Weise zu sollen:

char *p = &str[0][0]; // the same as "p = str[0];" 

str[0] verweist auf das erste Element von str, dh Art von str[0] ist ein Array von fünfzehn char ‚s, dann können Sie nur auf die erste char verweisen und nehmen Sie es Adresse - &(str[0])[0], oder verwenden Sie einfach die Tatsache, dass Ausdruck mit dem Typ "Array" verfällt, um "Zeiger t" einzugeben o Element des ersten Arrays ", deshalb funktioniert str[0] auch.

Lets go voraus

printf("%s\n",p[3]); // statement C - Seg Fault in this line 

Diese Linie nicht definiertes Verhalten verursacht, weil Formatspezifizierer das zweite Argument erfordert eine const char * zu sein, aber sie sind vorbei char. Wenn Sie ein Zeichen drucken wollen - das tun:

printf("%c\n", p[3]); // prints "n" 

Dann

printf("%s\n",p); // working properly displaying "Pointer to" 
    printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to" 

Diese funktionieren gut, weil die Art der zweiten Argument richtig ist, und wir wissen, dass Strings nul-termini sind.

printf("%s\n",pt+1); // printing properly "char" as expected 

sagen offen - es falsch ist, da pt + 1 ist „Zeiger auf Array von char“, aber Sie sollten „Zeiger auf char“ übergeben. Es soll wie folgt umgeschrieben werden:

printf("%s\n",*(pt+1)); // or pt[1] 

Aber es scheint zu funktionieren, weil unabhängig von der Art Inkompatibilität beiden Zeiger auf die gleiche Stelle verweisen.

Nächster Abschnitt über int 's.

int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 
int (*nm)[3] = num[1]; 
int *n = num; 

Hier sind zwei Fehler: nm sollte nicht mit num[1] initialisiert werden, da sie inkompatible Typen haben: „Zeiger auf Array von drei int“ vs. „Anordnung von vier int/Zeiger auf int“ (dank abklingenden). Und n kann nicht mit num initialisiert werden, weil sie auch inkompatible Typen haben. Nach meiner Vermutung über das, was Sie wollen, dass es in der nächsten Weise aussehen sollte:

int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 
int (*nm)[4] = num + 1; 
int *n = &num[0][0]; 

Und die letzten:

printf("n - %d\n",n[10]); // statement D 
printf("nm - %d\n",nm[0][0]); 

Dereferenziere korrekt ist und bestanden auch Argumente, aber denken Sie daran, dass Zeiger wurden initialisiert falsch.

Hoffe, ich habe alle Ihre Fragen abgedeckt.

+0

Große Antwort .... – 2501

+0

Großartig. besser als meins. ;) – LPs

Verwandte Themen