การเริ่มต้น - มันคืออะไร? การกำหนดค่าพารามิเตอร์ฟังก์ชันล่วงหน้า

ขึ้นอยู่กับว่าโปรแกรมทำงานหรือควรทำงานอย่างไร คุณสามารถแก้ไขปัญหาได้หลายวิธี ตามที่ฉันเข้าใจ Login_Form รับ/กรอกข้อมูลเกี่ยวกับผู้ใช้ จากนั้นในตำแหน่งที่คุณต้องการรับ user_id จากแบบฟอร์มนี้ คุณเพียงแค่รอจุดที่แบบฟอร์มได้รับข้อมูลทั้งหมดแล้ว จากนั้นคุณก็จะได้รับ ID นี้ อย่างไรก็ตาม ควรทำการรับใบเสร็จอย่างเป็นทางการในรูปแบบของเมธอด GetUserId() จากนั้นในวิธีนี้ คุณสามารถรอหยุดชั่วคราวจนกว่าข้อมูลจะมาถึง จากนั้นจึงส่งคืน ID ที่ต้องการเท่านั้น หากไม่สามารถรอได้ในทันที คุณจะต้องใช้บูล GetUserId(int & user_id) เพื่อส่งคืน เช่น จริง/เท็จ หากมีข้อมูลอยู่แล้วหรือไม่ และเฉพาะในกรณีที่ส่งคืนจริงเท่านั้น จึงจะถือว่า user_id เต็มไปด้วย ค่าที่ต้องการ เหล่านั้น. คุณต้องจัดเก็บแบบฟอร์มไว้ที่ใดที่หนึ่งและบางครั้งก็สอบถามเพื่อรับข้อมูลที่คุณต้องการ และคุณสามารถสร้างการบล็อก GetUserId() ที่รออินพุตหรือแบบที่ไม่ปิดกั้นซึ่งจะส่งคืนแฟล็กความสำเร็จ ในกรณีนี้ มีความจำเป็นที่แบบฟอร์มนี้จะถูกจัดเก็บเป็นตัวแปรหรือสมาชิกของคลาสจนกว่าจะได้รับข้อมูลทั้งหมด วิธีแก้ปัญหาของคุณเมื่อบันทึกตัวชี้ไปที่ user_id นั้นไม่ปลอดภัย ใครจะรู้ว่าวัตถุฟอร์มยังมีชีวิตอยู่หรือไม่มีชีวิตอีกต่อไป เช่น ตัวชี้อาจจะใช่หรือไม่ถูกต้องก็ได้ แต่หากวัตถุแบบฟอร์มถูกจัดเก็บตลอดเวลาจนกว่าจะดำเนินการ การดำเนินการที่จำเป็นมีการรับประกันว่าวิธีการทั้งหมดของเธอจะได้ผล

หากคุณยังจำเป็นต้องแก้ไขปัญหานี้ด้วยพอยน์เตอร์ คุณก็สามารถแก้ไขได้เช่นกัน ไม่เหมือนในโค้ดของคุณ แต่เช่นนี้ คุณต้องใช้พอยน์เตอร์อัจฉริยะ เช่น std::shared_ptr เช่น ในคลาสแบบฟอร์ม เราไม่ได้เก็บสมาชิกสองคน (int user_id และ int * ptr_user_id) แต่เก็บสมาชิกหนึ่งคน std::shared_ptr ptr_user_id ในตัวสร้างที่เราจัดสรรหน่วยความจำสำหรับมัน ptr_user_id = new int(0) จากนั้นเมื่อจำเป็นใน แบบฟอร์มที่เรากรอกไปพร้อมๆ กัน เราจะทำให้มันสามารถรับได้จากแบบฟอร์มผ่าน shared_ptr GetUserIdPtr() const ( ส่งคืน ptr_user_id; ) ในทุกที่ที่คุณต้องการใช้ ID นี้ เพียงคัดลอกไปยังสมาชิกคลาส shared_ptr my_copy_user_id; ... หลังจากสร้างแบบฟอร์มแล้ว เราทำ my_copy_user_id = form.GetUserId() และตอนนี้ในรูปแบบของเราและใน Consumer ทุกคน เราทุกคนมี shared_ptr ชี้ไปที่หนึ่ง หน่วยความจำที่ใช้ร่วมกันด้วยเหตุนี้คุณจึงสามารถรับค่าของพอยน์เตอร์ได้ตลอดเวลาแม้ว่าออบเจ็กต์ฟอร์มจะถูกทำลายก็ตาม แม้จะปลอดภัย คุณยังสามารถตรวจสอบได้ตลอดเวลาว่า user_id กรอกค่าแล้วหรือยัง ถ้า 0 หมายถึงยังไม่ได้เติม มิฉะนั้นจะเติมแล้ว shared_ptr เป็นคลาสเทมเพลต C++ มาตรฐานที่นับการอ้างอิงไปยังหน่วยความจำที่ใช้ร่วมกันของประเภทที่กำหนด และปล่อยว่างเมื่อจำเป็น เช่น ไม่จำเป็นต้องดำเนินการใด ๆ เพื่อปลดปล่อยมัน และการนับการอ้างอิงทำให้แน่ใจได้ว่าหน่วยความจำจะถูกปลดปล่อยเฉพาะเมื่อแบบฟอร์มและผู้บริโภคทั้งหมดสิ้นสุดลงเท่านั้น นอกจากนี้เมื่อแบบฟอร์มถูกทำลายไปแล้ว ตัวชี้ยังคงใช้ได้เนื่องจาก ความทรงจำของมันจะไม่ถูกทำลาย

รายการพารามิเตอร์ในคำจำกัดความและต้นแบบของฟังก์ชัน นอกเหนือจากการจับคู่ประเภทของพารามิเตอร์แล้ว ยังมีวัตถุประสงค์อีกอย่างหนึ่งอีกด้วย

การประกาศพารามิเตอร์อาจมีตัวเริ่มต้น นั่นคือ นิพจน์ที่ต้องจัดเตรียมค่าเริ่มต้นสำหรับพารามิเตอร์ ตัวเริ่มต้นพารามิเตอร์ไม่ใช่นิพจน์คงที่ การกำหนดค่าเริ่มต้นของพารามิเตอร์ไม่ได้เกิดขึ้นในขั้นตอนการคอมไพล์ (เช่น การจัดสรรหน่วยความจำสำหรับอาร์เรย์) แต่เกิดขึ้นโดยตรงระหว่างการทำงานของโปรแกรม

บรรทัดต่อไปนี้แสดงตัวอย่างการประกาศฟังก์ชันพร้อมการกำหนดค่าเริ่มต้นของพารามิเตอร์ ฟังก์ชัน XX ใช้เพื่อเริ่มต้นพารามิเตอร์ ww

int ZZ(int tt, int ww = XX(BigVal));

พารามิเตอร์ตัวที่สองสามารถเริ่มต้นได้ด้วยวิธีนี้ โดยไม่ต้องระบุชื่อเลย ไวยากรณ์การประกาศช่วยให้คุณทำสิ่งนี้ได้!

int ZZ(int tt, int = XX(BigVal));

เงื่อนไขเดียวสำหรับการกำหนดค่าเริ่มต้นดังกล่าวคือ ประเภทของพารามิเตอร์ตรงกับประเภทของนิพจน์ที่มีค่าที่ใช้ระหว่างการกำหนดค่าเริ่มต้น

ต้นแบบฟังก์ชันสามารถอยู่ในขอบเขตที่แตกต่างกันได้ มันสามารถวางไว้ในส่วนเนื้อหาของฟังก์ชันที่กำหนดได้ การประกาศฟังก์ชันแต่ละรายการสามารถมีตัวเลือกของตัวเองสำหรับการประกาศและเตรียมใช้งานพารามิเตอร์ แต่การประกาศฟังก์ชันเดียวกันหลายครั้งภายในขอบเขตเดียวกันไม่อนุญาตให้มีการเริ่มต้นพารามิเตอร์ใหม่ ทุกสิ่งจะต้องมีขอบเขตที่สมเหตุสมผล

