cari

Rumah  >  Soal Jawab  >  teks badan

objective-c - 关于C语言指针的问题

C语言指针问题 下面代码为什么第二个数字是5呢?

int a[5] = {1,2,3,4,5};
int *p = (int *)(&a+1);
NSLog(@"%d,%d", *(a+1), *(p-1));
黄舟黄舟2769 hari yang lalu425

membalas semua(3)saya akan balas

  • 阿神

    阿神2017-04-21 11:19:34

    &a menghasilkan penuding kepada tatasusunan, jadi &a+1 sebenarnya bergerak berdasarkan panjang tatasusunan. Jika anda hanya ingin mendapatkan elemen kedua tatasusunan, kemudian gunakan *(&a[0]+1), kerana jenis data &a[0] ialah int*. Lukis gambar dahulu:

    Andaikan kita mempunyai tatasusunan berikut

    int a[5] = {1,2,3,4,5};
    int *x = &a+1;
    

    Walaupun program di atas boleh disusun dan diluluskan, pengkompil akan mengeluarkan amaran kerana jenis x dan a tidak sepadan Terdapat dua cara untuk membuang amaran

    1. Melalui penukaran jenis paksa

    int *x = (int *)(&a+1); 
    print("%d\n",*(x-1));
    

    2. Cari jenis yang sesuai untuknya. Jenis &a ialah int (*)[5]

    int (*x)[5] = &a+1;
    printf("%d\n",**(x-1));
    

    Ini melibatkan cara menulis jenis data yang sesuai, yang sangat penting dalam tugasan dan lulus parameter!

    Jadi, mula-mula saya perlu meringkaskan jenis data a, &a dan &a[0]

    1. a ialah nama tatasusunan, yang merupakan penunjuk kepada elemen pertama tatasusunan Tidak syak lagi bahawa di sini, jenis data bagi elemen pertama tatasusunan ialah int, jadi jenis data a ialah Ia adalah int*.

    2. &a mengambil alamat tatasusunan satu dimensi, dan hasilnya ialah penuding kepada tatasusunan (dalam kes ini, penuding kepada tatasusunan int), iaitu,

      int(*)[5 ] .

    3. &a[0] adalah sangat mudah, pertama, a[0] mendapat integer, dan kemudian mengambil alamatnya, jadi jenis datanya ialah

      int*.

    Sekarang anda tahu jenis data, aritmetik penunjuk menjadi lebih jelas!

    Pertama lihat bahagian kod yang melepasi penukaran jenis paksa Apakah nombor yang akan ia keluarkan?

    Jawapannya ialah 5! Daripada ringkasan jenis data tadi, kita boleh tahu bahawa jenis data &a ialah

    int (*)[5], jadi &a+1 sebenarnya telah dialihkan sebanyak 5*sizeof(int) byte Sekarang penunjuk menunjuk kepada elemen selepas elemen terakhir tatasusunan (Rajah 1), iaitu, ia telah melepasi sempadan! Tetapi kerana jenis data x sebenarnya int * Jadi untuk x-1, ia sebenarnya dialihkan 1*sizeof(int) bait ke kiri, yang bermaksud ia menunjuk ke elemen terakhir, jadi *(x-1) diperolehi Nilai ialah elemen terakhir tatasusunan: 5

    Baiklah, sekarang mari kita lihat bahagian kedua. Apakah nombor yang akan dikeluarkan? Mari kita tidak bercakap tentang jawapannya dahulu. Jenis data bagi Sizeof(int)*5 bait dialihkan dalam unit, jadi x-1 sebenarnya dialihkan ke kiri oleh sizeof(int)*5 bait Ia dialihkan pada mesin saya. 20 bait, yang kembali kepada elemen pertama tatasusunan, jadi jawapannya ialah: 1

    Di atas ialah tatasusunan satu dimensi Sekarang saya ingin bercakap tentang situasi tatasusunan dua dimensi Terdapat sekeping kod berikut:

    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    /*
    ?? = a; // int (*b)[3] = a;
    ?? = a[0]; // int *c = a[0];
    ?? = a[0][0] // int d = a[0][0];
    ?? = &a; // int (*e)[3][3] = &a;
    ?? &a[0]; // int (*f)[3] = &a[0]
    ?? &a[0][0]; // int *g = &a[0][0]
    */
    

    Mari lihat dahulu jenis data a, a[0], &a, &a[0], &a[0][0]:

    Perhatikan teks tebal di atas Nama tatasusunan ialah penunjuk kepada elemen pertama tatasusunan!

    1. Apakah jenis data a? ? int *? Tidak, inti teks tebal ini ialah lima perkataan elemen pertama. Bukankah elemen pertama bagi a[0][0] sahaja? Tegasnya, tidak, elemen pertama a sebenarnya ialah a[0], jadi apakah jenis data a[0]? a[0] ialah tatasusunan yang mengandungi tiga elemen int, jadi jenis a[0] adalah sama dengan jenis t dalam int t[3], iaitu int* Sejak jenis data elemen pertama ialah int*, jika tatasusunan dua dimensi ini dianggap sebagai tatasusunan satu dimensi, ia sebenarnya tatasusunan yang mengandungi tiga elemen int*. Tatasusunan ialah tatasusunan penunjuk, jadi jenis data a ialah int (*)[3]

    2. Mari kita lihat &a sekali lagi Seperti yang dinyatakan semasa bercakap tentang tatasusunan satu dimensi, alamat yang diperolehi dengan mengambil alamat nama tatasusunan ialah penunjuk kepada tatasusunan, jadi jenis data &a ialah . int (*)[3] [3]

    3. &a[0] Ini nampaknya agak menyakitkan, tetapi seperti yang dinyatakan dalam perenggan sebelumnya, a[0] ialah tatasusunan yang mengandungi tiga elemen int dan int t[3] Jenis data t adalah sama, iaitu int* Sememangnya, jenis data &a[0] adalah sama dengan jenis data &t, iaitu int (*) [3]

    Pada ketika ini, kami hampir menulis tentang jenis data dalam tatasusunan dua dimensi Sekarang setelah kami mengetahui jenis data, kami dapat mengetahui dengan tepat di mana penunjuk akan bergerak selepas pengiraan.

    Lihat kod berikut:

    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    int (*x)[3] = a;
    int *k = a[0];
    int (*y)[3][3] = &a;
    int (*q)[3] = &a[0];
    int *z = &a[0][0];
    
    printf("%d\n",(*(x+1))[0]);
    printf("%d\n",*(k+1));
    printf("%d\n",(*(*(y+1)))[0]);
    printf("%d\n",(*(q+1))[0]);
    printf("%d\n",*(z+1));
    
    int *p = (int *)(y+1);
    printf("%d\n",*(p-1));
    
      Jenis data
    • x ialah int (*)[3], jadi x+1 sebenarnya digerakkan oleh 3*sizeof(int) bait, seperti yang ditunjukkan dalam rajah:

    • Jenis data
    • k ialah int *, jadi k+1 sebenarnya dialihkan oleh sizeof(int) bait.

    • Jenis data
    • y ialah int (*)[3][3], jadi y+1 sebenarnya dialihkan oleh 3*3*sizeof(int) bait, iaitu kepada yang terakhir dalam tatasusunan Unsur selepas unsur. Seperti yang ditunjukkan dalam gambar:

    • Jenis data
    • q ialah int (*)[3], jadi q+1 sebenarnya dialihkan oleh 3*sizeof(int) bait.

    • Jenis data
    • z ialah int *, jadi z+1 sebenarnya dialihkan oleh sizeof(int) bait.

    Jadi apabila menambah dan menolak penunjuk tatasusunan, perkara yang paling penting ialah mengetahui saiz langkahnya, dan saiz langkah ditentukan oleh jenis data!

    balas
    0
  • PHP中文网

    PHP中文网2017-04-21 11:19:34

    Penjawab di tingkat satu menulis dengan sangat baik, sila kembangkan padanya

    Nilai penuding ialah alamat tatasusunan
    int (* pa)[5];
    pa++;pa bergerak ke belakang 20 bait (5*4)

    Berbeza, elemen dalam tatasusunan ialah penunjuk (int*)
    int *pa[5];
    pa++;pa bergerak ke belakang 4 bait

    balas
    0
  • 高洛峰

    高洛峰2017-04-21 11:19:34

    Maaf kerana menyiarkan semula siaran lama. Saya melihat ini secara tidak sengaja, kerana pada masa lalu semasa saya melakukan pengaturcaraan terbenam, tatasusunan dan penunjuk sering digunakan, termasuk secara langsung memberikan alamat memori kepada pembolehubah penunjuk (ini biasanya tidak digunakan dalam aplikasi biasa), dan saya tidak pernah menemui &arr sebelum ini. Apa bezanya dengan arr. Saya menyemak secara khusus hari ini dan mendapati bahawa ini bergantung pada pengkompil. Sesetengah penyusun merawat tatasusunan dan penunjuk secara berasingan Maksud mengambil alamat untuk nama tatasusunan adalah untuk keseluruhan memori tatasusunan yang menganggap tatasusunan sebagai bentuk tertentu penunjuk memori tatasusunan, tetapi tiada perkara seperti keseluruhan memori tatasusunan.

    balas
    0
  • Batalbalas