Video: Pointers and arrays 2024
Numele matricei este un pointer la matricea. Matricea este o secvență de variabile stocate în memorie. Numele de matrice indică primul element.
Aceasta este o întrebare interesantă despre indicii: Puteți să aveți un antet de funcții, cum ar fi următoarea linie și să utilizați doar dimensiunea pentru a determina câte elemente sunt în matrice? Dacă da, această funcție nu va avea nevoie ca apelantul să specifice dimensiunea matricei.
int AddUp (int numere []) {Luați în considerare această funcție găsită în exemplul Array01 și o principală () care îl numește:
void ProcessArray (int Numbers [cout << "în interiorul funcției: Mărimea în bytes este << << sizeof (Numere) << endl; int int (int argc, char * argv []) {int MyNumbers [] = {1,2,3,4, 5, 6, 7, 8, 9, 10}; cout << "funcție exterioară: Dimensiunea în octeți este"; cout << sizeof (MyNumbers) << endl; ProcessArray (MyNumbers); return 0;}
Când executați această aplicație, iată ce vedeți:
Funcție exterioară: Dimensiunea în octeți este 40 Funcție interioară: Dimensiunea în octeți este 4
În afara funcției, codul știe că dimensiunea matricei este de 40 octeți. Dar de ce codul crede că dimensiunea este de 4 după ce se află în interiorul matricei? Motivul este că, deși se pare că treci printr-o matrice, într-adevăr, treci printr-un pointer într-un matrice. Dimensiunea indicatorului este de doar 4, deci este ceea ce imprimă linia finală.
Declanșarea matricelor are o ușoară idiosincrazie. Atunci când declarați o matrice prin acordarea unui număr determinat de elemente, cum ar fi
int MyNumbers [5];
compilatorul știe că aveți o matrice și operatorul sizeof vă oferă dimensiunea întregului matrice. Numele matricei, atunci, este ambele un pointer și un matrice! Dar dacă declarați un antet de funcții fără o dimensiune a matricei, cum ar fi
void ProcessArray (int Numbers []) {
, compilatorul tratează acest lucru ca un simplu pointer și nimic mai mult. Această linie este, de fapt, echivalentă cu următoarea linie:
void ProcessArray (int * Numere) {
Astfel, în interiorul funcțiilor care declară fiecare linie, următoarele două linii de cod sunt : Numerele [3] = 10; * (Numere + 3) = 10;
Această echivalență înseamnă că dacă utilizați o declarație externă pe o matrice, cum ar fi
extern int MyNumbers [];
și apoi luați mărimea acestei matrice, compilatorul va deveni confuz. Iată un exemplu: dacă aveți două fișiere, numere. cpp și principale. cpp, unde numerele. cpp declară o matrice și una principală. cpp declară extern (așa cum se arată în exemplul Array02), veți obține o eroare de compilator dacă sunați sizeof:
#include folosind namespace std; extern int MyNumbers []; int principală (int argc, char * argv []) {cout << sizeof (MyNumbers) << endl; retur 0;}
În Cod:: Blocks, compilatorul gcc ne dă această eroare:
eroare: aplicarea nevalidă a 'sizeof' la tip incomplet 'int []'
a matricei din paranteze.Doar asigurați-vă că dimensiunea este aceeași ca și în celălalt fișier cu cod sursă! Puteți să falsificați compilatorul schimbând numărul și
nu va primi o eroare . Dar e un stil de programare prost și doar să ceri erori. Deși o matrice
este pur și simplu o secvență de variabile, toate adiacente în memorie, numele al unei matrice este într-adevăr doar un pointer la primul element din matrice. Puteți utiliza numele ca un pointer. Cu toate acestea, face acest lucru numai atunci când într-adevăr nevoie pentru a lucra cu un pointer. La urma urmei, într-adevăr nu aveți niciun motiv să scrieți un cod care este criptic, cum ar fi * (Numere + 3) = 10;. Reversul este, de asemenea, adevărat. Uită-te la această funcție:
void ProcessArray (int * Numere) {cout << numere [1] << endl;}
Această funcție are un pointer ca parametru, dar accesați-l ca un matrice. Din nou, nu scrie cod ca acesta; în schimb, trebuie să înțelegeți
de ce codul ca acesta funcționează . În acest fel, veți obține o cunoaștere mai profundă a matricelor și a modului în care aceștia trăiesc în interiorul computerului, iar aceste cunoștințe vă pot ajuta, în schimb, să scrieți coduri care funcționează corect. Chiar dacă numele matricei este doar un pointer, numele unei serii de numere întregi nu este exact același lucru ca un pointer la un număr întreg. Verificați aceste linii de cod (găsite în exemplul Array03):
int LotsNumbers [50]; int x; LotsONumbers = & x;
Indicați indicatorul LotsONumbers
la ceva diferit: ceva declarat ca un număr întreg. Compilatorul nu vă lasă să faceți acest lucru; primiți o eroare. Acest lucru nu s-ar întâmpla dacă LotsONumbers au fost declarate ca int * LotsNumbers; atunci acest cod ar funcționa. Dar, așa cum este scris, acest cod vă oferă o eroare de compilator. Și credeți sau nu, iată eroarea compilatorului pe care o primiți în Cod:: Blocuri: eroare: tipuri incompatibile în atribuirea "int *" la 'int [50]'
Această eroare presupune compilatorul nu vede distincție clară între cele două tipuri, int * și int []. Cu toate acestea, numele matricei este într-adevăr un pointer și îl puteți folosi ca unul; nu poți să faci tot ce poți, cu un pointer normal, cum ar fi realocarea acestuia.
Atunci când utilizați matrice, rețineți următoarele sfaturi. Acestea vă vor ajuta să vă păstrați cheile fără probleme:
Țineți codul în concordanță. Dacă declarați, de exemplu, un pointer la un număr întreg, nu îl tratați ca o matrice.
-
Țineți codul clar și de înțeles. Dacă treceți pointeri, este bine să luați adresa primului element, ca și în & (MyNumbers [0]) dacă acest lucru face codul mai clar - deși este echivalent doar cu MyNumbers.
-
Când declarați o matrice, încercați întotdeauna să introduceți un număr în paranteze, cu excepția cazului în care scrieți o funcție care are un matrice.
-
Când utilizați cuvântul cheie extern pentru a declara o matrice, mergeți mai departe și puneți dimensiunea matricei în paranteze. Dar fii consistenta! Nu utilizați un număr unic și un alt număr o dată. Cel mai simplu mod de a fi consecvent este să folosiți o constantă, cum ar fi const int int ArraySize = 10; într-un fișier de antet comun și apoi utilizați-l în declarația dvs. de matrice: int MyArray [ArraySize];.