นอกจากนี้ C++ ยังมีข้อจำกัดอื่นที่เกี่ยวข้องกับลำดับที่พารามิเตอร์เริ่มต้นภายในขอบเขต การเริ่มต้นดำเนินการโดยไม่ล้มเหลวจากพารามิเตอร์สุดท้าย (ขวาสุด) ในรายการการประกาศพารามิเตอร์ การกำหนดค่าเริ่มต้นของพารามิเตอร์ไม่อนุญาตให้มีช่องว่าง: พารามิเตอร์เริ่มต้นไม่สามารถสลับกับพารามิเตอร์ที่ไม่ได้กำหนดค่าเริ่มต้นได้

int MyF1 (int par1, int par2, int par3, int par4 = 10);

………………………………….

int MyF1 (int par1, int par2 = 20, int par3 = 20, int par4);

………………………………….

int MyF1(int par1 = 100, int, int, int);

#รวม

int f(int, int=4);

int หลัก (int argc, ถ่าน * argv)

printf("%d\n", f(2)); //8

printf("%d\n", f(2,3)); //6

int ฉ(int a, int b)

ฟังก์ชั่นที่มีจำนวนพารามิเตอร์แปรผัน

เมื่อเรียกใช้ฟังก์ชันด้วยจำนวนพารามิเตอร์ที่แปรผัน จำนวนอาร์กิวเมนต์ที่ต้องการใดๆ จะถูกระบุในการเรียกใช้ฟังก์ชันนี้ ในการประกาศและคำจำกัดความของฟังก์ชันดังกล่าว หมายเลขตัวแปรอาร์กิวเมนต์ถูกระบุโดยจุดไข่ปลาที่ส่วนท้ายของรายการพารามิเตอร์ที่เป็นทางการหรือรายการประเภทอาร์กิวเมนต์

อาร์กิวเมนต์ทั้งหมดที่ระบุในการเรียกใช้ฟังก์ชันจะถูกผลักเข้าสู่สแต็ก จำนวนพารามิเตอร์ที่เป็นทางการที่ประกาศสำหรับฟังก์ชันจะถูกกำหนดโดยจำนวนอาร์กิวเมนต์ที่นำมาจากสแต็กและกำหนดให้กับพารามิเตอร์ที่เป็นทางการ โปรแกรมเมอร์มีหน้าที่รับผิดชอบในการเลือกอาร์กิวเมนต์เพิ่มเติมจากสแต็กอย่างถูกต้องและกำหนดจำนวนอาร์กิวเมนต์ที่อยู่บนสแต็ก

ตัวอย่างของฟังก์ชันที่มีจำนวนพารามิเตอร์แปรผันคือฟังก์ชันจากไลบรารีฟังก์ชันภาษา SI ที่ดำเนินการอินพุต/เอาต์พุตข้อมูล (printf, scanf ฯลฯ) ฟังก์ชัน printf() ในไลบรารีมีการประกาศดังนี้:

int printf(const char* ...);

เพื่อให้แน่ใจว่าเมื่อใดก็ตามที่มีการเรียก printf() อาร์กิวเมนต์แรกของประเภท const char* จะถูกส่งผ่านไป เนื้อหาของสตริงนี้ เรียกว่าสตริงรูปแบบ กำหนดว่าจำเป็นต้องมีอาร์กิวเมนต์เพิ่มเติมเมื่อโทรหรือไม่ หากมีอักขระเมตาในสตริงรูปแบบที่ขึ้นต้นด้วยสัญลักษณ์ % ฟังก์ชันจะรอให้มีอาร์กิวเมนต์เหล่านี้อยู่

โปรแกรมเมอร์สามารถพัฒนาฟังก์ชันของเขาด้วยพารามิเตอร์จำนวนตัวแปร เพื่อให้มั่นใจ วิธีที่สะดวกในการเข้าถึงอาร์กิวเมนต์ของฟังก์ชันด้วยจำนวนพารามิเตอร์ที่แปรผันได้ มีคำจำกัดความของแมโครสามแบบ (มาโคร) va_start, va_arg, va_end ซึ่งอยู่ในไฟล์ส่วนหัว stdarg.h มาโครเหล่านี้บ่งชี้ว่าฟังก์ชันที่ผู้ใช้พัฒนาขึ้นมีจำนวนอาร์กิวเมนต์ที่จำเป็น ตามด้วยอาร์กิวเมนต์เผื่อเลือกจำนวนหนึ่งที่แปรผันได้ อาร์กิวเมนต์ที่จำเป็นสามารถเข้าถึงได้ผ่านชื่อ เช่นเดียวกับเมื่อเรียกใช้ฟังก์ชันปกติ หากต้องการดึงข้อมูลอาร์กิวเมนต์เผื่อเลือก ให้ใช้มาโคร va_start, va_arg, va_end ตามลำดับต่อไปนี้

มาโคร va_start ได้รับการออกแบบมาเพื่อตั้งค่าอาร์กิวเมนต์ arg_ptr ไปที่จุดเริ่มต้นของรายการพารามิเตอร์ทางเลือก และดูเหมือนฟังก์ชันที่มีพารามิเตอร์สองตัว:

เป็นโมฆะ va_start(arg_ptr, prav_param);

พารามิเตอร์ prav_param ต้องเป็นพารามิเตอร์ที่จำเป็นตัวสุดท้ายของฟังก์ชันที่ถูกเรียก และตัวชี้ arg_prt จะต้องถูกประกาศด้วยคำนิยามล่วงหน้าในรายการตัวแปรประเภท va_list ในรูปแบบ:

va_list arg_ptr;

ต้องใช้แมโคร va_start ก่อนที่จะใช้แมโคร va_arg ครั้งแรก

มาโคร va_arg ให้การเข้าถึงพารามิเตอร์ปัจจุบันของฟังก์ชันที่ถูกเรียก และยังดูเหมือนฟังก์ชันที่มีพารามิเตอร์สองตัวอีกด้วย

type_arg va_arg(arg_ptr,ประเภท);

มาโครนี้ดึงค่าของประเภทตามที่อยู่ที่ระบุโดยตัวชี้ arg_ptr เพิ่มค่าของตัวชี้ arg_ptr ตามความยาวของพารามิเตอร์ที่ใช้ (ความยาวประเภท) ดังนั้นพารามิเตอร์ arg_ptr จะชี้ไปที่พารามิเตอร์ถัดไปของฟังก์ชันที่เรียกว่า . แมโคร va_arg ถูกใช้บ่อยเท่าที่จำเป็นเพื่อดึงพารามิเตอร์ทั้งหมดของฟังก์ชันที่เรียกว่า

แมโคร va_end ถูกใช้หลังจากประมวลผลพารามิเตอร์ฟังก์ชันทั้งหมดแล้ว และตั้งค่าตัวชี้รายการพารามิเตอร์เผื่อเลือกเป็นศูนย์ (NULL)

ลองพิจารณาใช้มาโครเหล่านี้เพื่อประมวลผลพารามิเตอร์ของฟังก์ชันที่คำนวณค่าเฉลี่ยของลำดับจำนวนเต็มตามอำเภอใจ เนื่องจากฟังก์ชันมีจำนวนพารามิเตอร์ที่แปรผันได้ เราจะถือว่าค่าเท่ากับ -1 เป็นจุดสิ้นสุดของรายการ เนื่องจากรายการต้องมีอย่างน้อยหนึ่งองค์ประกอบ ฟังก์ชันจึงมีพารามิเตอร์ที่จำเป็นหนึ่งรายการ

#รวม

#รวม

int sred_znach(int,...);

n=sred_znach(2,3,4,-1);

/* โทรด้วยพารามิเตอร์สี่ตัว */

printf("n=%d\n",n);

/* โทรด้วยพารามิเตอร์สี่ตัว */

n=sred_znach(5,6,7,8,9,-1);

/* โทรด้วยพารามิเตอร์ 6 ตัว */

int sred_znach(int x,...)

int i=0, j=0, ผลรวม=0;

va_start(uk_arg,x);

