ከጠቋሚዎች ጋር ክዋኔዎች. ከጠቋሚዎች ጋር ክዋኔዎች በ C ውስጥ የሚከተሉት የጠቋሚ ዓይነቶች ተለይተዋል፡

መለያዎች ሲ ጠቋሚዎች. ጠቋሚ ወደ ጠቋሚ. የጠቋሚ አይነት. የጠቋሚ አርቲሜቲክ. የጠቋሚዎች ንጽጽር.

ምልክቶች

ይህ ምናልባት በጠቅላላው ኮርስ ውስጥ በጣም አስቸጋሪ እና በጣም አስፈላጊው ርዕሰ ጉዳይ ነው። ጠቋሚዎችን ካልተረዳ፣ የC ተጨማሪ ጥናት ትርጉም የለሽ ይሆናል። የምልክት ምልክቶች በጣም ቀላል ጽንሰ-ሀሳብ ናቸው, በጣም ምክንያታዊ ናቸው, ግን ለዝርዝር ትኩረት ያስፈልጋቸዋል.

ፍቺ

ኢንዴክስ የማህደረ ትውስታ ቦታን አድራሻ የሚያከማች ተለዋዋጭ ነው። ጠቋሚ, ልክ እንደ ተለዋዋጭ, ዓይነት አለው. ጠቋሚዎችን ለማወጅ አገባብ

<тип> *<имя>;

ለምሳሌ
መንሳፈፍ * a;
ረጅም ረጅም * b;
ከጠቋሚዎች ጋር ለመስራት ሁለቱ ዋና ኦፕሬተሮች የ & አድራሻ ኦፕሬተር እና * የማጣቀሻ ኦፕሬተር ናቸው። አንድ ቀላል ምሳሌ እንመልከት።

#ያካትቱ #ያካትቱ ባዶ ዋና () ( int A = 100; int * p; // የተለዋዋጭ A p = // የተለዋዋጭ A printf አድራሻን ያግኙ ("% p\n", p); // የይዘቱን ውፅዓት ተለዋዋጭ A printf ("% d\n", *p) ጌች ();

እንደገና ኮዱን በጥንቃቄ እንመልከተው

ኢንት A = 100;

የተሰየመ ተለዋዋጭ . በማህደረ ትውስታ ውስጥ በአንዳንድ አድራሻዎች ላይ ይገኛል. ዋጋው 100 በዚህ አድራሻ ተቀምጧል።

ጠቋሚ ዓይነት ፈጠረ int.

አሁን ተለዋዋጭ ገጽየተለዋዋጭ አድራሻን ያከማቻል . የ * ኦፕሬተርን በመጠቀም የተለዋዋጭ ይዘቶችን እናገኛለን .
ይዘቱን ለመለወጥ, ይጻፉ

* ገጽ = 200;

ከዚህ በኋላ እሴቱ ወደ ተመሳሳዩ የማስታወሻ ቦታ ስለሚጠቁም እንዲሁ ተለውጧል. ምንም የተወሳሰበ ነገር የለም።
አሁን ሌላ አስፈላጊ ምሳሌ

#ያካትቱ #ያካትቱ ባዶ ዋና () ( int A = 100፤ int *a = ድርብ B = 2.3፤ ድርብ * b = printf("%d\n" sizeof(A))፤ printf("%d\n", sizeof(a) )) printf("%d\n", sizeof(B));የህትመት መጠን("%d");

ይታያል
4
4
8
4
ምንም እንኳን ተለዋዋጮች የተለያዩ አይነት እና መጠኖች ቢኖራቸውም, ለእነሱ ጠቋሚዎች ተመሳሳይ መጠን አላቸው. በእርግጥ ጠቋሚዎች አድራሻዎችን የሚያከማቹ ከሆነ የኢንቲጀር ዓይነት መሆን አለባቸው። ልክ ነው, ጠቋሚው ራሱ እንደ ተለዋዋጭ ውስጥ ተከማችቷል መጠን_ቲ(እና ptrdiff_t), ይህ እንደ ኢንቲጀር አይነት ባህሪ ነው, ነገር ግን መጠኑ በስርዓቱ ቢት አቅም ላይ የተመሰረተ ነው. በአብዛኛዎቹ ሁኔታዎች በመካከላቸው ምንም ልዩነት የለም. ለምን አንድ ጠቋሚ ዓይነት ያስፈልገዋል?

ጠቋሚ አርቲሜቲክ

በመጀመሪያ፣ ጠቋሚው የማቋረጡ ሥራ (ይዘቶችን በአድራሻ መቀበል) በትክክል እንዲሠራ ዓይነት ይፈልጋል። ጠቋሚው የተለዋዋጭ አድራሻውን ካከማቻል፣ ሙሉውን ተለዋዋጭ ለማግኘት ከዚያ አድራሻ ጀምሮ ምን ያህል ባይት መውሰድ እንዳለቦት ማወቅ አለቦት።
በሁለተኛ ደረጃ ጠቋሚዎች የሂሳብ ስራዎችን ይደግፋሉ. እነሱን ለማከናወን መጠኑን ማወቅ ያስፈልግዎታል.
የ+N ክዋኔው ጠቋሚውን በN*sizeof(አይነት) ባይት ወደፊት ያንቀሳቅሰዋል።
ለምሳሌ, ጠቋሚው int * p; አድራሻውን CC02 ያከማቻል, ከዚያም ከ p += 10 በኋላ; አድራሻውን ያከማቻል CC02 + sizeof(int)*10 = CC02 + 28 = CC2A (ሁሉም ስራዎች በሄክሳዴሲማል ቅርጸት ይከናወናሉ)። ወደ ድርድር መጀመሪያ ጠቋሚ ፈጠርን እንበል። ከዚያም በዚህ ድርድር ውስጥ "መንቀሳቀስ" እንችላለን፣ ወደ ግለሰባዊ አካላት።

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int *p; p = A; printf("%d\n", *p) ; p ++; printf ("%d\n", *p = p + 4;

የአደራደሩን የመጀመሪያ አካል አድራሻ እንዴት እንዳገኘን ልብ ይበሉ

ድርድር በመሠረቱ ጠቋሚ ነው፣ ስለዚህ እና ኦፕሬተሩን መጠቀም አያስፈልግዎትም። ምሳሌውን በተለየ መንገድ ልንጽፈው እንችላለን

የመጀመሪያውን ኤለመንት አድራሻ ያግኙ እና ከእሱ ጋር በተዛመደ ድርድር ውስጥ ይሂዱ።
ከ + እና - ኦፕሬተሮች በተጨማሪ ጠቋሚዎች የንፅፅር ስራዎችን ይደግፋሉ. ሁለት ጠቋሚዎች ሀ እና ለ ካሉን ሀ > ለ ሀ የሚያከማችበት አድራሻ ከያዘው አድራሻ የሚበልጥ ከሆነ ለ.

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int *a, *b; a = b = printf("&A == %p\" n"፣ ሀ)፤ printf("&A ==%p\n"፣ለ)፤ ከሆነ (ሀ< b) { printf("a < b"); } else { printf("b < a"); } getch(); }

ጠቋሚዎቹ እኩል ከሆኑ, ከዚያም ወደ ተመሳሳይ ማህደረ ትውስታ ቦታ ያመለክታሉ.

ጠቋሚ ወደ ጠቋሚ

መረጃ ጠቋሚው የማስታወሻ ቦታን አድራሻ ያከማቻል. ወደ ጠቋሚ ጠቋሚ መፍጠር ይችላሉ, ከዚያ የጠቋሚውን አድራሻ ያከማቻል እና ይዘቱን መድረስ ይችላል. ጠቋሚ ወደ ጠቋሚ ይገለጻል

<тип> **<имя>;