/* ตั้งค่าตัวชี้ uk_arg เป็น */

/* พารามิเตอร์ทางเลือกแรก */

ถ้า (x!=-1) ผลรวม=x; /* ตรวจสอบว่ารายการว่างหรือไม่ */

อย่างอื่นกลับ (0);

ในขณะที่ ((i=va_arg(uk_arg,int))!=-1)

/* เลือกอันถัดไป */

( /* พารามิเตอร์และตรวจสอบ */

#รวม

#รวม

ผลรวม+=ฉัน;

/* ต่อท้ายรายการ */

/* โทรด้วยพารามิเตอร์สี่ตัว */

va_end(uk_arg);

/* ปิดรายการพารามิเตอร์ */

ตัวอย่างที่ 2: มีตัวเลือกอื่นที่เป็นไปได้ - พารามิเตอร์แรกของฟังก์ชันมีหน้าที่รับผิดชอบจำนวนองค์ประกอบที่จะสรุป นอกจากนี้ คุณสามารถปฏิเสธที่จะใช้มาโครและแยกวิเคราะห์สแต็กในโค้ดฟังก์ชันได้

int sred_znach2(int,...);

n=sred_znach2(3,2,3,4);

= <int sred_znach2(int n,...)>

int *pPointer = สำหรับ (int i=n ; i; i--) รวม += *(++pPointer);การเริ่มต้น

ตัวแปรที่ประกาศภายนอกโดยไม่มีข้อกำหนดเฉพาะคลาสพื้นที่เก็บข้อมูลสามารถเริ่มต้นได้มากที่สุดหนึ่งครั้งในไฟล์ต้นฉบับใดๆ ที่ประกอบเป็นโปรแกรม หากไม่ได้เตรียมใช้งานอย่างชัดเจนในไฟล์ต้นฉบับใดๆ ตัวเชื่อมโยงจะเตรียมใช้งานเป็นศูนย์

ตัวแปรคลาสหน่วยความจำ คงที่ที่ประกาศทั้งระดับภายนอกและระดับภายใน สามารถเริ่มต้นได้ด้วยนิพจน์คงที่ไม่เกินหนึ่งครั้งต่อ ไฟล์ต้นฉบับ- หากไม่ได้เตรียมใช้งานอย่างชัดเจน คอมไพเลอร์ C จะเตรียมใช้งานให้เป็นศูนย์

การเริ่มต้นตัวแปรคลาสหน่วยความจำ อัตโนมัติและ ลงทะเบียนดำเนินการทุกครั้งที่คุณเข้าสู่บล็อก (ยกเว้นการเข้าสู่บล็อกโดยใช้ตัวดำเนินการ ข้ามไป) ซึ่งมีการประกาศไว้ หากละเว้นตัวเริ่มต้นในการประกาศตัวแปรคลาสหน่วยความจำ อัตโนมัติหรือ ลงทะเบียนแสดงว่าค่าเริ่มต้นไม่ได้ถูกกำหนดไว้ การเริ่มต้นตัวแปรประเภทคอมโพสิต (อาร์เรย์ โครงสร้าง ยูเนียน) โดยมีคลาสหน่วยความจำ อัตโนมัติเป็นสิ่งต้องห้ามใน SP MSC แต่อนุญาตใน SP TS แม้ว่าตัวแปรจะประกาศด้วยตัวดัดแปลงก็ตาม ค่าคงที่- ตัวแปร ประเภทคอมโพสิตมีคลาสหน่วยความจำ คงที่, สามารถเริ่มต้นได้ภายใน

การกำหนดค่าเริ่มต้นสำหรับตัวแปรระดับภายนอกและตัวแปรคลาสหน่วยความจำ คงที่ระดับภายในจะต้องเป็นการแสดงออกคงที่ (ดูหัวข้อ 4.2.9) ตัวแปรคลาสหน่วยความจำ อัตโนมัติและ ลงทะเบียนสามารถเริ่มต้นได้ไม่เพียงแต่ด้วยนิพจน์คงที่เท่านั้น แต่ยังรวมถึงนิพจน์ที่มีตัวแปรและการเรียกใช้ฟังก์ชันด้วย

จากหนังสือ C++ โดย ฮิลล์ เมอร์เรย์

5.2.4 การเริ่มต้น การใช้ฟังก์ชันเช่น set_date() เพื่อให้แน่ใจว่าการเริ่มต้นของคลาสอ็อบเจ็กต์นั้นไม่สวยงามและเกิดข้อผิดพลาดได้ง่าย เนื่องจากไม่มีที่ไหนระบุว่าต้องเตรียมใช้งานอ็อบเจ็กต์ โปรแกรมเมอร์จึงอาจลืมทำเช่นนั้น หรือ (นั่น

จากหนังสือ คู่มือช่วยเหลือในภาษาซี++ ผู้เขียน สตรอสแตรป บีจาร์น

6.6 การกำหนดและการเริ่มต้น พิจารณาคลาสสตริงที่เรียบง่ายมาก string:struct string (* char* p; int size; // ขนาดของเวกเตอร์ชี้ไปที่ pstring(int sz) (* p = new char; *) ~string() (* ลบ p; *) *); สตริงคือโครงสร้างข้อมูลที่ประกอบด้วยเวกเตอร์ของอักขระและความยาวของเวกเตอร์นี้ เวกเตอร์

จากหนังสือสำนวนและสไตล์ C++ โดย มาคมูตอฟ อัลเบิร์ต

จากหนังสือ System Programming in สภาพแวดล้อมของวินโดวส์ โดย Hart Johnson M

R.12.6 การเริ่มต้น อ็อบเจ็กต์ของคลาสที่ไม่มีตัวสร้าง ไม่มีสมาชิกส่วนตัวหรือสมาชิกที่ได้รับการคุ้มครอง หมายเลข ฟังก์ชั่นเสมือนและไม่มีคลาสพื้นฐานสามารถเริ่มต้นได้โดยใช้รายการตัวเริ่มต้น (§R.8.4.1) วัตถุคลาสที่มีตัวสร้างจะต้องเริ่มต้นหรือมี

จากหนังสือโครงสร้างพื้นฐาน กุญแจสาธารณะ ผู้เขียน โปเลียนสกายา โอลก้า ยูริเยฟนา

จากหนังสือ The C Programming Language for คอมพิวเตอร์ส่วนบุคคล ผู้เขียน โบชคอฟ เอส.โอ.

ขั้นตอนที่ 12 - การเริ่มต้นสองขั้นตอน เมื่อเราสร้างอินสแตนซ์ที่ไม่ใช่สแต็ก เราจะเขียนโค้ดต่อไปนี้: CClass* cc = new CClass(); เรามาลองคิดกันดู new เป็นตัวดำเนินการระดับโลกที่มีคำจำกัดความ: ตัวดำเนินการ void* ใหม่ (size_t ไบต์) โดยได้รับจากคอมไพเลอร์ตามจำนวนไบต์ที่ต้องการ การจัดเก็บวัตถุ,

จากหนังสือ QNX/UNIX [Anatomy of Concurrency] ผู้เขียน ทซิลูริก โอเลก อิวาโนวิช

รองรับการเริ่มต้น Winsock Winsock API DLL(WS2_32.DLL) เพื่อเข้าใช้งานซึ่งคุณต้องเชื่อมต่อไลบรารี WS_232.LIB กับโปรแกรม DLL นี้ควรเริ่มต้นได้โดยใช้ฟังก์ชัน WSAStartup เฉพาะ Winsock ที่ไม่เป็นไปตามมาตรฐาน ซึ่งควรเป็นฟังก์ชันแรกของ

จากหนังสือ The C Language - A Guide for Beginners โดย ปราตา สตีเว่น

การเริ่มต้น ในขั้นตอนการเริ่มต้น ขึ้นอยู่กับ พารามิเตอร์อินพุตมีการตั้งค่าตัวแปรสถานะที่จำเป็นในการตรวจสอบเส้นทางการรับรองแล้ว ใน ตัวแปรสถานะข้อจำกัดต่างๆ ยังคงอยู่ซึ่งจะถูกนำมาพิจารณาเมื่อตรวจสอบความถูกต้องของเส้นทาง ตัวแปร

จากหนังสือการเขียนโปรแกรมสำหรับ Linux แนวทางแบบมืออาชีพ โดย มิทเชลล์ มาร์ก

การเริ่มต้น ตัวแปรในการประกาศสามารถกำหนดค่าเริ่มต้นผ่านตัวเริ่มต้นได้ รายการตัวเริ่มต้นในการประกาศนำหน้าด้วยเครื่องหมายเท่ากับ =<инициализатор>ตัวแปรทุกประเภทสามารถเริ่มต้นได้ ฟังก์ชั่นไม่ได้เริ่มต้น

จากหนังสือ C++ สำหรับผู้เริ่มต้น โดย ลิปป์แมน สแตนลีย์

การกำหนดค่าเริ่มต้น int pthread_mutexattr_init (const pthread_mutexattr_t* attr); ฟังก์ชันเตรียมใช้งานโครงสร้างแอ็ตทริบิวต์ mutex ที่ชี้โดยพารามิเตอร์ attr ชนิดข้อมูล pthread_mutexattr_t ถูกกำหนดไว้ในไฟล์ (ได้มาจากประเภท sync_attr_t ซึ่งจะถูกกำหนดไว้ในไฟล์

จากหนังสือของผู้เขียน

การกำหนดค่าเริ่มต้น Mutex int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr); โครงสร้างข้อมูล pthread_mutex_t ถูกกำหนดไว้ในไฟล์ (ประเภทที่ได้มาจากประเภท sync_t ซึ่งจะถูกกำหนดไว้ในไฟล์ ) และมีรูปแบบดังต่อไปนี้: struct _sync_t ( /* Counter for recursive

จากหนังสือของผู้เขียน

การเริ่มต้นโครงสร้าง เราได้เห็นว่าตัวแปรและอาร์เรย์เริ่มต้นอย่างไร: int count = 0;static int fibo=(0, 1, 1, 2, 3, 5, 8); เป็นไปได้ไหมที่จะเตรียมใช้งานตัวแปรโครงสร้างด้วย? ใช่ หากตัวแปรโครงสร้างเป็นแบบภายนอกหรือแบบคงที่ ก็ควรจะจำไว้ตรงนี้ว่า

จากหนังสือของผู้เขียน

5.2.2. การเริ่มต้นการจัดสรรเซมาฟอร์และการเริ่มต้นเซมาฟอร์เป็นการดำเนินการที่แตกต่างกันสองประการ ในการเริ่มต้นเซมาฟอร์ ให้เรียกใช้ฟังก์ชัน semctl() โดยส่งผ่านอาร์กิวเมนต์ที่สอง เท่ากับศูนย์และอาร์กิวเมนต์ที่สามเท่ากับค่าคงที่ SETALL อาร์กิวเมนต์ที่สี่ต้องเป็นประเภท union semun, field

จากหนังสือของผู้เขียน

7.9.2. การเริ่มต้นและการกำหนด จำได้ว่าชื่ออาร์เรย์โดยไม่ระบุดัชนีองค์ประกอบถูกตีความว่าเป็นที่อยู่ขององค์ประกอบแรก ในทำนองเดียวกัน ชื่อฟังก์ชันที่ไม่มีวงเล็บตามหลังจะถูกตีความว่าเป็นตัวชี้ฟังก์ชัน เช่น เมื่อคำนวณ

จากหนังสือของผู้เขียน

14.1. การเริ่มต้นคลาส พิจารณาคำจำกัดความของคลาสต่อไปนี้: class Data (public:int ival;char *ptr;);หากต้องการใช้คลาสออบเจ็กต์อย่างปลอดภัย คุณต้องเตรียมใช้งานสมาชิกอย่างถูกต้อง อย่างไรก็ตาม ความหมายของการดำเนินการนี้จะแตกต่างกันไปตามคลาสที่ต่างกัน ตัวอย่างเช่น can ival

จากหนังสือของผู้เขียน

14.6. การเริ่มต้น Memberwise A การเริ่มต้นของอ็อบเจ็กต์หนึ่งของคลาสโดยอ็อบเจ็กต์อื่นในคลาสเดียวกัน เช่น: Account oldAcct(" Anna Livia Plurabelle");Account newAcct(oldAcct); ตามค่าเริ่มต้น - เพราะจะทำโดยอัตโนมัติโดยอิสระ

โปรแกรม SI ทั่วไปคือคำจำกัดความ ฟังก์ชั่นหลักซึ่งจะต้องดำเนินการ การดำเนินการที่จำเป็นเรียกใช้ฟังก์ชันอื่นๆ โปรแกรมตัวอย่างข้างต้นเป็นไฟล์ต้นฉบับเดียวที่มีฟังก์ชันทั้งหมดที่จำเป็นในการรันโปรแกรม การสื่อสารระหว่างฟังก์ชันต่างๆ ดำเนินการตามข้อมูลโดยการส่งพารามิเตอร์และส่งกลับค่าฟังก์ชัน แต่คอมไพเลอร์ SI ยังช่วยให้คุณแบ่งโปรแกรมออกเป็นหลายส่วน (ไฟล์ต้นฉบับ) แปลแต่ละส่วนแยกกัน จากนั้นรวมทุกส่วนเป็นไฟล์ปฏิบัติการไฟล์เดียวโดยใช้ตัวเชื่อมโยง

ด้วยโครงสร้างดังกล่าว โปรแกรมต้นฉบับฟังก์ชั่นที่อยู่ในไฟล์ต้นฉบับที่แตกต่างกันสามารถใช้ตัวแปรภายนอกส่วนกลางได้ ฟังก์ชั่นทั้งหมดในภาษา C เป็นไปตามคำจำกัดความภายนอกและสามารถเข้าถึงได้จากไฟล์ใด ๆ เสมอ ตัวอย่างเช่น หากโปรแกรมประกอบด้วยไฟล์ต้นฉบับสองไฟล์ ดังแสดงในรูปที่ 2 ฟังก์ชันหลักจะสามารถเรียกใช้ฟังก์ชันใดฟังก์ชันหนึ่งในสามฟังก์ชัน fun1, fun2, fun3 และแต่ละฟังก์ชันเหล่านี้สามารถเรียกฟังก์ชันอื่นได้

เพื่อให้ฟังก์ชันที่กำหนดไว้ดำเนินการใด ๆ ฟังก์ชันนั้นจะต้องใช้ตัวแปร ใน SI จะต้องประกาศตัวแปรทั้งหมดก่อนจึงจะสามารถใช้งานได้ การประกาศจะแมปชื่อและคุณลักษณะของตัวแปร ฟังก์ชัน หรือประเภท การกำหนดตัวแปรจะทำให้หน่วยความจำถูกจัดสรรเพื่อเก็บค่าของมัน คลาสของหน่วยความจำที่จัดสรรถูกกำหนดโดยตัวระบุคลาสหน่วยความจำ และกำหนดอายุการใช้งานและขอบเขตของตัวแปรที่เกี่ยวข้องกับแนวคิดของบล็อกโปรแกรม

ในภาษา SI บล็อกคือลำดับของการประกาศ คำจำกัดความ และข้อความที่อยู่ในนั้น วงเล็บปีกกา- บล็อกมีสองประเภท - คำสั่งผสมและคำจำกัดความของฟังก์ชัน ซึ่งประกอบด้วยคำสั่งผสมซึ่งเป็นเนื้อความของฟังก์ชัน และส่วนหัวของฟังก์ชันที่อยู่ข้างหน้าเนื้อหา (ซึ่งรวมถึงชื่อฟังก์ชัน ประเภทการส่งคืน และพารามิเตอร์ที่เป็นทางการ ). บล็อกสามารถรวมคำสั่งผสมได้ แต่ไม่ใช่คำจำกัดความของฟังก์ชัน บล็อกด้านในเรียกว่าซ้อนกันและ หน่วยภายนอก- ครอบคลุม.

อายุการใช้งานคือช่วงเวลาของเวลาดำเนินการโปรแกรมในระหว่างที่มีอ็อบเจ็กต์โปรแกรม (ตัวแปรหรือฟังก์ชัน) อยู่ อายุการใช้งานของตัวแปรอาจเป็นแบบโลคัลหรือโกลบอลก็ได้ ตัวแปรที่มีอายุการใช้งานทั่วโลกจะมีการจัดสรรหน่วยความจำและค่าเฉพาะตลอดการทำงานของโปรแกรม โดยเริ่มจากช่วงเวลาที่ประกาศตัวแปร ตัวแปรที่มีอายุการใช้งานในเครื่องจะมีการจัดสรรหน่วยความจำและค่าที่กำหนดเฉพาะระหว่างการดำเนินการของบล็อกซึ่งมีการกำหนดหรือประกาศตัวแปรเท่านั้น แต่ละครั้งที่มีการป้อนบล็อก ตัวแปรท้องถิ่นจะถูกจัดสรร หน่วยความจำใหม่ซึ่งจะถูกปล่อยออกมาเมื่อออกจากบล็อก

ฟังก์ชันทั้งหมดใน SI มีอายุการใช้งานทั่วโลกและมีอยู่ตลอดระยะเวลาดำเนินการของโปรแกรม

ขอบเขตเป็นส่วนหนึ่งของข้อความโปรแกรมที่สามารถใช้งานได้ วัตถุนี้- วัตถุจะถือว่ามองเห็นได้ในบล็อกหรือไฟล์ต้นฉบับหากทราบชื่อและประเภทของวัตถุในบล็อกหรือไฟล์นั้น วัตถุสามารถมองเห็นได้ภายในบล็อก ไฟล์ต้นฉบับ หรือไฟล์ต้นฉบับทั้งหมดที่ประกอบเป็นโปรแกรม ขึ้นอยู่กับว่าวัตถุถูกประกาศในระดับใด: ในระดับภายในเช่น ภายในบางบล็อกหรือภายนอกเช่น นอกช่วงตึกทั้งหมด

หากมีการประกาศวัตถุภายในบล็อก ก็จะปรากฏให้เห็นในบล็อกนี้และในบล็อกภายในทั้งหมด หากมีการประกาศออบเจ็กต์ในระดับภายนอก จะมองเห็นได้ตั้งแต่จุดประกาศไปจนถึงจุดสิ้นสุดของไฟล์ต้นฉบับที่กำหนด

วัตถุสามารถทำให้มองเห็นได้ทั่วโลกโดยการประกาศที่เหมาะสมในไฟล์ต้นฉบับทั้งหมดที่ประกอบเป็นโปรแกรม

ตัวระบุคลาสหน่วยความจำในการประกาศตัวแปรอาจเป็นแบบอัตโนมัติ รีจิสเตอร์ สแตติก หรือภายนอก หากไม่ได้ระบุคลาสหน่วยความจำ คลาสนั้นจะถูกกำหนดโดยค่าเริ่มต้นจากบริบทการประกาศ

ออบเจ็กต์ของคลาส auto และ register มี เวลาท้องถิ่นชีวิต. ตัวระบุแบบคงที่และภายนอกจะกำหนดออบเจ็กต์ที่มีอายุการใช้งานทั่วโลก

เมื่อประกาศตัวแปรในระดับภายใน สามารถใช้ตัวระบุคลาสหน่วยความจำตัวใดตัวหนึ่งในสี่ตัวได้ และหากไม่ได้ระบุไว้ ก็จะถือว่าคลาสหน่วยความจำอัตโนมัตินั้น

ตัวแปรที่มีคลาสหน่วยความจำอัตโนมัติจะมีอายุการใช้งานภายในเครื่องและมองเห็นได้เฉพาะในบล็อกที่มีการประกาศเท่านั้น หน่วยความจำสำหรับตัวแปรดังกล่าวจะถูกจัดสรรเมื่อเข้าสู่บล็อกและจะว่างเมื่อออกจากบล็อก เมื่อกลับเข้าสู่บล็อกของตัวแปรนี้อีกครั้ง หน่วยความจำส่วนอื่นอาจถูกจัดสรร

ตัวแปรที่มีคลาสการจัดเก็บข้อมูลอัตโนมัติจะไม่ถูกเตรียมใช้งานโดยอัตโนมัติ จะต้องเริ่มต้นอย่างชัดเจนเมื่อมีการประกาศโดยการกำหนดค่าเริ่มต้น ตัวแปรที่ไม่ได้เตรียมใช้งานด้วยคลาสหน่วยเก็บข้อมูลอัตโนมัติจะถือว่าไม่ได้กำหนดไว้

ตัวระบุคลาสหน่วยความจำรีจิสเตอร์แนะนำให้คอมไพเลอร์จัดสรรหน่วยความจำสำหรับตัวแปรในรีจิสเตอร์ถ้าเป็นไปได้ การใช้หน่วยความจำรีจิสเตอร์มักจะส่งผลให้เวลาในการเข้าถึงตัวแปรลดลง ตัวแปรที่ประกาศด้วยคลาสหน่วยเก็บข้อมูลรีจิสเตอร์มีขอบเขตเดียวกันกับตัวแปรอัตโนมัติ จำนวนการลงทะเบียนที่สามารถใช้สำหรับค่าตัวแปรนั้นถูกจำกัดโดยความสามารถของคอมพิวเตอร์และหากคอมไพเลอร์ไม่มีการลงทะเบียนว่าง ตัวแปรนั้นจะถูกจัดสรรหน่วยความจำสำหรับคลาสอัตโนมัติ คลาสหน่วยความจำรีจิสเตอร์สามารถระบุได้เฉพาะกับตัวแปรเท่านั้น พิมพ์ intหรือพอยน์เตอร์ที่มีขนาดเท่ากับขนาดของ int

ตัวแปรที่ประกาศภายในด้วยตัวระบุคลาสการจัดเก็บข้อมูลแบบคงที่ช่วยให้สามารถบันทึกค่าของตัวแปรเมื่อออกจากบล็อก และใช้เมื่อกลับเข้าสู่บล็อกอีกครั้ง ตัวแปรดังกล่าวมีอายุใช้งานทั่วโลกและขอบเขตภายในบล็อกที่มีการประกาศ ต่างจากตัวแปรอัตโนมัติซึ่งจัดสรรไว้บนสแต็ก ตัวแปรคงที่จะได้รับการจัดสรรในส่วนข้อมูล และดังนั้นจึงคงค่าไว้เมื่อออกจากบล็อก

ตัวอย่าง: /* ประกาศตัวแปร i ในระดับภายในโดยมีคลาสหน่วยความจำคงที่ */ /* ไฟล์ต้นฉบับ file1.c */ main() ( ... ) fun1() ( static int i=0; ... ) /* ไฟล์ต้นฉบับ file2.c */ fun2() ( static int i= 0; ... ) fun3() ( คงที่ int i=0; ... )

ในตัวอย่างข้างต้น มีการประกาศตัวแปรสามตัวที่มีคลาสหน่วยความจำแบบคงที่และมีชื่อเหมือนกันคือ i ตัวแปรแต่ละตัวมีอายุใช้งานทั่วโลก แต่จะมองเห็นได้เฉพาะในบล็อก (ฟังก์ชัน) ที่ถูกประกาศเท่านั้น ตัวแปรเหล่านี้สามารถใช้เพื่อนับจำนวนการเรียกแต่ละฟังก์ชันจากทั้งสามฟังก์ชัน

ตัวแปรของคลาสหน่วยความจำแบบคงที่สามารถเริ่มต้นได้ด้วยนิพจน์คงที่ หากไม่มีการกำหนดค่าเริ่มต้นที่ชัดเจน ตัวแปรดังกล่าวจะถูกกำหนดค่าเป็นศูนย์ เมื่อเริ่มต้นด้วยนิพจน์ที่อยู่คงที่ คุณสามารถใช้ที่อยู่ของวัตถุภายนอกใด ๆ ยกเว้นที่อยู่ของวัตถุที่มีคลาสหน่วยความจำอัตโนมัติ เนื่องจากที่อยู่ของวัตถุหลังไม่ใช่ค่าคงที่และเปลี่ยนแปลงไปตามแต่ละรายการในบล็อก การเริ่มต้นจะดำเนินการหนึ่งครั้งเมื่อเข้าสู่บล็อกครั้งแรก

ตัวแปรที่ประกาศในเครื่องด้วยคลาสพื้นที่เก็บข้อมูลภายนอกคือการอ้างอิงถึงตัวแปรที่มีชื่อเดียวกันซึ่งกำหนดไว้ทั่วโลกในไฟล์ต้นฉบับไฟล์หนึ่งของโปรแกรม วัตถุประสงค์ของการประกาศดังกล่าวคือการทำให้คำนิยามตัวแปรระดับโลกมองเห็นได้ภายในบล็อก

ตัวอย่าง: /* ประกาศตัวแปร i ซึ่งเป็นชื่อของอาร์เรย์ภายนอกของจำนวนเต็มยาว ที่ระดับโลคัล */ /* ไฟล์ต้นฉบับ file1.c */ main() ( ... ) fun1() ( extern long i ; ... ) /* ไฟล์ต้นฉบับ file2.c */ long i=(0);

fun2() ( ... ) fun3() ( ... )

การประกาศ i เป็น extern ในตัวอย่างด้านบนจะทำให้มองเห็นได้ภายใน fun1 คำจำกัดความของตัวแปรนี้อยู่ใน file2.c ที่ระดับโกลบอล และควรมีเพียงรายการเดียว ในขณะที่อาจมีการประกาศหลายรายการกับคลาสหน่วยความจำภายนอก

จำเป็นต้องมีการประกาศกับคลาสหน่วยความจำภายนอกหากจำเป็นเพื่อใช้ตัวแปรที่อธิบายไว้ในไฟล์ต้นฉบับปัจจุบัน แต่ต่ำกว่าในข้อความของโปรแกรม เช่น ก่อนที่คำจำกัดความสากลจะเสร็จสมบูรณ์ ตัวอย่างต่อไปนี้แสดงให้เห็นถึงการใช้ตัวแปรชื่อเซนต์นี้

ตัวอย่าง: main() ( ภายนอก int st; ... ) static int st=(0);

เมื่อประกาศตัวแปรในระดับโกลบอล คุณสามารถใช้ตัวระบุคลาสหน่วยความจำแบบคงที่หรือภายนอกได้ และคุณยังสามารถประกาศตัวแปรโดยไม่ต้องระบุคลาสหน่วยความจำได้อีกด้วย คลาสหน่วยความจำอัตโนมัติและการลงทะเบียนไม่ได้รับอนุญาตสำหรับการประกาศทั่วโลก

การประกาศตัวแปรในระดับสากลอาจเป็นคำจำกัดความของตัวแปรหรือการอ้างอิงถึงคำจำกัดความที่สร้างไว้ที่อื่นในโปรแกรม การประกาศตัวแปรโกลบอลที่เตรียมใช้งานตัวแปรนั้น (ไม่ว่าจะโดยชัดแจ้งหรือโดยปริยาย) คือคำจำกัดความของตัวแปร คำจำกัดความในระดับโลกสามารถกำหนดได้ในรูปแบบต่อไปนี้:

1. ประกาศตัวแปรด้วยคลาสหน่วยความจำแบบคงที่ ตัวแปรดังกล่าวสามารถเริ่มต้นได้ด้วยนิพจน์คงที่ที่ชัดเจน หรือด้วยค่าเริ่มต้นเป็นศูนย์ นั่นคือการประกาศ static int i=0 และ static int i นั้นเทียบเท่ากัน และในทั้งสองกรณี ตัวแปร i จะได้รับการกำหนดค่าเป็น 0

2. ประกาศตัวแปรโดยไม่ระบุคลาสหน่วยความจำ แต่มีการกำหนดค่าเริ่มต้นที่ชัดเจน ตัวแปรนี้ถูกกำหนดคลาสหน่วยความจำแบบคงที่ตามค่าเริ่มต้น นั่นคือการประกาศ int i=1 และ static int i=1 จะเทียบเท่ากัน

ตัวแปรที่ประกาศแบบโกลบอลสามารถมองเห็นได้ภายในส่วนที่เหลือของไฟล์ต้นฉบับที่ตัวแปรนั้นถูกกำหนดไว้ เหนือคำอธิบายและในไฟล์ต้นฉบับอื่นๆ ตัวแปรนี้จะมองไม่เห็น (เว้นแต่จะมีการประกาศด้วยคลาสภายนอก)

ตัวแปรร่วมสามารถกำหนดได้เพียงครั้งเดียวภายในขอบเขตของมัน ในไฟล์ต้นฉบับอื่น สามารถประกาศตัวแปรโกลบอลอื่นที่มีชื่อเดียวกันและมีคลาสหน่วยความจำแบบสแตติกได้ โดยจะไม่มีข้อขัดแย้ง เนื่องจากตัวแปรแต่ละตัวเหล่านี้จะมองเห็นได้ในไฟล์ต้นฉบับเท่านั้น

ตัวระบุคลาสหน่วยความจำภายนอกสำหรับตัวแปรโกลบอลถูกใช้ เช่นเดียวกับการประกาศโลคัล เพื่อเป็นการอ้างอิงถึงตัวแปรที่ประกาศไว้ที่อื่นในโปรแกรม เช่น เพื่อขยายขอบเขตของตัวแปร ด้วยการประกาศดังกล่าว ขอบเขตของตัวแปรจะถูกขยายไปยังจุดสิ้นสุดของไฟล์ต้นฉบับซึ่งมีการประกาศเกิดขึ้น

การประกาศกับคลาสหน่วยเก็บข้อมูลภายนอกไม่อนุญาตให้มีการเริ่มต้น เนื่องจากการประกาศเหล่านี้อ้างถึงตัวแปรที่มีอยู่แล้วและที่กำหนดไว้ก่อนหน้านี้

1.6.2. การประกาศฟังก์ชั่น

ฟังก์ชั่นถูกกำหนดไว้ทั่วโลกเสมอ สามารถประกาศด้วยคลาสหน่วยความจำแบบคงที่หรือภายนอก การประกาศฟังก์ชันในระดับท้องถิ่นและระดับโลกมีความหมายเหมือนกัน

กฎในการกำหนดขอบเขตของฟังก์ชันแตกต่างจากกฎการมองเห็นของตัวแปรและมีดังต่อไปนี้

1. ฟังก์ชันที่ประกาศเป็นสแตติกจะมองเห็นได้ภายในไฟล์ที่ถูกกำหนดไว้ แต่ละฟังก์ชันสามารถเรียกใช้ฟังก์ชันอื่นที่มีคลาสหน่วยเก็บข้อมูลคงที่จากไฟล์ต้นฉบับ แต่ไม่สามารถเรียกใช้ฟังก์ชันที่กำหนดด้วยคลาสหน่วยเก็บข้อมูลคงที่ในไฟล์ต้นฉบับอื่นได้ ฟังก์ชั่นต่างๆด้วยคลาสหน่วยความจำคงที่ที่มีชื่อเดียวกันสามารถกำหนดในไฟล์ต้นฉบับที่แตกต่างกันได้โดยไม่ทำให้เกิดข้อขัดแย้ง

2. ฟังก์ชั่นที่ประกาศด้วยคลาสหน่วยความจำภายนอกจะปรากฏให้เห็นในไฟล์ต้นฉบับของโปรแกรมทั้งหมด ฟังก์ชันใดๆ ก็สามารถเรียกใช้ฟังก์ชันกับคลาสหน่วยความจำภายนอกได้

3. หากไม่มีตัวระบุคลาสหน่วยความจำในการประกาศฟังก์ชัน คลาสภายนอกจะถูกถือว่าตามค่าเริ่มต้น

คอมไพเลอร์จะวางอ็อบเจ็กต์ทั้งหมดที่มีคลาสหน่วยความจำภายนอกไว้ในตารางพิเศษในอ็อบเจ็กต์ไฟล์ ลิงค์ภายนอกซึ่งใช้โดยตัวแก้ไขลิงก์เพื่อแก้ไขลิงก์ภายนอก ลิงก์ภายนอกบางลิงก์ถูกสร้างขึ้นโดยคอมไพเลอร์เมื่อเรียกใช้ฟังก์ชันไลบรารี SI ดังนั้นเพื่อแก้ไขลิงก์เหล่านี้ ไลบรารีฟังก์ชันที่เกี่ยวข้องจะต้องพร้อมใช้งานสำหรับตัวแก้ไขลิงก์

1.6.3. อายุการใช้งานและขอบเขตของออบเจ็กต์ซอฟต์แวร์

อายุการใช้งานของตัวแปร (ทั่วโลกหรือท้องถิ่น) ถูกกำหนดตามกฎต่อไปนี้

1. ตัวแปรที่ประกาศแบบโกลบอล (เช่น นอกบล็อกทั้งหมด) มีอยู่ตลอดการดำเนินการทั้งหมดของโปรแกรม

2. ตัวแปรโลคัล (เช่น ประกาศภายในบล็อก) ที่มีรีจิสเตอร์หรือคลาสหน่วยความจำอัตโนมัติจะมีอายุการใช้งานเฉพาะในช่วงเวลาของการดำเนินการของบล็อกที่มีการประกาศเท่านั้น หากมีการประกาศตัวแปรโลคัลด้วยคลาสหน่วยความจำแบบคงที่หรือภายนอก ตัวแปรนั้นจะมีอายุการใช้งานตลอดระยะเวลาของโปรแกรมทั้งหมด

การมองเห็นตัวแปรและฟังก์ชันในโปรแกรมถูกกำหนดโดยกฎต่อไปนี้

1. ตัวแปรที่ประกาศหรือกำหนดไว้ทั่วโลกสามารถมองเห็นได้จากจุดประกาศหรือคำจำกัดความจนถึงจุดสิ้นสุดของไฟล์ต้นฉบับ คุณสามารถทำให้ตัวแปรมองเห็นได้ในไฟล์ต้นฉบับอื่นโดยการประกาศตัวแปรด้วยคลาสหน่วยความจำภายนอกในไฟล์เหล่านี้

2. ตัวแปรที่ประกาศในเครื่องหรือกำหนดไว้สามารถมองเห็นได้จากจุดประกาศหรือคำจำกัดความจนถึงจุดสิ้นสุดของบล็อกปัจจุบัน ตัวแปรดังกล่าวเรียกว่าท้องถิ่น

3. ตัวแปรจากบล็อกที่ล้อมรอบ รวมถึงตัวแปรที่ประกาศในระดับโลก จะมองเห็นได้ในบล็อกด้านใน การมองเห็นนี้เรียกว่าซ้อนกัน หากตัวแปรที่ประกาศภายในบล็อกมีชื่อเดียวกันกับตัวแปรที่ประกาศในบล็อกที่ล้อมรอบ ตัวแปรเหล่านั้นจะเป็นตัวแปรที่แตกต่างกัน และตัวแปรจากบล็อกที่ปิดล้อมในบล็อกด้านในจะมองไม่เห็น

4. ฟังก์ชั่นที่มีคลาสหน่วยความจำแบบสแตติกจะมองเห็นได้เฉพาะในไฟล์ต้นฉบับที่ถูกกำหนดไว้เท่านั้น ฟังก์ชั่นอื่นๆ ทั้งหมดจะมองเห็นได้ตลอดทั้งโปรแกรม

ป้ายกำกับในฟังก์ชันสามารถมองเห็นได้ตลอดทั้งฟังก์ชัน

ชื่อพารามิเตอร์อย่างเป็นทางการที่ประกาศในรายการพารามิเตอร์ของต้นแบบฟังก์ชันจะมองเห็นได้ตั้งแต่จุดประกาศพารามิเตอร์จนถึงจุดสิ้นสุดของการประกาศฟังก์ชันเท่านั้น

1.6.4. การเริ่มต้นตัวแปรระดับโลกและท้องถิ่น

เมื่อเริ่มต้นคุณต้องปฏิบัติตามกฎต่อไปนี้:

1. การประกาศที่มีตัวระบุคลาสหน่วยความจำภายนอกไม่สามารถมีตัวเริ่มต้นได้

2. ตัวแปรโกลบอลจะถูกเตรียมใช้งานเสมอ และเว้นแต่จะทำอย่างชัดเจน ตัวแปรจะเตรียมใช้งานเป็นศูนย์

3. ตัวแปรที่มีคลาสหน่วยความจำแบบคงที่สามารถเริ่มต้นได้ด้วยนิพจน์คงที่ การเริ่มต้นจะดำเนินการหนึ่งครั้งก่อนที่จะเริ่มโปรแกรม หากไม่มีการกำหนดค่าเริ่มต้นที่ชัดเจน ตัวแปรจะถูกเตรียมใช้งานเป็นศูนย์

4. การเริ่มต้นตัวแปรด้วยคลาสหน่วยความจำอัตโนมัติหรือรีจิสเตอร์จะดำเนินการทุกครั้งที่คุณเข้าสู่บล็อกที่มีการประกาศตัวแปรเหล่านั้น หากตัวแปรไม่ได้เตรียมใช้งานในการประกาศ แสดงว่าค่าเริ่มต้นของตัวแปรเหล่านั้นไม่ได้ถูกกำหนดไว้

5. ค่าเริ่มต้นสำหรับตัวแปรโกลบอลและตัวแปรที่มีคลาสหน่วยความจำแบบคงที่จะต้องเป็นนิพจน์คงที่ ที่อยู่ของตัวแปรดังกล่าวเป็นค่าคงที่ และค่าคงที่เหล่านี้สามารถใช้เพื่อเริ่มต้นพอยน์เตอร์ที่ประกาศทั่วโลกได้ ที่อยู่ของตัวแปรที่มีคลาสหน่วยความจำอัตโนมัติหรือรีจิสเตอร์ไม่ใช่ค่าคงที่และไม่สามารถใช้ในตัวเริ่มต้นได้

ตัวอย่าง: int global_var;

int func(void) ( int local_var; /* default auto */ static int *local_ptr=&local_var; /* นี่ผิด */ static int *global_ptr=&global_var; /* นี่ถูกต้อง */ register int *reg_ptr=&local_var; /* และถูกต้องมาก */ ) ในตัวอย่างข้างต้น ตัวแปรโกลบอล global_var มีอายุการใช้งานโกลบอลและที่อยู่ถาวร

[

ในหน่วยความจำ และที่อยู่นี้สามารถใช้เพื่อเริ่มต้นตัวชี้แบบคงที่ global_ptr ตัวแปรโลคัล local_var ซึ่งมีคลาสหน่วยความจำ auto จะถูกจัดสรรในหน่วยความจำเฉพาะในขณะที่ฟังก์ชัน func กำลังทำงานอยู่เท่านั้น ที่อยู่ของตัวแปรนี้ไม่ใช่ค่าคงที่และไม่สามารถใช้ในการเริ่มต้นตัวแปรคงที่ local_ptr ในการเริ่มต้นตัวแปรรีจิสเตอร์โลคัล reg_ptr คุณสามารถใช้นิพจน์ที่ไม่คงที่ และโดยเฉพาะที่อยู่ของตัวแปร local_ptr

การจำแนกประเภทของพอยน์เตอร์ฟังก์ชัน

คำจำกัดความของตัวชี้ฟังก์ชัน

โดยทั่วไปแล้ว พารามิเตอร์ฟังก์ชันจะใช้เพื่อจัดให้มีอินเทอร์เฟซข้อมูลระหว่างบริบทจุดเรียกและบริบทของฟังก์ชัน การใช้พอยน์เตอร์ฟังก์ชั่นช่วยให้เราสามารถแนะนำได้ รูปลักษณ์ใหม่พารามิเตอร์ พารามิเตอร์ฟังก์ชันที่เกี่ยวข้องกับประเภทใหม่นี้ช่วยให้คุณสามารถส่งผ่านฟังก์ชันอื่นๆ ไปยังฟังก์ชันที่คุณกำลังพัฒนาได้ เป็นผลให้สามารถเพิ่มระดับความเป็นสากลของฟังก์ชันที่พัฒนาขึ้นได้

ตัวชี้ฟังก์ชันคือนิพจน์ที่มีค่าเป็นที่อยู่ของฟังก์ชัน หรือตัวแปรที่เก็บที่อยู่ของฟังก์ชัน ที่อยู่ของฟังก์ชันมักเป็นที่อยู่ของจุดเริ่มต้น รหัสโปรแกรม- อย่างไรก็ตาม สำหรับคอมไพเลอร์บางตัว ที่อยู่ของฟังก์ชันอาจเป็นที่อยู่ของออบเจ็กต์ที่มีที่อยู่ของจุดเริ่มต้นของโค้ดโปรแกรมของฟังก์ชัน

พอยน์เตอร์ฟังก์ชันในภาษา C มีสองประเภท:

· ตัวชี้ – การแสดงออก

· ตัวแปรพอยน์เตอร์

38.9.3. ตัวชี้ - การแสดงออก

ตามที่ระบุไว้ข้างต้น นิพจน์ตัวชี้คือนิพจน์ที่มีค่าเป็นที่อยู่ของฟังก์ชัน ลองยกตัวอย่าง

ให้มีต้นแบบของฟังก์ชันสำหรับคำนวณกำลังสองของจำนวนชนิดสองเท่า จากนั้นนิพจน์ &sqr จะเป็นนิพจน์ตัวชี้ ที่นี่ & คือตัวดำเนินการที่อยู่แบบเอกภาค ซึ่งสั่งให้คอมไพเลอร์คำนวณที่อยู่ของฟังก์ชัน

38.9.4. ตัวชี้ - ตัวแปร

ตัวแปรพอยน์เตอร์เป็นตัวแปรที่ออกแบบมาเพื่อจัดเก็บที่อยู่ของฟังก์ชัน ลองพิจารณารูปแบบในการกำหนดตัวแปรดังกล่าว

(* <α>) (<γ>)

· * - ตัวดำเนินการอ้างอิง,

α – ตัวระบุของตัวชี้ที่ประกาศ

· b - ประเภทของค่าที่ส่งคืนโดยฟังก์ชันที่สามารถตั้งค่าตัวชี้ได้

· γ – รายการประเภทพารามิเตอร์ฟังก์ชันที่สามารถตั้งค่าตัวชี้ได้

ให้เรายกตัวอย่างการประกาศตัวแปรพอยน์เตอร์

สองเท่า (*pf)(สองเท่า);

นี่คือการประกาศตัวแปร ชื่อตัวแปร pf. ค่าของตัวแปรนี้สามารถเป็นที่อยู่ของฟังก์ชันใด ๆ ที่รับพารามิเตอร์ชนิด double และส่งคืนค่าชนิด double

จากที่กล่าวมาข้างต้น เราสามารถพูดได้ว่าคำจำกัดความของตัวชี้ฟังก์ชันระบุชุดของฟังก์ชันที่สามารถใช้งานได้ ตัวแปรพอยน์เตอร์ pf ที่ประกาศข้างต้นสามารถทำงานกับฟังก์ชันต่างๆ ต่อไปนี้ได้

sqr สองเท่า(x สองเท่า)
{

ดับเบิ้ลคิวบ์(ดับเบิ้ล x)
{

กลับ x * x * x;

กลับไปที่การประกาศของตัวชี้ - ตัวแปร pf ลองพิจารณาจุดประสงค์ของวงเล็บที่ใช้ในนั้น มีสองคู่ที่นี่



สองเท่า (*pf)(สองเท่า);

วงเล็บคู่ที่สองคือตัวดำเนินการฟังก์ชัน คำถามเกิดขึ้น: “วงเล็บคู่แรกมีบทบาทอย่างไร” เพื่อให้เข้าใจปัญหานี้ เราจะลบวงเล็บคู่นี้ออกชั่วคราว จากนั้นนิพจน์ดังกล่าวจะอยู่ในรูปแบบต่อไปนี้

สองเท่า *pf(สองเท่า);

นิพจน์ผลลัพธ์คือการประกาศฟังก์ชันที่รับพารามิเตอร์ประเภท double และส่งกลับตัวชี้ประเภท double* เพื่อให้แน่ใจในสิ่งนี้ ให้เราจำไว้ว่าไวยากรณ์ของการประกาศในภาษา C มีไวยากรณ์ของนิพจน์ด้วย หากต้องการระบุวัตถุประสงค์ของชื่อ pf ในนิพจน์ที่เป็นปัญหา ให้พิจารณานิพจน์ย่อย *pf(double) มีการนำโอเปอเรเตอร์สองตัวไปใช้กับชื่อ pf: * และ () การตีความชื่อ pf ขึ้นอยู่กับลำดับความสำคัญของตัวดำเนินการเหล่านี้ หากคุณดูที่ตารางลำดับความสำคัญของตัวดำเนินการ คุณจะเห็นว่าตัวดำเนินการฟังก์ชัน () มีลำดับความสำคัญสูงกว่าตัวดำเนินการอ้างอิง * ตามมาด้วยตัวดำเนินการ () ผูกชื่อ pf ไว้แน่นกว่าตัวดำเนินการ * ดังนั้นในเวอร์ชันใหม่ pf คือชื่อของฟังก์ชัน ไม่ใช่ชื่อของตัวชี้

ตอนนี้เรากลับไปที่โฆษณาเดิม

สองเท่า (*pf)(สองเท่า);

วงเล็บตัวแรกในนิพจน์นี้จะรวมลำดับการจัดกลุ่มของตัวดำเนินการและตัวถูกดำเนินการ ตอนนี้ชื่อ pf กลายเป็นชื่อของตัวชี้

ตัวชี้ – ตัวแปรสามารถเริ่มต้นได้ในเวลาที่มีการประกาศโดยใช้ตัวชี้ว่างหรือด้วยที่อยู่ของฟังก์ชันประเภทที่สามารถตั้งค่าตัวชี้ได้

ให้มีสองฟังก์ชันที่มีต้นแบบดังต่อไปนี้

sqr สองเท่า(x สองเท่า);
คิวบ์คู่(x สองเท่า);

มาประกาศสามพอยน์เตอร์ฟังก์ชัน:

สองเท่า (*pf1)(สองเท่า) =
สองเท่า (*pf2)(สองเท่า)= ลูกบาศก์;

สองเท่า (*pf3)(สองเท่า)= 0;

ไวยากรณ์ที่ใช้ประกาศตัวแปรสองตัวแรก (pf1 และ pf2) จะแตกต่างกันเล็กน้อย ไวยากรณ์ที่ใช้ประกาศตัวแปรตัวแรก (pf1) ไม่ต้องสงสัยเลยว่าถูกต้องหรือไม่ ทางด้านขวาของเครื่องหมายมอบหมายคือนิพจน์ที่มีค่าเป็นที่อยู่ของฟังก์ชัน อาจมีข้อสงสัยเกี่ยวกับความถูกต้องของการประกาศครั้งที่สองซึ่งมีการประกาศตัวแปร pf2 การประกาศนี้ใช้ชื่อฟังก์ชันแทนที่จะเป็นที่อยู่เป็นตัวเริ่มต้น อย่างไรก็ตามโค้ดนี้คอมไพล์ได้ดี ความจริงก็คือภาษา C มักจะอยู่ในโค้ดที่คาดว่าจะมีตัวชี้ไปยังฟังก์ชันและพบชื่อฟังก์ชันจะแปลงชื่อฟังก์ชันเป็นตัวชี้โดยอัตโนมัติ

ความคิดเห็น- การดำเนินการเริ่มต้นจะดำเนินการเช่นกันเมื่อใช้เลขชี้กำลังฟังก์ชันเป็นพารามิเตอร์ที่เป็นทางการของฟังก์ชัน