በግልጽ ለማየት እንደሚቻለው ጠቋሚን ወደ ጠቋሚ ወደ ጠቋሚ, እና ወደ ጠቋሚው ጠቋሚ, ወዘተ የመሳሰሉትን ከመፍጠር ምንም ነገር አይከለክልዎትም. ከሁለት-ልኬት እና ባለብዙ-ልኬት ድርድሮች ጋር ስንሰራ ይህንን እንፈልጋለን። በጠቋሚ ወደ ጠቋሚ እንዴት እንደሚሠሩ የሚያሳይ ቀላል ምሳሌ ይኸውና.

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ( int A; int B; int *p; int **pp; A = 10; B = 111; p = pp = printf ("A = %d\n", A); *p = 20; printf("A = %d\n",A);*(*pp) = 30; ("B = %d\n", *p **pp = 333; printf("B = %d",B);

ጠቋሚዎች እና የመውሰድ አይነት

ጠቋሚው አድራሻ ስለሚያከማች ወደ ሌላ ዓይነት መጣል ይችላሉ። ይህ ሊያስፈልግ ይችላል፣ ለምሳሌ፣ ከተለዋዋጭ አካል መውሰድ ከፈለግን ወይም ተለዋዋጭው የምንፈልገውን አይነት እንደሚያከማች ካወቅን።

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ይግለጹ ( int A = 10፤ int *intPtr፤ char *charPtr፤ intPtr = printf("%d\n"፣ *intPtr)፤ printf("---------- -------\n"፤ charPtr = (char*)intPtr፤ printf("%d"፣ *charPtr)፤ charPtr++፤ printf("%d"፣ *charPtr)፤ charPtr++፤ printf ("%d"፣ *charPtr printf("%d"፣ *charPtr);

በዚህ ምሳሌ ውስጥ የመጠን አይነት የመሆኑን እውነታ እንጠቀማለን int 4 ባይት ነው፣ እና ቻር 1 ባይት በዚህ ምክንያት, የመጀመሪያውን ባይት አድራሻ ከተቀበሉ, የቀረውን የቁጥር ባይት ማለፍ እና ይዘታቸውን ማሳየት ይችላሉ.

NULL ጠቋሚ - ባዶ አመልካች

ከመጀመሩ በፊት መረጃ ጠቋሚው ልክ እንደሌላው ተለዋዋጭ ቆሻሻ ያከማቻል። ግን በተመሳሳይ ጊዜ ይህ "ቆሻሻ" ትክክለኛ አድራሻ ሊሆን ይችላል. ለምሳሌ, ጠቋሚ ይኖረናል. መጀመሩን ወይም አለመጀመሩን እንዴት ማወቅ እችላለሁ? በአጠቃላይ, ምንም መንገድ. ይህንን ችግር ለመፍታት፣ የ stdlib ቤተ-መጽሐፍት NULL ማክሮ ተጀመረ።
ጠቋሚን በሚገልጹበት ጊዜ, በተወሰነ እሴት ካልተጀመረ, ከ NULL ጋር እኩል ማድረግ የተለመደ ነው.

Int *ptr = NULL;

በደረጃው መሰረት, በዚህ ሁኔታ ጠቋሚው እኩል እንደሚሆን የተረጋገጠ ነው ባዶ, እና ዜሮ ነው, እና እንደ ቡሊያን እሴት ሊያገለግል ይችላል የውሸት. ምንም እንኳን በአተገባበሩ ላይ በመመስረት ባዶከ 0 ጋር እኩል ላይሆን ይችላል (በትርጉሙ፣ በቢትዊዝ ውክልና ከዜሮ ጋር እኩል አይደለም፣ ለምሳሌ፣ intወይም መንሳፈፍ).
ይህ ማለት በዚህ ጉዳይ ላይ ማለት ነው

Int *ptr = NULL; ከሆነ (ptr == 0) (...)

በጣም ትክክለኛ ክዋኔ, እና ሁኔታ ውስጥ

ኢንት a = 0; ከሆነ (a == NULL) (...)

ባህሪ አልተገለጸም. ያም ማለት ጠቋሚው ከዜሮ ወይም ከ ጋር ሊወዳደር ይችላል ባዶግን አትችልም። ባዶከተለዋዋጭ የኢንቲጀር ወይም ተንሳፋፊ ነጥብ አይነት ጋር ያወዳድሩ።

#ያካትቱ #ያካትቱ #ያካትቱ ባዶ ዋና() ( int *a = NULL፤ ያልተፈረመ ርዝመት፣ i፤ printf("የድርድር ርዝመት አስገባ፡")፤ scanf("%d"፣&ርዝመት)፤ ከሆነ (ርዝመት > 0) (// ማህደረ ትውስታ ሲመደብ // ማህደረ ትውስታ ካልተመደበ፣ ((a = (int*) malloc(ርዝመት *መጠን(int))))!= NULL) ከሆነ (i = 0; i) ይመለሳል።< length; i++) { a[i] = i * i; } } else { printf("Error: can"t allocate memory"); } } //Если переменая была инициализирована, то очищаем её if (a != NULL) { free(a); } getch(); }

ምሳሌዎች

አሁን በጠቋሚዎች የመሥራት አንዳንድ ምሳሌዎች
1. በድርድሩ ውስጥ እንሂድ እና ሁሉንም እኩል የሆኑትን ንጥረ ነገሮች እናገኛለን።

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int even; int evenCounter = 0; int *iter, *end; //iter የድርድር የመጀመሪያ ኤለመንት አድራሻ // መጨረሻ የሚቀጥለውን የድርድር “ንጥረ ነገር” አድራሻ ከመጨረሻው በኋላ ያከማቻል ( iter = A ፣ end = iter )< end; iter++) { if (*iter % 2 == 0) { even = *iter; } } //Выводим задом наперёд чётные числа for (--evenCounter; evenCounter >= 0; evenCounter--) ( printf("%d"፣ even);) getch(); )

2. ኤለመንቶችን ስናስተካክል ብዙውን ጊዜ ማንቀሳቀስ አለብን. አንድ ነገር ብዙ ቦታ የሚይዝ ከሆነ ሁለት ንጥረ ነገሮችን መለዋወጥ በጣም ውድ ይሆናል. በምትኩ፣ ወደ መጀመሪያዎቹ አካላት የጠቋሚዎች ድርድር መፍጠር እና መደርደር ትችላለህ። የጠቋሚዎች መጠን ከዒላማው ድርድር አካላት መጠን ያነሰ ስለሆነ መደርደር ፈጣን ይሆናል። በተጨማሪም, ድርድር አይስተካከልም, ይህም ብዙውን ጊዜ አስፈላጊ ነው.

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ይግለጹ (ድርብ ያልተደራጀ = (1.0፣ 3.0፣ 2.0፣ 4.0፣ 5.0፣ 6.0፣ 8.0፣ 7.0፣ 9.0፣ 0.0)፤ ድርብ * ፒ፣ ድርብ * tmp፣ ቻር ባንዲራ = 1፤ ያልተፈረመ i; printf("ያልተደረደሩ ድርድር\n"); ለ (i = 0; i< SIZE; i++) { printf("%.2f ", unsorted[i]); } printf("\n"); //Сохраняем в массив p адреса элементов for (i = 0; i < SIZE; i++) { p[i] = &unsorted[i]; } do { flag = 0; for (i = 1; i

3. የበለጠ አስደሳች ምሳሌ. የቻር ዓይነት መጠኑ ሁልጊዜ 1 ባይት ስለሆነ የመቀያየር ክዋኔውን ለመተግበር ሊያገለግል ይችላል - የሁለት ተለዋዋጮችን ይዘቶች መለዋወጥ።

እባኮትን አድብሎክን በዚህ ጣቢያ ላይ ያቁሙ።

ጠቋሚ የአንድን ነገር አድራሻ በኮምፒዩተር ማህደረ ትውስታ ውስጥ የሚያከማች ተለዋዋጭ ነው ፣ ለምሳሌ ፣ ሌላ ተለዋዋጭ። የ scanf ተግባርን ስናጠና ከዚህ በፊት ተለዋዋጭ አድራሻዎችን አጋጥሞናል።

ስለዚህ, በቅደም ተከተል እንሂድ. ጠቋሚ መግለጫ።

የጠቋሚ መግለጫ ከተለዋዋጭ መግለጫ የሚለየው ከስሙ በኋላ * ምልክት በመጨመር ብቻ ነው። ምሳሌዎች፡-

ዝርዝር 1.

int * p_g; // ጠቋሚ ወደ ተለዋዋጭ አይነት int ድርብ * p_f; // ወደ ተለዋዋጭ ዓይነት ድርብ አመላካች

የምደባ ኦፕሬተርን በመጠቀም አድራሻን ለጠቋሚ መመደብ ይችላሉ። ምሳሌዎች፡-

ዝርዝር 2.

int n = 100; ድርብ PI = 3.1415926; int * p_k; // ጠቋሚ ወደ ተለዋዋጭ አይነት int ድርብ * p_pi; // ጠቋሚ ወደ ተለዋዋጭ ዓይነት ድርብ p_k = // የተለዋዋጭ አድራሻን ያግኙ እና ለጠቋሚው ይመድቡት p_k p_pi = // የተለዋዋጭ ፒአይ አድራሻን ያግኙ እና ለጠቋሚው p_pi ይመድቡት

የጠቋሚውን ዋጋ በስክሪኑ ላይ ለማሳየት በህትመት ተግባር ውስጥ %p መቀየሪያን መጠቀም ያስፈልግዎታል። ለምሳሌ፥

ዝርዝር 3.

printf("adres peremennoi PI%p\n", p_pi);

በጠቋሚ ውስጥ የተቀመጠውን የተለዋዋጭ አድራሻ በመጠቀም የዚያን ተለዋዋጭ ዋጋ መቀየር ይችላሉ. ይህንን ለማድረግ የማሰናከል ክዋኔውን * ይጠቀሙ። እዚ ምሳሌ እዚ፡ ኣብ ውሽጣዊ ምምሕዳር ምምሕያሽ ምምሕያሽ ምምሕዳርን ምምሕዳርን ምሉእ ብምሉእ ምሉእ ብምሉእ ምሉእ ብምሉእ ምሉእ ብምሉእ ምሉእ ብምሉእ ኣገዳሲ እዩ።

ዝርዝር 4.

#ያካትቱ int ዋና ( ባዶ) ( int a = 100; int * p_a = // የተለዋዋጭ አድራሻን ወደ ጠቋሚ ማተሚያ ያከማቹ ("a = %d\n", a); // የተለዋዋጭ እሴትን ለማግኘት መደበኛ መንገድ printf("a = %d\n"**p_a)፡ a = %d\n", *p_a); መመለስ 0;)

ምስል.1 በጠቋሚ በኩል ተለዋዋጭ መድረስ

በአጠቃላይ * ከጠቋሚዎች ጋር በተያያዘ በሁለት አጋጣሚዎች ጥቅም ላይ ይውላል፡-

  • ጠቋሚን ሲያውጅ, ጠቋሚ መሆኑን ለማሳየት;
  • በጠቋሚው የተጠቆመውን ተለዋዋጭ መድረስ ከፈለግን.

null pointerNULL የሚባልም አለ። ባዶ ጠቋሚ ምንም ነገር አያመለክትም። ጠቋሚዎችን ወደ ዜሮ ለመመለስ ጥቅም ላይ ይውላል. ምሳሌውን ተመልከት።

ዝርዝር 5.

#ያካትቱ int ዋና ( ባዶ) ( int a = 100; int * p_a = // የተለዋዋጭ አድራሻን ወደ ጠቋሚ ማተሚያ ያከማቹ ("a = %d\n", a); // የተለዋዋጭ እሴትን ለማግኘት መደበኛ መንገድ printf("a = %d\n"**p_a)፡ a = %d\n፣ *p_a)፤ printf("%p\n"፣ p_a)፤ p_a = NULL፤ printf("% p\n"፣ p_a);

Fig.2 ጠቋሚውን ወደ ዜሮ እንደገና በማስጀመር ላይ

ወደ ዋና

ሐ ቋንቋ ከምሳሌዎች ጋር

ተግባራት በሲ

በ C ውስጥ ተግባራት ምንድ ናቸው?

በ C ውስጥ ያሉ ተግባራት በአጠቃላይ መርሃ ግብር ውስጥ የተወሰኑ ድርጊቶችን ለማከናወን ጥቅም ላይ ይውላሉ. ፕሮግራመር ራሱ በተግባሮች ውስጥ የትኞቹን ድርጊቶች እንደሚያሳዩ ይወስናል. በተለይ ለተደጋጋሚ ድርጊቶች ተግባራትን ለመጠቀም ምቹ ነው.

በሲ ውስጥ የአንድ ተግባር ቀላል ምሳሌ

በC ውስጥ ያለ ተግባር ምሳሌ፡-

ይህ በጣም ቀላል C ፕሮግራም ነው. በቀላሉ "ተግባራት በ C" የሚለውን መስመር ያትማል. ፕሮግራሙ ዋና ተብሎ የሚጠራ አንድ ነጠላ ተግባር አለው. ይህንን ተግባር በዝርዝር እንመልከተው. በተግባሩ ራስጌ, i.e. በአግባቡ

int የተግባር መመለሻ አይነት ነው;

ዋናው የተግባር ስም ነው;

(ባዶ) የተግባር ነጋሪ እሴቶች ዝርዝር ነው። ባዶ የሚለው ቃል የሚያመለክተው ተግባሩ ምንም ክርክሮች እንደሌለው ነው;

መመለስ የአንድን ተግባር አፈፃፀም የሚያቋርጥ እና የተግባር ውጤቱን ወደተጠራበት ደረጃ የሚመልስ መግለጫ ነው;

EXIT_SUCCESS ከዜሮ ጋር እኩል የሆነ ዋጋ ነው። በ stdlib.h ፋይል ውስጥ ይገለጻል;

ከጭንቅላቱ በኋላ የተግባሩ አካል ፣ በተጠማዘዘ ቅንፎች ውስጥ ተዘግቷል።

{
ያስቀምጣል ("በ C ውስጥ ተግባራት");
መመለስ EXIT_SUCCESS;
}

የተግባር አካል ተብሎ ይጠራል.

ስለዚህ ከተግባር ጋር ስንሰራ የተግባሩን ስም መጠቆም አለብን፣ ለእኛ ዋናው ነው፣ በተግባሩ የተመለሰው የእሴቱ አይነት፣ ለእኛ int ነው፣ በቅንፍ ውስጥ ያሉ ክርክሮችን ዝርዝር ከተከተለ በኋላ የተግባሩ ስም, ምንም ክርክሮች የሉንም, ስለዚህ ባዶ እንጽፋለን, በተግባሩ አካል ውስጥ አንዳንድ ድርጊቶችን እንፈጽማለን (ተግባሩ ለተፈጠረበት ዓላማ) እና የመመለሻ መግለጫውን በመጠቀም የተግባሩን ውጤት እንመልሳለን. በ C ውስጥ ስላለው ተግባራት ማወቅ ያለብዎት መሰረታዊ ነገሮች እዚህ አሉ።

በ C ውስጥ ከአንድ ተግባር ሌላ ተግባር እንዴት መደወል ይቻላል?

በ C ውስጥ የጥሪ ተግባራትን ምሳሌ እንመልከት፡-

እናሮጥነው እና እናገኛለን፡-

ይህ ምሳሌ ሁለት ኢንቲጀር የሚጨምር እና ውጤቱን የሚመልስ ድምር ተግባር ይፈጥራል። የዚህን ተግባር አወቃቀር በዝርዝር እንመልከት.

ድምር ተግባር ራስጌ፡-

ኢንት ድምር (int a, int b)

እዚህ int የተግባሩ መመለሻ አይነት ነው;

ድምር የተግባሩ ስም ነው;

(int a, int b) - ከተግባሩ ስም በኋላ በቅንፍ ውስጥ የክርክሮቹ ዝርዝር አለ-የመጀመሪያው ነጋሪ እሴት int a, ሁለተኛው ነጋሪ እሴት int b ነው. የክርክሩ ስሞች መደበኛ ናቸው, ማለትም. ተግባርን ስንጠራ ሀ እና b የተሰየሙ ተለዋዋጮች እሴቶችን ለዚህ ተግባር እንደ ግቤት መላክ አይጠበቅብንም። በዋናው ተግባር የድምር ተግባርን እንዲህ ብለን እንጠራዋለን፡ ድምር(መ፣ ሠ); ነገር ግን ወደ ተግባሩ የተላለፉት ክርክሮች በተግባሩ ውስጥ ከተገለፀው አይነት ጋር መመሳሰል አስፈላጊ ነው.

በድምሩ ተግባር አካል ውስጥ, i.e. ከተግባር ራስጌ በኋላ በተጠማዘዙ ማሰሪያዎች ውስጥ ፣ የአካባቢ ተለዋዋጭ int c እንፈጥራለን ፣ የፕላስ ለ ድምር ዋጋን እንመድባለን እና በተግባሩ ውጤት በተመላሽ መግለጫ እንመልሰዋለን።

አሁን የድምር ተግባር ከዋናው ተግባር እንዴት እንደሚጠራ እንይ.

ዋናው ተግባር እነሆ፡-

በመጀመሪያ ሁለት ተለዋዋጮችን እንፈጥራለን

int d = 1; int e = 2;

እንደ ነጋሪ እሴት ወደ ድምር ተግባር እናስተላልፋቸዋለን።

int f = ድምር (d, e);

ዋጋው የድምር ተግባር ውጤት ይሆናል, ማለትም. ድምር ተግባር ብለን እንጠራዋለን፣ እሱም ኢንት እሴትን የሚመልስ፣ ለተለዋዋጭ የምንሰጠው f. d እና f እንደ ክርክሮች እናልፋለን. ነገር ግን በተግባሩ ራስጌ ድምር

ኢንት ድምር (int a, int b)

ክርክሮቹ ሀ እና ለ ይባላሉ፣ ለምንድነው d እና f እናልፋለን? ምክንያቱም መደበኛ ክርክሮች በተግባሩ ራስጌ ውስጥ ተጽፈዋል፣ ማለትም. የክርክሩ ስሞች አስፈላጊ አይደሉም፣ ግን ዓይነታቸው አስፈላጊ ናቸው። ድምር ተግባር የ int አይነት ሁለቱም ነጋሪ እሴቶች አሉት፣ይህም ማለት ይህንን ተግባር ሲጠሩት ሁለት ነጋሪ እሴቶችን ከማንኛውም ስሞች ጋር ማለፍ አለብዎት ማለት ነው።

አንድ ተጨማሪ ስውር። አንድ ተግባር መጀመሪያ ከመጠራቱ በፊት መታወጅ አለበት። በምሳሌአችን, ይህ የሆነው ይኸው ነው: በመጀመሪያ ድምር ተግባሩ ይገለጻል, ከዚያም ከዋናው ተግባር እንጠራዋለን. አንድ ተግባር ከተጠራበት ቦታ በኋላ ከተገለጸ, የተግባር ፕሮቶታይፕ ጥቅም ላይ መዋል አለበት.

የተግባር ምሳሌ በሲ

በ C ውስጥ የአንድ ተግባር ምሳሌን እንመልከት፡-

በዚህ ምሳሌ, ድምር ተግባሩ በዋናው ተግባር ውስጥ ከተጠራበት በታች ይገለጻል.

በዚህ አጋጣሚ የድምር ተግባር ፕሮቶታይፕ መጠቀም ያስፈልግዎታል። የእኛ ምሳሌ ከዋናው ተግባር በላይ ተገልጿል፡-

int ድምር (int a, int b);

ፕሮቶታይፕ በሰሚኮሎን የሚጨርስ የተግባር ራስጌ ነው። ፕሮቶታይፕ ከዚህ በታች የሚገለፅ ተግባር መግለጫ ነው። በትክክል ያደረግነው ይኸው ነው፡ የተግባር ፕሮቶታይፕ አውጀናል።

int f = ድምር (d, e);

እና ከዋናው ተግባር በታች ቀደም ሲል በአምሳያው ውስጥ የታወጀውን ድምር ተግባርን እንገልፃለን-

በ C ውስጥ ያለው የተግባር መግለጫ በ C ውስጥ ካለው የተግባር ትርጉም እንዴት ይለያል?

የተግባር ፕሮቶታይፕ ስንጽፍ፣ ለምሳሌ እንደዚህ፡-

int ድምር (int a, int b);

ከዚያም አንድ ተግባር እናውጃለን.

እና አንድ ተግባርን ስንተገብር, ማለትም. ርዕሱን ብቻ ሳይሆን የተግባሩን አካል ጭምር እንጽፋለን ለምሳሌ፡-

ከዚያም አንድ ተግባር እንገልጻለን.

የመመለሻ መግለጫ

የመመለሻ መግለጫው በ C ውስጥ ያለውን ተግባር ያጠናቅቃል እና የሥራውን ውጤት ወደ ጥሪ ቦታ ይመልሳል። ለምሳሌ፥

ይህንን ተግባር ማቃለል ይቻላል፡-

እዚህ የመመለሻ መግለጫው የድምሩ a + b ዋጋ ይመልሳል።

በአንድ ተግባር ውስጥ በርካታ የመመለሻ መግለጫዎች ሊኖሩ ይችላሉ። ለምሳሌ፥

በምሳሌው ውስጥ የክርክር ሀ እሴት ከሁለት በላይ ከሆነ ተግባሩ ዜሮ (የመጀመሪያው ጉዳይ) እና ከአስተያየቱ በታች ያለውን ሁሉ ይመልሳል "// የመጀመሪያ ጉዳይ;" አይፈጸምም.

ጠቋሚዎች በ C ቋንቋ

ሀ ከሁለት በታች ከሆነ ግን b ከዜሮ በታች ከሆነ ተግባሩ ስራውን እና ከአስተያየቱ በታች ያለውን ሁሉ ያጠናቅቃል "// ሁለተኛ ጉዳይ;" አይፈጸምም.

እና ሁለቱም የቀድሞ ሁኔታዎች ካልተሟሉ ብቻ የፕሮግራሙ አፈፃፀም የመጨረሻውን የመመለሻ መግለጫ ይደርሳል እና ድምር a + b ይመለሳል።

የተግባር ነጋሪ እሴቶችን በእሴት ማለፍ

ክርክሮች በዋጋ ወደ C ተግባር ሊተላለፉ ይችላሉ። ለምሳሌ፥

በምሳሌው ውስጥ በዋናው ተግባር ውስጥ ተለዋዋጭ int d = 10 እንፈጥራለን. ይህንን ተለዋዋጭ እሴት ወደ ድምር (መ) ተግባር እናስተላልፋለን. በድምር ተግባር ውስጥ, የተለዋዋጭ እሴት በ 5 ጨምሯል. ነገር ግን በዋና ተግባር ውስጥ, d ዋጋ አይለወጥም, ምክንያቱም በእሴት ተላልፏል. ይህ ማለት የተለዋዋጭው እሴት አልፏል, ተለዋዋጭው ራሱ አይደለም. ይህም በፕሮግራሙ ውጤት ተረጋግጧል፡-

እነዚያ። ከድምር ተግባር ከተመለሰ በኋላ የዲ ዋጋ አልተለወጠም, በጥቅሉ ውስጥ ግን ተቀይሯል.

የ C ተግባር አመልካቾችን ማለፍ

ጠቋሚውን ከተለዋዋጭ እሴት ይልቅ እንደ ነጋሪ እሴት ወደ ተግባር ካሳለፉት የዚህ ተለዋዋጭ እሴት ሊለወጥ ይችላል። ለምሳሌ ፣ ፕሮግራሙን ከቀዳሚው ክፍል እንወስዳለን ፣ ትንሽ እንቀይረው-

በዚህ የፕሮግራሙ ስሪት ውስጥ ነጋሪ እሴትን በእሴት ከማለፍ ወደ ጠቋሚ ወደ ተለዋዋጭ ማስተላለፍ ቀየርኩ። ይህንን ነጥብ ጠለቅ ብለን እንመልከተው።

printf (" ድምር = %d \n", ድምር (&d));

ወደ ድምር ተግባር የተላለፈው የተለዋዋጭ ዲ እሴት አይደለም፣ ከ10 ጋር እኩል ነው፣ ነገር ግን የዚህ ተለዋዋጭ አድራሻ፣ እንደዚህ ያለ፡-

አሁን የድምር ተግባሩን እንመልከት፡-

የእሱ መከራከሪያ ወደ int ጠቋሚ ነው. ጠቋሚ እሴቱ የአንዳንድ ነገሮች አድራሻ የሆነ ተለዋዋጭ መሆኑን እናውቃለን። የተለዋዋጭ ዲ አድራሻ ወደ ድምር ተግባር ይላካል፡-

በውስጥ ድምር፣ ጠቋሚው int *a ተወስኗል። ይህ ከጠቋሚው ወደ ተለዋዋጭ እራሱ እንድንሸጋገር ያስችለናል, ወደ እሱ ጠቋሚያችን. እና በእኛ ሁኔታ ይህ ተለዋዋጭ ነው d, i.e. አገላለጽ

ከመግለጫው ጋር እኩል ነው

ውጤት፡ ድምር ተግባር የተለዋዋጭውን እሴት ይለውጣል d፡

በዚህ ጊዜ ከድምሩ ከተመለሰ በኋላ የ d ዋጋ ይለወጣል, ይህም ነጋሪቱን በእሴት ስናልፍ በቀደመው አንቀጽ ላይ አልታየም.

C/C++ በግርዶሽ

በግርዶሽ ውስጥ ለዚህ ጽሑፍ ሁሉንም ምሳሌዎች ሠራሁ። በ Eclipse ውስጥ ከ C/C++ ጋር እንዴት እንደሚሠራ እዚህ ይገኛል። በተለየ አካባቢ ውስጥ የሚሰሩ ከሆነ, ምሳሌዎች እዚያም ይሰራሉ.

መለያዎች: ሲ ጠቋሚዎች. ጠቋሚ ወደ ጠቋሚ. የጠቋሚ አይነት. የጠቋሚ አርቲሜቲክ. የጠቋሚዎች ንጽጽር.

ምልክቶች

ይህ ምናልባት በጠቅላላው ኮርስ ውስጥ በጣም አስቸጋሪ እና በጣም አስፈላጊው ርዕሰ ጉዳይ ነው። አመላካቾችን ካልተረዳ፣ የC ተጨማሪ ጥናት ትርጉም የለሽ ይሆናል። የምልክት ምልክቶች በጣም ቀላል ጽንሰ-ሀሳብ ናቸው, በጣም ምክንያታዊ ናቸው, ነገር ግን ለዝርዝር ትኩረት ያስፈልጋቸዋል.

ፍቺ

ጠቋሚ የማህደረ ትውስታ ቦታ አድራሻን የሚያከማች ተለዋዋጭ ነው።

ርዕስ 7. ጠቋሚዎች በሲ.

ጠቋሚ, ልክ እንደ ተለዋዋጭ, ዓይነት አለው. ጠቋሚዎችን ለማወጅ አገባብ

<тип> *<имя>;

ለምሳሌ
ከጠቋሚዎች ጋር ለመስራት ሁለቱ ዋና ኦፕሬተሮች የ & አድራሻ ኦፕሬተር እና * የማጣቀሻ ኦፕሬተር ናቸው። አንድ ቀላል ምሳሌ እንመልከት።

#ያካትቱ #ያካትቱ ባዶ ዋና () ( int A = 100; int * p; // የተለዋዋጭ A p = // የተለዋዋጭ A printf አድራሻን ያግኙ ("% p\n", p); // የይዘቱን ውፅዓት ተለዋዋጭ A printf ("% d\n", *p) የተለዋዋጭውን ይዘት ይቀይሩ A *p = 200;

እንደገና ኮዱን በጥንቃቄ እንመልከተው

የተሰየመ ተለዋዋጭ . በማህደረ ትውስታ ውስጥ በአንዳንድ አድራሻዎች ላይ ይገኛል. ዋጋው 100 በዚህ አድራሻ ተቀምጧል።

ጠቋሚ ዓይነት ፈጠረ int.

አሁን ተለዋዋጭ ገጽየተለዋዋጭ አድራሻን ያከማቻል . የ * ኦፕሬተርን በመጠቀም የተለዋዋጭ ይዘቶችን እናገኛለን .
ይዘቱን ለመለወጥ, ይጻፉ

ከዚህ በኋላ እሴቱ ወደ ተመሳሳዩ የማስታወሻ ቦታ ስለሚጠቁም እንዲሁ ተለውጧል. ምንም የተወሳሰበ ነገር የለም።
አሁን ሌላ አስፈላጊ ምሳሌ

#ያካትቱ #ያካትቱ ባዶ ዋና () ( int A = 100፤ int *a = ድርብ B = 2.3፤ ድርብ * b = printf("%d\n" sizeof(A))፤ printf("%d\n", sizeof(a) )) printf("%d\n", sizeof(B)) ;

ይታያል
ምንም እንኳን ተለዋዋጮች የተለያዩ አይነት እና መጠኖች ቢኖራቸውም, ለእነሱ ጠቋሚዎች ተመሳሳይ መጠን አላቸው. በእርግጥ ጠቋሚዎች አድራሻዎችን የሚያከማቹ ከሆነ የኢንቲጀር ዓይነት መሆን አለባቸው። ልክ ነው, ጠቋሚው ራሱ እንደ ተለዋዋጭ ውስጥ ተከማችቷል መጠን_ቲ(እና ptrdiff_t), ይህ እንደ ኢንቲጀር አይነት ባህሪ ነው, ነገር ግን መጠኑ በስርዓቱ ቢት አቅም ላይ የተመሰረተ ነው. በአብዛኛዎቹ ሁኔታዎች በመካከላቸው ምንም ልዩነት የለም. ለምን አንድ ጠቋሚ ዓይነት ያስፈልገዋል?

ጠቋሚ አርቲሜቲክ

በመጀመሪያ፣ ጠቋሚው የማቋረጡ ስራ (ይዘቱን በአድራሻ ማግኘት) በትክክል እንዲሰራ አይነት ያስፈልገዋል። ጠቋሚው የተለዋዋጭ አድራሻውን ካከማቻል፣ ሙሉውን ተለዋዋጭ ለማግኘት ከዚያ አድራሻ ጀምሮ ምን ያህል ባይት መውሰድ እንዳለቦት ማወቅ አለቦት።
በሁለተኛ ደረጃ ጠቋሚዎች የሂሳብ ስራዎችን ይደግፋሉ.

እነሱን ለማከናወን መጠኑን ማወቅ ያስፈልግዎታል.
ክዋኔው ጠቋሚውን በባይት ወደፊት ያንቀሳቅሰዋል.
ለምሳሌ, ጠቋሚው int * p; አድራሻውን CC02 ያከማቻል, ከዚያም ከ p += 10 በኋላ; አድራሻውን ያከማቻል CC02 + sizeof(int)*10 = CC02 + 28 = CC2A (ሁሉም ስራዎች በሄክሳዴሲማል ቅርጸት ይከናወናሉ)። ወደ ድርድር መጀመሪያ ጠቋሚ ፈጠርን እንበል። ከዚያ ወደ ግለሰባዊ አካላት በመድረስ በዚህ ድርድር "መንቀሳቀስ" እንችላለን።

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int *p; p = A; printf("%d\n", *p) ; p ++; printf ("%d\n", *p = p + 4;

የአደራደሩን የመጀመሪያ አካል አድራሻ እንዴት እንዳገኘን ልብ ይበሉ

ድርድር በመሠረቱ ጠቋሚ ነው፣ ስለዚህ እና ኦፕሬተሩን መጠቀም አያስፈልግዎትም። ምሳሌውን በተለየ መንገድ ልንጽፈው እንችላለን

የመጀመሪያውን ኤለመንት አድራሻ ያግኙ እና ከእሱ ጋር በተዛመደ ድርድር ውስጥ ይሂዱ።
ከ + እና - ኦፕሬተሮች በተጨማሪ ጠቋሚዎች የንፅፅር ስራዎችን ይደግፋሉ. ሁለት ጠቋሚዎች ሀ እና ለ ካሉን ሀ > ለ ሀ የሚያከማችበት አድራሻ ከያዘው አድራሻ የሚበልጥ ከሆነ ለ.

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int *a, *b; a = b = printf("&A == %p\" n"፣ ሀ)፤ printf("&A ==%p\n"፣b)< b) { printf(«a < b»); } else { printf(«b < a»); } getch(); }

ጠቋሚዎቹ እኩል ከሆኑ, ከዚያም ወደ ተመሳሳይ ማህደረ ትውስታ ቦታ ያመለክታሉ.

ጠቋሚ ወደ ጠቋሚ

ጠቋሚ የማህደረ ትውስታ ቦታ አድራሻን ያከማቻል። ወደ ጠቋሚ ጠቋሚ መፍጠር ይችላሉ, ከዚያ የጠቋሚውን አድራሻ ያከማቻል እና ይዘቱን መድረስ ይችላል. ጠቋሚ ወደ ጠቋሚ ይገለጻል

<тип> **<имя>;

በግልጽ ለማየት እንደሚቻለው ጠቋሚን ወደ ጠቋሚ ወደ ጠቋሚ, እና ወደ ጠቋሚው ጠቋሚ, ወዘተ የመሳሰሉትን ከመፍጠር ምንም ነገር አይከለክልዎትም. ከሁለት-ልኬት እና ባለብዙ-ልኬት ድርድሮች ጋር ስንሰራ ይህንን እንፈልጋለን። በጠቋሚ ወደ ጠቋሚ እንዴት እንደሚሠሩ የሚያሳይ ቀላል ምሳሌ ይኸውና.

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ( int A; int B; int *p; int **pp; A = 10; B = 111; p = pp = printf ("A = %d\n", A); *p = 20; printf ("A = %d\n", *p **pp = 333; ለ);

ጠቋሚዎች እና የመውሰድ አይነት

ጠቋሚው አድራሻ ስለሚያከማች ወደ ሌላ ዓይነት መጣል ይችላሉ።

ይህ ሊያስፈልግ ይችላል፣ ለምሳሌ፣ ከተለዋዋጭ አካል መውሰድ ከፈለግን ወይም ተለዋዋጭው የምንፈልገውን አይነት እንደሚያከማች ካወቅን።

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ይግለጹ ( int A = 10፤ int *intPtr; char *charPtr; intPtr = printf("%d\n", *intPtr); printf ("———————\n" charPtr = (char*)intPtr; printf("%d"፣*charPtr++);

በዚህ ምሳሌ ውስጥ የመጠን አይነት የመሆኑን እውነታ እንጠቀማለን int 4 ባይት ነው፣ እና ቻር 1 ባይት በዚህ ምክንያት, የመጀመሪያውን ባይት አድራሻ ከተቀበሉ, የቀረውን የቁጥር ባይት ማለፍ እና ይዘታቸውን ማሳየት ይችላሉ.

NULL ጠቋሚ - ባዶ አመልካች

ከመጀመሩ በፊት ጠቋሚ ልክ እንደሌላው ተለዋዋጭ ቆሻሻ ያከማቻል። ግን በተመሳሳይ ጊዜ ይህ "ቆሻሻ" ትክክለኛ አድራሻ ሊሆን ይችላል. ለምሳሌ, ጠቋሚ ይኖረናል. መጀመሩን ወይም አለመጀመሩን እንዴት ማወቅ እችላለሁ? በአጠቃላይ, ምንም መንገድ. ይህንን ችግር ለመፍታት፣ የ stdlib ቤተ-መጽሐፍት NULL ማክሮ ተጀመረ።
ጠቋሚን በሚገልጹበት ጊዜ, በተወሰነ እሴት ካልተጀመረ, ከ NULL ጋር እኩል ማድረግ የተለመደ ነው.

int *ptr = NULL;

በደረጃው መሰረት, በዚህ ሁኔታ ጠቋሚው እኩል እንደሚሆን የተረጋገጠ ነው ባዶ, እና ዜሮ ነው, እና እንደ ቡሊያን እሴት ሊያገለግል ይችላል የውሸት. ምንም እንኳን በአተገባበሩ ላይ በመመስረት ባዶከ 0 ጋር እኩል ላይሆን ይችላል (በትርጉሙ፣ በቢትዊዝ ውክልና ከዜሮ ጋር እኩል አይደለም፣ ለምሳሌ፣ intወይም መንሳፈፍ).
ይህ ማለት በዚህ ጉዳይ ላይ ማለት ነው

int *ptr = NULL; ከሆነ (ptr == 0) (…)

በጣም ትክክለኛ ክዋኔ, እና ሁኔታ ውስጥ

int a = 0; ከሆነ (a == NULL) (…)

ባህሪ አልተገለጸም. ያም ማለት ጠቋሚው ከዜሮ ወይም ከ ጋር ሊወዳደር ይችላል ባዶግን አትችልም። ባዶከተለዋዋጭ የኢንቲጀር ወይም ተንሳፋፊ ነጥብ አይነት ጋር ያወዳድሩ።

#ያካትቱ #ያካትቱ #ያካትቱ ባዶ ዋና() ( int *a = NULL፤ ያልተፈረመ ርዝመት፣ i፤ printf("የድርድር ርዝመት አስገባ፡")፤ scanf("%d"፣&ርዝመት)፤ ከሆነ (ርዝመት > 0) (// ማህደረ ትውስታ ሲመደብ // ማህደረ ትውስታ ካልተመደበ፣ ((a = (int*) malloc(ርዝመት *መጠን(int))))!= NULL) ከሆነ (i = 0; i) ይመለሳል።< length; i++) { a[i] = i * i; } } else { printf(«Error: can’t allocate memory»); } } //Если переменая была инициализирована, то очищаем её if (a != NULL) { free(a); } getch(); }

ምሳሌዎች

አሁን በጠቋሚዎች የመሥራት አንዳንድ ምሳሌዎች
1. በድርድሩ ውስጥ እንሂድ እና ሁሉንም እኩል የሆኑትን ንጥረ ነገሮች እናገኛለን።

#ያካትቱ #ያካትቱ ባዶ ዋና () (int A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int even; int evenCounter = 0; int *iter, *end; //iter የድርድር የመጀመሪያ ኤለመንት አድራሻ // መጨረሻ የሚቀጥለውን የድርድር “ንጥረ ነገር” አድራሻ ከመጨረሻው በኋላ ያከማቻል ( iter = A ፣ end = iter )< end; iter++) { if (*iter % 2 == 0) { even = *iter; } } //Выводим задом наперёд чётные числа for (—evenCounter; evenCounter >= 0; evenCounter—) ( printf("%d "፣ even);) getch(); )

2. ኤለመንቶችን ስናስተካክል ብዙውን ጊዜ ማንቀሳቀስ አለብን. አንድ ነገር ብዙ ቦታ የሚይዝ ከሆነ ሁለት ንጥረ ነገሮችን መለዋወጥ በጣም ውድ ይሆናል. በምትኩ፣ ወደ መጀመሪያዎቹ አካላት የጠቋሚዎች ድርድር መፍጠር እና መደርደር ትችላለህ። የጠቋሚዎች መጠን ከዒላማው ድርድር አካላት መጠን ያነሰ ስለሆነ መደርደር ፈጣን ይሆናል። በተጨማሪም, ድርድር አይስተካከልም, ይህም ብዙውን ጊዜ አስፈላጊ ነው.

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ይግለጹ (ድርብ ያልተደራጀ = (1.0፣ 3.0፣ 2.0፣ 4.0፣ 5.0፣ 6.0፣ 8.0፣ 7.0፣ 9.0፣ 0.0)፤ ድርብ * ፒ፣ ድርብ * tmp፣ ቻር ባንዲራ = 1፤ ያልተፈረመ i; printf("ያልተደረደሩ ድርድር\n"); ለ (i = 0; i< SIZE; i++) { printf(«%.2f «, unsorted[i]); } printf(«\n»); //Сохраняем в массив p адреса элементов for (i = 0; i < SIZE; i++) { p[i] = &unsorted[i]; } do { flag = 0; for (i = 1; i

3. የበለጠ አስደሳች ምሳሌ. የቻር ዓይነት መጠኑ ሁልጊዜ 1 ባይት ስለሆነ የመቀያየር ክዋኔውን ለመተግበር ሊያገለግል ይችላል - የሁለት ተለዋዋጮችን ይዘቶች መለዋወጥ።

#ያካትቱ #ያካትቱ #ያካትቱ ባዶ ዋና () ( int ርዝመት፤ ቻር * p1፣ *p2፤ ቻር tmp፤ ተንሳፋፊ a = 5.0f፤ ተንሳፋፊ b = 3.0f፤ printf("a = % 3f\n", a)፤ printf ("b = %3f\n"፣ b)፤ p1 = (ቻር*) p2 = (ቻር*) // ስንት ባይት እንደሚንቀሳቀስ ይወቁ = የመጠን (ተንሳፋፊ) (// የተለዋዋጮችን ይዘት ይቀይሩ ባይት ባይት = * p1; * p1 = * p2; // ወደ ፊት መሄድን አይርሱ p1++; printf ("a = % 3f\n", a);

በዚህ ምሳሌ, የተለዋዋጮችን አይነት መቀየር ይችላሉ እና ላይ ድርብወይም ሌላ (በውጤቱ እና በመደወል ላይ ካለው ተዛማጅ ለውጥ ጋር የመጠን), አሁንም የሁለት ተለዋዋጮች ባይት እንለዋወጣለን።

4. #include ጠቋሚን በመጠቀም በተጠቃሚው የገባውን ሕብረቁምፊ ርዝመት ይፈልጉ #ያካትቱ ባዶ ዋና () ( ቻር ቋት፤ ቻር * ፒ፤ ያልተፈረመበት ርዝመት = 0፤ ስካንፍ("%127s"፣ ቋት)፤ p = ቋት፤ ሳለ (*p!= '\0') (p++፤ ርዝመት++፤) printf() "ርዝመት = %d", ርዝመት ();

ለኮዱ ክፍል ትኩረት ይስጡ

ሳለ (*p!= ‘\0’) ( p++; ርዝመት++;)

እንደገና ሊጻፍ ይችላል

ሳለ (*p!= 0) ( p++; ርዝመት++;) ወይም ጊዜ (*p) ( p++; ርዝመት++;)

ወይም በሁኔታው ላይ ያለውን ጭማሪ በማስወገድ

ሳለ (*p++) (ርዝመት++;)

ru-Cyrl18-የመማሪያ Sypachev [ኢሜል የተጠበቀ]

ጠቋሚየሌላ ተለዋዋጭ አድራሻን የሚያከማች ልዩ ተለዋዋጭ ነው. ጠቋሚው እንደሚከተለው ተገልጿል. ዓይነት * ተለዋዋጭ;የት ዓይነት- ማንኛውም ትክክለኛ ቀላል ወይም ውሁድ መሠረት ጠቋሚ ዓይነት።

ለምሳሌ፣ መደበኛ ተለዋዋጭ ታውጇል እንበል int t;መግለጫ እና ጅምር int* p=የሚከተለውን ማለት ነው። በተለዋዋጭ ገጽየሚቀመጠው በፕሮግራሙ የሚሰራው ኢንቲጀር (የተማሪ ክፍል፣የተመረቱ ምርቶች ብዛት፣ወዘተ) ሳይሆን የተገለጸው አይነት (ኢንቲጀር) መረጃ የያዘው የሕዋስ አድራሻ ነው። አድራሻ ስንል ለተለዋዋጭ የተመደበው የ RAM ክፍል የመጀመሪያ ባይት ቁጥር ማለታችን ነው። ጠቋሚ ላልሆኑ ተለዋዋጮች፣ ያለ ተጨማሪ መግለጫ፣ አድራሻው በስርዓቱ ይታወሳል እና በመጠቀም ማግኘት ይቻላል & (deaddressing) ክወናዎችለምሳሌ , &t.ይህ ያልተለመደ ክዋኔ፣ አንዳንድ ጊዜ "አድራሻ መውሰድ" ተብሎ የሚጠራው ከተለዋዋጭ እሴት ጋር ምንም አያደርግም። .

ከመጀመሪያው አጠቃቀም በፊት ጠቋሚው ተለዋዋጭ መሆን አለበት ተጀመረ።የጠቋሚውን ዋጋ እስክንገልጽ ድረስ፣ በዘፈቀደ የማህደረ ትውስታ ውስጥ የሆነን ነገር ያመለክታል፣ እና አጠቃቀሙ ወደማይታወቅ ውጤት ሊያመራ ይችላል።

አንደኛው ዘዴ ከላይ ይታያል እና በተለዋዋጭ ውስጥ ማለት ነው ገጽየሕዋስ አድራሻ ተቀምጧል . ያንን መረዳት አስፈላጊ ነው int* p=ተመጣጣኝ int * p; p=&t; ግን አይደለም *p=&t; ይህ የመማር ጠቋሚዎች የመጀመሪያ ደረጃ ችግሮች አንዱ ነው። ተመሳሳይ ምልክት “በመሆኑ ይህ ርዕስ የበለጠ የተወሳሰበ ነው። & ” የማጣቀሻ ዓይነት ተለዋዋጭ ሲያውጅ ጥቅም ላይ ይውላል።

ጠቋሚዎች በሲ.

እዚህ ይህ ምልክት ይገልፃል አድራሻ እየወሰደ ሥራለተለዋዋጭ እና ከማጣቀሻው አይነት ጋር ምንም ግንኙነት የለውም.

ጠቋሚዎችን ሲያውጅ የቦታዎች አቀማመጥ ነፃ መሆኑን ልብ ይበሉ። የሚከተሉት ግቤቶች እንዲሁ ተቀባይነት አላቸው፡ int * p= & t; int *p=በአንቀጹ መጀመሪያ ላይ ለግቤቶች ምርጫ መሰጠት አለበት ፣ ከዚያ የመረጃ ጠቋሚውን ትርጉም ለመረዳት ቀላል ነው። ተለዋዋጭ ታውጇል። ገጽ, ግን አይደለም *ገጽ, እና, በተጨማሪ, ዓይነት ነው ኢንት*, ግን አይደለም int.

ብዙ ጠቋሚዎች በአንድ ጊዜ ከታወጁ፣ “*” ምልክቱ ከእያንዳንዱ ተለዋዋጭ በፊት መፃፍ አለበት፡- ተንሳፋፊ * q1, *q2;

አድራሻው ያለበት የሕዋስ ይዘት ገጽ, በፕሮግራሙ ጽሑፍ ውስጥ በ ስራዎች ማገድ . የጠቋሚ ተለዋዋጭ ሲያውጅ ተመሳሳይ የ"*" ምልክት ይጠቀማል። ይህ ያልተለመደ ክዋኔ በተጠቀሰው አድራሻ ላይ የሚገኘውን የተለዋዋጭ እሴት ይመልሳል. ለዛ ነው *ገጽአድራሻው በጠቋሚ ተለዋዋጭ በሆነ ሕዋስ ውስጥ በፕሮግራሙ የሚሰራ ኢንቲጀር ነው። ገጽ. አጀማመርን ከግምት ውስጥ በማስገባት ( p = &t) *ገጽእና - ይህ ተመሳሳይ ትርጉም ነው. ይህ ማለት ከተጠቀሙበት ማለት ነው cin>>t;ለምሳሌ ቁጥር 2ን እናስገባና እንፈጽም። *ገጽ=5; ወይም *p=*p*5;ከዚያ እሴቱ ይለወጣል ምንም እንኳን ግልጽ የሆነ ለውጥ ያለ ቢመስልም. ስለዚህ ኦፕሬተሩ ኮት<< t; ቁጥር 10 (2*5) ያወጣል። እና በተቃራኒው መለወጥ (ለምሳሌ፣ t++;), በዚህም ዋጋውን እንለውጣለን *ገጽ.በመጠቀም ኮት<<(*p); እናተም 11.

ከላይ ያለውን እንደሚከተለው እንጠቁማለን.

ገጽ(ወይም &t) *ገጽ(ወይም )

"የግራ ሬክታንግል" (የማህደረ ትውስታ ሕዋስ) አድራሻውን ይይዛል, እና "የቀኝ" ሕዋስ እየተሰራ ያለውን ኢንቲጀር ይዟል.

እዚህ ላይ የተብራሩት የ"&" እና "*" ስራዎች ያልተለመዱ እና ከተመሳሳይ ሁለትዮሽ ኦፕሬሽኖች "ቢት እና" እና አርቲሜቲክ ማባዛት የበለጠ ቅድሚያ አላቸው።

*ገጽተመሳሳይ ክዋኔዎች የሚገለጹት ለተጠቀሰው ዓይነት ተለዋዋጭ ነው, ግን ለኢንቲጀር. ስለዚህ፡ ለምሳሌ፡ የሚከተሉት ኦፕሬተሮች ተቀባይነት አላቸው፡ ሀ) ሲን>>(*p);ለ) int r; r=*p*2;ሐ) ከሆነ (*p%2)…;መ) ኮት<<(*p);.

እንዲሁም የጠቋሚ ተለዋዋጭ ዋጋን ማሳየት ይችላሉ. ኮት<አድራሻውን በሄክሳዴሲማል ምልክት ያሳያል። ነገር ግን፣ ተመሳሳይ ፕሮግራም በተደጋጋሚ ሲተገበር የግድ ተመሳሳይ አይሆንም።

⇐ ቀዳሚ 567891011121314ቀጣይ ⇒

የታተመበት ቀን: 2015-02-18; አንብብ፡ 526 | የገጽ የቅጂ መብት ጥሰት

Studopedia.org - Studopedia.Org - 2014-2018 (0.001 ዎች)…

- ለሠራተኛው ጠቋሚ። ለዚህ ጠቋሚ አንድ የተመደበ ነገርን ወይም በእርስዎ ጉዳይ ላይ ብዙ (ከድርድር አገባብ ጋር) መመደብ ይችላሉ። ስለዚህ የሰራተኞች ስብስብን ያመለክታል.

ይህን ጠቋሚ ዋቢ አድርገውታል።

ማስታወሻዎች እና ግምቶች

ወደ ብዙ (በርካታ) ሠራተኞች ስለሚያመለክት፣ ወደ መጀመሪያው ግቤትም ይጠቁማል። ከዚያ አሁንም የሚቻለውን የኢንቲጀር አባል ተለዋዋጭ ያገኙታል። ነገር ግን የድርድር ኢንዴክስ ኦፕሬተርን () በኢንቲጀር ዋጋ ለመጠቀም ትሞክራለህ፣ ይህ የማይቻል ነው።

የተመደበለትን ድርድር አባል ተለዋዋጭ ለማግኘት ፈልገህ ይሆናል። ስለዚህ ይህንን ማሽከርከር ያስፈልግዎታል በመጀመሪያ የድርድር ኢንዴክስ ኦፕሬተርን ይጠቀሙ ፣ ከዚያ የዚያን የተወሰነ ሰራተኛ አባል ያግኙ።

በዝቅተኛ ቃላቶች ማለት፡- ጠቋሚን ውሰድ፣ የተጠቀሰውን አይነት መጠን ጨምር (ወደ -th መግቢያው እንዲጠቁም) እና አድራሻውን መሰረዝ ማለት ይህ ማለት ሰራተኛው በ -th ኢንዴክስ (ግን ውስጥ አይደለም) ጠቋሚው)።

ከዚያ የሰራተኛውን አባል ማግኘት ይፈልጋሉ።

አሁንም ጠቋሚ ከሆነ የቀስት ኦፕሬተርን መጠቀም ያስፈልግሃል ነገር ግን የድርድር መረጃ ጠቋሚውን () ስለተጠቀምክ አስቀድመህ አንስተውታል፣ ከዚያ የነጥብ ኦፕሬተር ትክክል ነው፡

ሲ ሲማሩ ጀማሪዎች ብዙውን ጊዜ ከጠቋሚዎች ጋር የተያያዙ ጥያቄዎች አሏቸው፣ ሁሉም ሰው በግምት ተመሳሳይ ጥያቄዎች ያሉት ይመስለኛል፣ ስለዚህ ለእኔ የተነሱትን እገልጻለሁ።

ጠቋሚ ምንድነው?

ለምንድነው ሁልጊዜ የተጻፈው "አይነት ጠቋሚ" እና የአመልካች አይነት ምንድን ነው uint16_tከአይነት ጠቋሚ የተለየ uint8_t?

እና ለማንኛውም መረጃ ጠቋሚውን ማን አመጣው?

ለእነዚህ ጥያቄዎች መልስ ከመስጠቱ በፊት ጠቋሚ ምን እንደሆነ እናስታውስ።
ጠቋሚ የአንዳንድ የውሂብ አካል አድራሻ (ተለዋዋጭ፣ ቋሚ፣ ተግባር፣ መዋቅር) የያዘ ተለዋዋጭ ነው።

ተለዋዋጭን እንደ ጠቋሚ ለማወጅ ከስሙ ጋር መቅደም አለብዎት * , እና የተለዋዋጭ አድራሻን ለማግኘት ጥቅም ላይ ይውላል & (unary አድራሻ ኦፕሬተር)።
ቻር a = "a"; ቻር * ፒ =
በዚህ አጋጣሚ p የተለዋዋጭ ሀ አድራሻ ይዟል። ግን የሚገርመው ከጠቋሚው ጋር ለበለጠ ስራ ፣ኮከብ መፃፍ አያስፈልግዎትም ፣የሚፈለገው በሚታወቅበት ጊዜ ብቻ ነው.
ቻር a = "a"; ቻር ለ = "b"; ቻር * p = p =
በዚህ ሁኔታ, p የተለዋዋጭውን አድራሻ ይይዛል b, ግን እሴቱን በዚህ አድራሻ ማግኘት ከፈለግን የዲፈረንስ ኦፕሬተርን መጠቀም አለብን, ተመሳሳይ ምልክት *.
ቻር አዲስ_ሲምቦል = 0; ቻር a = "a"; ቻር * ፒ = አዲስ_ሲምቦል = * p;
ስለዚህ የአዲሱ_ሲምቦል ተለዋዋጭ የ"a" ምልክት አስኪ ኮድ ይይዛል።

አሁን ጠቋሚው ለምን ያስፈልጋል ወደሚሉት ጥያቄዎች በቀጥታ እንሂድ። በአንድ ተግባር ውስጥ አብሮ ለመስራት የምንፈልገው ድርድር እንዳለን አስብ። ድርድርን ወደ ተግባር ለማሸጋገር እሱን መቅዳት ያስፈልግዎታል ፣ ማለትም ፣ ‹MK› ቀድሞውኑ ትንሽ ያለው ማህደረ ትውስታ ፣ ስለዚህ የበለጠ ትክክለኛ መፍትሄ ድርድርን መገልበጥ ሳይሆን የአድራሻውን አድራሻ ማለፍ ነው ። የመጀመሪያው ንጥረ ነገር እና መጠን.
m = (1,2,3...);
እንደዚህ ማድረግ ይችላሉ
ባዶ foo(char *m፣ uint8_t መጠን) ()
ወይም እንዲሁ
ባዶ foo(char m፣ uint8_t መጠን) ()
የድርድር ስም የመጀመርያውን አካል አድራሻ ስለያዘ፣ ከጠቋሚነት ያለፈ አይደለም። ቀላል የሂሳብ ስራዎችን በመጠቀም በድርድር ውስጥ ማለፍ ይችላሉ ፣ ለምሳሌ ፣ የድርድር አምስተኛውን ንጥረ ነገር ዋጋ ለማግኘት ፣ ወደ ድርድር አድራሻው (የመጀመሪያው አካል አድራሻ) 4 ማከል እና የዲፈረንስ ኦፕሬተርን መተግበር ያስፈልግዎታል ። .
m = * (m + 4);

እና ጥያቄው ወዲያውኑ የሚነሳው ለምንድነው በየቦታው ከጠቋሚው በፊት ለምን ዓይነት ይጽፋሉ? ሁሉም ነገር ቀላል ነው, የድርድር የመጀመሪያውን ኤለመንት አድራሻ እና የዝግጅቱን መጠን በማለፍ, እኛ እንላለን-ከዚህ (ጠቋሚ) 10 ጉድጓዶችን (የድርድሩን መጠን) ቆፍሩ, በሁለት ሰዓታት ውስጥ እንደርሳለን, እና የታሰቡት. ትራክተር የሚባሉትን ጉድጓዶች ለመቆፈር እና ጉድጓድ እየቆፈሩ ነው. በዚህ ሁኔታ ውስጥ ከመግባት ለመዳን የጉድጓዱን መጠን መግለጽ አስፈላጊ ነበር, በእኛ ተመሳሳይነት, የጠቋሚው አይነት ምን ያህል ባይት በማስታወስ ውስጥ እንደሚይዝ የሚወስነው ዓይነት ነው.

ስለዚህ የጠቋሚውን አይነት በመግለጽ ለአቀናባሪው እንነግራቸዋለን፣ የድርድር መጀመሪያ አድራሻው እዚህ አለ፣ የድርድር አንድ ኤለመንት 2 ባይት ይወስዳል፣ በድርድር ውስጥ 10 እንደዚህ ያሉ ንጥረ ነገሮች አሉ፣ ስለዚህ ምን ያህል ማህደረ ትውስታ መመደብ አለብን። ይህ ድርድር? 20 ባይት - አጣማሪው ምላሽ ይሰጣል. ግልጽ ለማድረግ, እንውሰድ ባዶ ዓይነት ጠቋሚ፣ ምን ያህል ቦታ እንደሚይዝ አልተገለጸም።- ይህ አድራሻ ብቻ ነው, ወደ ተለያዩ ዓይነቶች ጠቋሚዎች እንቀንሰው እና የማስተላለፊያውን ሥራ እንፈጽም.


እንዲሁም ጠቋሚን ወደ አንድ መዋቅር ወደ ተግባሩ ማስተላለፍ ይችላሉ. የአወቃቀሩ ምልክት ስለሚታወቅ የመነሻውን አድራሻ ብቻ ማለፍ አለብን, እና ማጠናከሪያው ራሱ ወደ መስኮች ይሰብረዋል.

እንግዲህ የመጨረሻው ጥያቄ ማን ነው ይህን ጠቋሚ ያመጣው የሚለው ነው። ይህንን ጉዳይ ለመረዳት ወደ ሰብሳቢው መዞር አለብን ፣ ለምሳሌ AVR ፣ እና እዚያ መመሪያዎችን እናገኛለን
st X, r1; የ r1 ይዘቶችን በ SRAM ውስጥ በአድራሻ X ያስቀምጡ, X ጥንድ መዝጋቢዎች r26, r27 ld r1, X; የSRAM ይዘቶችን በአድራሻ X ወደ r1 ይጫኑ፣ X ጥንድ መዝገቦች r26፣ r27 በሆነበት
X እንደያዘ ግልጽ ይሆናል ጠቋሚ(አድራሻ) እና, ሁሉም ሰው ለማታለል ጠቋሚን ያመጣ ክፉ ሰው የለም, በጠቋሚዎች (አድራሻዎች) መስራት በ MK kernel ደረጃ ይደገፋል.

ጠቋሚ የአንድን ነገር አድራሻ የያዘ ተለዋዋጭ ነው። ጠቋሚው ስለ ዕቃው ይዘት መረጃን አይይዝም, ነገር ግን እቃው የት እንደሚገኝ መረጃ ይዟል.

ጠቋሚዎች በማህደረ ትውስታ ውስጥ ያሉ ቦታዎችን የሚያመለክቱ እንደ መለያዎች ናቸው። አድራሻም አላቸው እሴታቸውም የሌላ ተለዋዋጭ አድራሻ ነው። እንደ ጠቋሚ የተገለጸው ተለዋዋጭ በ RAM ውስጥ 4 ባይት ይይዛል (በ32-ቢት የአቀናባሪው ስሪት)።

የጠቋሚ አገባብ

ዓይነት * የነገር ስም;

የጠቋሚው አይነት አድራሻው የያዘው የተለዋዋጭ አይነት ነው። በ C ውስጥ ካሉ ጠቋሚዎች ጋር ለመስራት ሁለት ክዋኔዎች ተለይተዋል-

  • ክዋኔ * (ኮከብ ምልክት) - የአንድን ነገር ዋጋ በአድራሻው እንድታገኝ ይፈቅድልሃል - በጠቋሚው ውስጥ ባለው አድራሻ የያዘውን ተለዋዋጭ እሴት ይወስናል;
  • ክወና እና (ampersand) - የተለዋዋጭ አድራሻን ለመወሰን ያስችልዎታል.

ለምሳሌ፥

ሻር ሐ; // ተለዋዋጭ ቻር * p; // ጠቋሚ p = // p = አድራሻ ሐ

ጠቋሚን ማወጅ፣ የተለዋዋጭ አድራሻ ማግኘት

ተለዋዋጭን የሚያመለክት ጠቋሚን ለማወጅ በመጀመሪያ የዚያን ተለዋዋጭ አድራሻ ማግኘት አለብዎት. የተለዋዋጭ የማስታወሻ አድራሻን ለማግኘት ከተለዋዋጭ ስም በፊት የ"&" ምልክት መጠቀም ያስፈልግዎታል። ይህ የተለዋዋጭ እሴት የተከማቸበትን የማህደረ ትውስታ ሕዋስ አድራሻ ለማወቅ ያስችልዎታል. ይህ ክዋኔ የአድራሻ መቀበያ ስራ ይባላል፡-

ኢንት ቫር = 5; // ከቅድመ ጅምር int *ptrVar ጋር የአንድ ተለዋዋጭ ቀላል መግለጫ; // ጠቋሚ አውጀዋል ፣ ግን እስካሁን ምንም ነገር አይጠቁም ptrVar = // አሁን የእኛ ጠቋሚ ቁጥር 5 የተከማቸበትን አድራሻ በማስታወሻ ውስጥ ያመላክታል

ጠቋሚ ወደ ጠቋሚ

ጠቋሚ የማህደረ ትውስታ ቦታ አድራሻን ያከማቻል። ወደ ጠቋሚ ጠቋሚ መፍጠር ይችላሉ, ከዚያ የጠቋሚውን አድራሻ ያከማቻል እና ይዘቱን መድረስ ይችላል. የጠቋሚ ጠቋሚ እንደሚከተለው ይገለጻል፡-

<тип> **<имя>;

ጠቋሚ ወደ ጠቋሚ እንዴት እንደሚሰራ ምሳሌ:

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ( int A; int B; int *p; int **pp; A = 10; B = 111; p = pp = printf ("A = %d\n", A); *p = 20; printf("A = %d\n",A);*(*pp) = 30; ("B = %d\n", *p **pp = 333; printf("B = %d",B);

ጠቋሚዎች እና የመውሰድ አይነት

ጠቋሚው አድራሻ ስለሚያከማች ወደ ሌላ ዓይነት መጣል ይችላሉ። ከተለዋዋጭ አካል መውሰድ ከፈለግን ወይም ተለዋዋጭው የምንፈልገውን አይነት እንደሚያከማች ካወቅን ይህ አስፈላጊ ሊሆን ይችላል።

በሚከተለው ምሳሌ, የ int አይነት መጠን 4 ባይት, እና ቻር 1 ባይት የመሆኑን እውነታ እንጠቀማለን. በዚህ ምክንያት, የመጀመሪያውን ባይት አድራሻ ከተቀበሉ, የቀረውን የቁጥር ባይት ማለፍ እና ይዘታቸውን ማሳየት ይችላሉ.

#ያካትቱ #ያካትቱ # SIZE 10 ባዶ ዋና () ይግለጹ ( int A = 10፤ int *intPtr፤ char *charPtr፤ intPtr = printf("%d\n"፣ *intPtr)፤ printf("---------- -------\n"፤ charPtr = (char*)intPtr፤ printf("%d"፣ *charPtr)፤ charPtr++፤ printf("%d"፣ *charPtr)፤ charPtr++፤ printf ("%d"፣ *charPtr printf("%d"፣ *charPtr);

NULL ጠቋሚ - ባዶ አመልካች

ከመጀመሩ በፊት ጠቋሚ ልክ እንደሌላው ተለዋዋጭ ቆሻሻ ያከማቻል። ግን በተመሳሳይ ጊዜ ይህ "ቆሻሻ" ትክክለኛ አድራሻ ሊሆን ይችላል. ለምሳሌ, ጠቋሚ አለ. መጀመሩን ወይም አለመጀመሩን እንዴት ማወቅ እችላለሁ? በአጠቃላይ, ምንም መንገድ. ይህንን ችግር ለመፍታት፣ የ stdlib ቤተ-መጽሐፍት NULL ማክሮ ተጀመረ።

ጠቋሚን በሚገልጹበት ጊዜ, በተወሰነ እሴት ካልተጀመረ, ከ NULL ጋር እኩል ማድረግ የተለመደ ነው.

Int *ptr = NULL;

መስፈርቱ በዚህ ጉዳይ ላይ ጠቋሚው NULL መሆኑን እና ከዜሮ ጋር እኩል መሆኑን ያረጋግጣል እና እንደ ቡሊያን ዋጋ ውሸት ሆኖ ሊያገለግል ይችላል። ምንም እንኳን በአተገባበሩ ላይ በመመስረት NULL ከ 0 ጋር እኩል ላይሆን ይችላል ማለትም ጠቋሚ ከዜሮ ወይም ከ NULL ጋር ሊወዳደር ይችላል ነገር ግን NULL ከአንድ የኢንቲጀር አይነት ወይም ተንሳፋፊ ነጥብ አይነት ተለዋዋጭ ጋር ሊወዳደር አይችልም.

ምንም እንኳን አብዛኛዎቹ ፕሮግራመሮች በእቃዎች እና በጠቋሚዎች መካከል ያለውን ልዩነት ቢረዱም ፣ አንዳንድ ጊዜ አንድን ነገር ለመድረስ የትኛው መንገድ እንደሚመረጥ ሙሉ በሙሉ ግልፅ አይደለም ። ከዚህ በታች ይህንን ጥያቄ ለመመለስ ሞክረናል.

ጥያቄ

ብዙ ጊዜ ኮድ ያየኋቸው ፕሮግራመሮች ከእነዚህ ነገሮች ራሳቸው ይልቅ ለነገሮች ጠቋሚዎችን እንደሚጠቀሙ አስተውያለሁ ፣ ማለትም ፣ ለምሳሌ ፣ የሚከተለውን ግንባታ ይጠቀማሉ።

ነገር * myObject = አዲስ ነገር;

ነገር myObject;

ዘዴዎች ጋር ተመሳሳይ. ለምን በምትኩ፡-

MyObject.testFunc ();

ይህንን መጻፍ አለብን: -

MyObject-> testFunc ();

እኔ እንደተረዳሁት፣ ይህ የፍጥነት ትርፍን ይሰጣል፣ ምክንያቱም... ወደ ማህደረ ትውስታ በቀጥታ እንገባለን. ቀኝ፧ ፒ.ኤስ. ከጃቫ ቀይሬያለሁ።

መልስ

በነገራችን ላይ በጃቫ ጠቋሚዎች በግልጽ ጥቅም ላይ እንዳልዋሉ ልብ ይበሉ, ማለትም. ፕሮግራመር በኮድ ውስጥ ያለውን ነገር በጠቋሚው በኩል ማግኘት አይችልም። ሆኖም ግን, በእውነቱ, በጃቫ, ሁሉም ዓይነቶች, ከመሠረታዊ በስተቀር, የማጣቀሻ ዓይነቶች ናቸው: በማጣቀሻዎች ይደርሳሉ, ምንም እንኳን አንድን መለኪያ በማጣቀሻነት በግልፅ ማለፍ የማይቻል ቢሆንም. እና ደግሞ፣ ማስታወሻ፣ አዲስ በC++ እና በጃቫ ወይም ሲ # ሙሉ ለሙሉ የተለያዩ ነገሮች ናቸው።

በC++ ውስጥ ምን ጠቋሚዎች እንዳሉ ትንሽ ሀሳብ ለመስጠት፣ ሁለት ተመሳሳይ የኮድ ቁርጥራጮች እዚህ አሉ።

ነገር1 = አዲስ ነገር (); // አዲስ ነገር እቃ2 = አዲስ ነገር (); // ሌላ አዲስ ነገር1 = object2; // ሁለቱም ተለዋዋጮች ቀደም ሲል በነገር2 የተጠቀሰውን ነገር ያመለክታሉ // በነገር1 የተጠቀሰው ነገር ከተቀየረ // እቃ2 እንዲሁ ይለወጣል, ምክንያቱም እነሱ ተመሳሳይ ናቸው.

በC++ ውስጥ ያለው በጣም ቅርብ የሆነው፡-

ነገር * እቃ1 = አዲስ ነገር (); // ማህደረ ትውስታ ለአዲስ ነገር ተመድቧል // ይህ ማህደረ ትውስታ በነገር1 ነገር * እቃ 2 = አዲስ ነገር (); // ከሁለተኛው ነገር ጋር ተመሳሳይ ነገር ይሰርዙ1; // C++ የቆሻሻ ማጠራቀሚያ ዘዴ ስለሌለው ይህ ካልተደረገ // ፕሮግራሙ ከአሁን በኋላ ይህንን ማህደረ ትውስታ ማግኘት አይችልም // ቢያንስ ፕሮግራሙ እንደገና እስኪጀመር ድረስ // ይህ የማስታወሻ ፍሳሽ ነገር ይባላል1 = እቃ2; // በጃቫ እንደሚታየው፣ object1 ወደ ተመሳሳይ ቦታ ይጠቁማል2

ሆኖም፣ ይህ ፈጽሞ የተለየ ነገር ነው (C++):

የነገር እቃ1; // አዲስ ነገር እቃ2; // ሌላ ነገር1 = object2; // እቃውን ሙሉ በሙሉ ወደ ቁስ1 መገልበጥ, // ጠቋሚውን እንደገና ከመወሰን ይልቅ, በጣም ውድ የሆነ ቀዶ ጥገና ነው.

ነገር ግን ማህደረ ትውስታን በቀጥታ በመድረስ ፍጥነት እናገኝ ይሆን?

በትክክል ለመናገር ይህ ጥያቄ ሁለት የተለያዩ ጥያቄዎችን ያጣምራል። መጀመሪያ: ተለዋዋጭ ማህደረ ትውስታ ምደባ መቼ መጠቀም አለብዎት? ሁለተኛ: ጠቋሚዎችን መቼ መጠቀም አለብዎት? በተፈጥሮ, እዚህ ያለ አጠቃላይ ቃላቶች ማድረግ አንችልም, ለሥራው በጣም ተስማሚ የሆነውን መሳሪያ መምረጥ ሁልጊዜ አስፈላጊ ነው. በእጅ ተለዋዋጭ ምደባን ከመጠቀም ሁልጊዜ የተሻለ ትግበራ አለ። (ተለዋዋጭ ምደባ)እና/ወይም ጥሬ ጠቋሚዎች።

ተለዋዋጭ ስርጭት

የጥያቄው አጻጻፍ አንድን ነገር ለመፍጠር ሁለት መንገዶችን ያቀርባል. እና ዋናው ልዩነታቸው የህይወት ዘመን ነው (የማከማቻ ቆይታ)በፕሮግራም ማህደረ ትውስታ ውስጥ. Object myObject መጠቀም; , በራስ-ሰር የህይወት ዘመን ማወቂያ ላይ ትተማመናለህ፣ እና ነገሩ ልክ ከስፋቱ እንደወጣ ይጠፋል። ነገር ግን ዕቃ *myObject = አዲስ ነገር; በሰርዝ ትእዛዝ እራስዎ ከማህደረ ትውስታ እስክትሰርዙት ድረስ እቃውን በህይወት ያቆየዋል። የመጨረሻውን አማራጭ በጣም አስፈላጊ በሚሆንበት ጊዜ ብቻ ይጠቀሙ. እና ስለዚህ ሁሌምከተቻለ የእቃውን የመደርደሪያ ህይወት በራስ-ሰር ለመወሰን ይምረጡ.

በተለምዶ የግዳጅ የህይወት ዘመን ውሳኔ በሚከተሉት ሁኔታዎች ውስጥ ጥቅም ላይ ይውላል።

  • ስፋቱን ከለቀቁ በኋላም ነገሩ እንዲኖር ያስፈልግዎታል- በትክክል ይህ ነገር, በትክክል በዚህ የማስታወሻ ቦታ ውስጥ, እና የእሱ ቅጂ አይደለም. ይህ ለእርስዎ አስፈላጊ ካልሆነ (በአብዛኛዎቹ ሁኔታዎች ይህ ነው) በራስ-ሰር የህይወት ጊዜ መወሰን ላይ ይደገፉ። ሆኖም ፣ አንድን ነገር ከአቅሙ ውጭ ማግኘት የሚያስፈልግበት ሁኔታ ምሳሌ እዚህ አለ ፣ ግን ይህንን በግልፅ ሳያከማቹ ይህንን ማድረግ ይችላሉ-አንድን ነገር ወደ ቬክተር በመፃፍ ፣ ከእቃው ጋር “ግንኙነቱን ማፍረስ” ይችላሉ - በእውነቱ (እና ቅጂው አይደለም) ከቬክተር ሲጠራ ይገኛል.
  • ብዙ ማህደረ ትውስታን መጠቀም ያስፈልግዎታል, ይህም ቁልል ሊጥለቀለቅ ይችላል. እንደዚህ አይነት ችግር ካላጋጠመዎት በጣም ጥሩ ነው (እና እምብዛም አያጋጥሙዎትም), ምክንያቱም ከ C ++ "ብቃት ውጭ" ነው, ግን በሚያሳዝን ሁኔታ, አንዳንድ ጊዜ ይህንን ችግር መፍታት አለብዎት.
  • ለምሳሌ፣ መጠቀም ያለብህን የድርድር መጠን በትክክል አታውቅም።. እንደሚታወቀው፣ በC++፣ ድርድር ሲገለጽ ቋሚ መጠን አላቸው። ይሄ ችግርን ሊፈጥር ይችላል፣ ለምሳሌ የተጠቃሚን ግብአት ሲያነቡ። ጠቋሚው መጠኑን ሳይገድብ በግምታዊ አነጋገር የዝግጅቱ መጀመሪያ የሚጻፍበትን ቦታ በማህደረ ትውስታ ውስጥ ብቻ ይገልጻል።

ተለዋዋጭ ምደባን መጠቀም አስፈላጊ ከሆነ ብልጥ ጠቋሚን በመጠቀም ማሸግ አለብዎት (በእኛ ጽሑፍ ውስጥ ማንበብ ይችላሉ) ወይም “ሀብትን ማግኘት እየጀመረ ነው” የሚለውን ፈሊጥ የሚደግፍ ሌላ ዓይነት (መደበኛ መያዣዎች ይህንን ይደግፋሉ - ይህ በ የትኛው ምንጭ: የማህደረ ትውስታ, የፋይል, የአውታረ መረብ ግንኙነት, ወዘተ - ሲቀበሉ, በገንቢው ውስጥ ይጀመራል እና ከዚያም በአጥፊው በጥንቃቄ ይደመሰሳል). ብልጥ ጠቋሚዎች ለምሳሌ std :: ልዩ_ptr እና std :: የተጋራ_ptr ናቸው።

ምልክቶች

ይሁን እንጂ ጠቋሚዎችን መጠቀም ከተለዋዋጭ ማህደረ ትውስታ ምደባ እይታ አንጻር ብቻ ሳይሆን ሁልጊዜም አማራጭ መንገድ አለ, ጠቋሚዎችን ሳይጠቀሙ, መምረጥ ያለብዎት. እንደበፊቱ፡ እንበል፡- ጠቋሚዎችን ለመጠቀም የተለየ ፍላጎት ከሌለ በስተቀር ሁልጊዜ አማራጭን ይምረጡ.

ጠቋሚዎችን መጠቀም እንደ አማራጭ አማራጭ ሊቆጠር የሚችልባቸው ጉዳዮች የሚከተሉትን ያካትታሉ:

  • የማጣቀሻ ትርጓሜዎች. አንዳንድ ጊዜ አንድን ነገር መድረስ አስፈላጊ ሊሆን ይችላል (ማህደረ ትውስታ ለእሱ የተመደበው ምንም ይሁን ምን), ምክንያቱም በዚህ ነገር ውስጥ ተግባራትን ማግኘት ይፈልጋሉ, እና ቅጂውን ሳይሆን - ማለትም. በማጣቀሻ ማለፍን ለመተግበር ሲያስፈልግ. ሆኖም ግን, በአብዛኛዎቹ ሁኔታዎች, እዚህ አገናኝ መጠቀም በቂ ነው, እና ጠቋሚ አይደለም, ምክንያቱም አገናኞች የሚፈጠሩት ለዚህ ነው. እነዚህ ከላይ በቁጥር 1 ላይ ከተገለጹት ነገሮች ትንሽ የተለዩ መሆናቸውን ልብ ይበሉ። ነገር ግን የነገሩን ግልባጭ ማግኘት ከቻሉ ማጣቀሻ መጠቀም አያስፈልግም (ነገር ግን ዕቃን መቅዳት ውድ ክዋኔ መሆኑን ልብ ይበሉ)።
  • ፖሊሞርፊዝም. በፖሊሞርፊዝም ውስጥ ያሉ ተግባራትን መጥራት (ተለዋዋጭ የነገር ክፍል) ማጣቀሻ ወይም ጠቋሚን በመጠቀም ይቻላል ። በድጋሚ, ማጣቀሻዎችን መጠቀም ይመረጣል.
  • አማራጭ ነገር. በዚህ አጋጣሚ ነገሩ እንደቀረ ለማመልከት nullptr ን መጠቀም ይችላሉ። የተግባር ክርክር ከሆነ በነባሪ ነጋሪ እሴቶች ወይም ከመጠን በላይ መጫን መጠቀሙ የተሻለ ነው። በአማራጭ፣ ይህንን ባህሪ የሚያጠቃልለውን አይነት መጠቀም ይችላሉ፣ ለምሳሌ ማበልጸጊያ:: አማራጭ (በC ++14 std :: አማራጭ የተሻሻለ)።
  • የማጠናቀር ፍጥነትን ማሻሻል. የማጠናቀሪያ ክፍሎችን መለየት ሊኖርብዎ ይችላል። (የማጠናቀር ክፍሎች). አንድ ውጤታማ የጠቋሚዎች አጠቃቀም ቅድመ-መግለጫ ነው (ምክንያቱም አንድን ነገር ለመጠቀም መጀመሪያ መግለጽ ያስፈልግዎታል)። ይህ የማጠናቀሪያ ክፍሎችን በቦታ እንዲለቁ ያስችልዎታል, ይህም የማጠናቀሪያ ጊዜን በማፋጠን ላይ አዎንታዊ ተጽእኖ ይኖረዋል, በዚህ ሂደት ላይ የሚጠፋውን ጊዜ በእጅጉ ይቀንሳል.
  • ከቤተ-መጽሐፍት ጋር መስተጋብርC ወይም C-like. እዚህ በመጨረሻው ጊዜ ማህደረ ትውስታን ከነሱ ነፃ በማድረግ ጥሬ ጠቋሚዎችን መጠቀም አለብዎት። አንድ ጥሬ ጠቋሚ ከብልጥ ጠቋሚ ማግኘት ይችላሉ, ለምሳሌ, በማግኘት ኦፕሬሽን. ቤተ መፃህፍቱ በኋላ በእጅ መፈታት ያለበትን ማህደረ ትውስታ ከተጠቀመ አጥፊውን በስማርት ጠቋሚ ውስጥ መቅረጽ ይችላሉ።