ตัวเลือกใดดีกว่าที่จะใช้ในข้อความด้านล่างใน C
static const int var = 5;
หรือ
#define var 5
หรือ
enum { var = 5 };
ตัวเลือกใดดีกว่าที่จะใช้ในข้อความด้านล่างใน C
static const int var = 5;
หรือ
#define var 5
หรือ
enum { var = 5 };
คำตอบ:
ขึ้นอยู่กับสิ่งที่คุณต้องการสำหรับค่า คุณ (และคนอื่น ๆ ) ไม่ได้ใช้ตัวเลือกที่สาม:
static const int var = 5;#define var 5enum { var = 5 };ไม่สนใจปัญหาเกี่ยวกับการเลือกชื่อจากนั้น:
ดังนั้นในบริบทส่วนใหญ่ต้องการ 'enum' มากกว่าทางเลือก มิฉะนั้นสัญลักษณ์แสดงหัวข้อย่อยแรกและสุดท้ายมีแนวโน้มที่จะเป็นปัจจัยควบคุม - และคุณต้องคิดให้หนักขึ้นถ้าคุณต้องตอบสนองทั้งสองในครั้งเดียว
หากคุณถามเกี่ยวกับ C ++ คุณจะต้องใช้ตัวเลือก (1) - const แบบคงที่ - ทุกครั้ง
enumคือพวกเขาใช้งานเป็นint([C99] 6.7.2.2/3) #defineช่วยให้คุณระบุไม่ได้ลงนามและระยะยาวด้วยUและLต่อท้ายและconstช่วยให้คุณให้ชนิด enumอาจทำให้เกิดปัญหากับการแปลงประเภทปกติ
enumมิได้#defineใช้พื้นที่พิเศษต่อ se ค่าจะปรากฏในรหัสวัตถุเป็นส่วนหนึ่งของคำแนะนำแทนที่จะเป็นหน่วยเก็บข้อมูลที่จัดสรรในส่วนข้อมูลหรือในกองหรือกองซ้อน คุณจะได้รับการจัดสรรพื้นที่สำหรับstatic const intคอมไพเลอร์ แต่คอมไพเลอร์อาจปรับให้เหมาะสมถ้าคุณไม่ใช้ที่อยู่
enum(และstatic const): พวกเขาไม่สามารถเปลี่ยนแปลงได้ a defineสามารถเป็น#undefine'd โดยที่ a enumและstatic constถูกกำหนดให้เป็นค่าที่กำหนด
พูด, พูดแบบทั่วไป, พูดทั่วๆไป:
static const
เพราะมันเคารพขอบเขตและเป็นประเภทที่ปลอดภัย
caveat เดียวที่ฉันเห็น: ถ้าคุณต้องการตัวแปรที่อาจกำหนดไว้ในบรรทัดคำสั่ง ยังมีทางเลือก:
#ifdef VAR // Very bad name, not long enough, too general, etc..
static int const var = VAR;
#else
static int const var = 5; // default value
#endif
เมื่อใดก็ตามที่เป็นไปได้แทนที่จะใช้มาโคร / จุดไข่ปลาให้ใช้ทางเลือกประเภทที่ปลอดภัย
หากคุณจำเป็นต้องใช้แมโครจริงๆ (ตัวอย่างเช่นคุณต้องการ__FILE__หรือ__LINE__) คุณควรตั้งชื่อแมโครของคุณให้ดีขึ้นด้วยความระมัดระวัง: ในแบบแผนการตั้งชื่อ Boost จะแนะนำตัวพิมพ์ใหญ่ทั้งหมดโดยเริ่มจากชื่อโครงการ (ที่นี่ BOOST_ ) ในขณะที่อ่านห้องสมุดคุณจะสังเกตเห็นว่านี่คือ (โดยทั่วไป) ตามด้วยชื่อของพื้นที่เฉพาะ (ไลบรารี) แล้วด้วยชื่อที่มีความหมาย
โดยทั่วไปแล้วจะทำให้ชื่อยาว :)
staticที่มีที่อยู่เท่านั้นที่ควรอยู่ และหากมีการใช้ที่อยู่อย่างใดอย่างหนึ่งอาจไม่สามารถใช้#defineหรือenum(ไม่มีที่อยู่) ... ดังนั้นฉันจึงล้มเหลวที่จะเห็นว่ามีทางเลือกอื่นที่สามารถใช้งานได้ หากคุณสามารถทำได้ด้วย "การประเมินเวลารวบรวม" คุณอาจกำลังมองหาextern constแทน
#ifอาจจะเป็นที่นิยมมากกว่า#ifdefธงบูล แต่ในกรณีนี้มันจะทำให้มันเป็นไปไม่ได้ที่จะกำหนดvarเป็น0จากบรรทัดคำสั่ง ดังนั้นในกรณีนี้#ifdefทำให้รู้สึกมากขึ้นตราบใดที่มีค่าทางกฎหมายสำหรับ0 var
ใน C โดยเฉพาะ ใน C คำตอบที่ถูกต้องคือใช้#define(หรือถ้าเหมาะสมenum)
ในขณะที่มันมีประโยชน์ที่จะมีการกำหนดขอบเขตและคุณสมบัติการพิมพ์ของconstวัตถุในความเป็นจริงconstวัตถุใน C (เมื่อเทียบกับ C ++) ไม่ใช่ค่าคงที่ที่แท้จริงดังนั้นจึงมักจะไร้ประโยชน์ในกรณีที่ใช้งานได้จริง
ดังนั้นใน C ตัวเลือกควรถูกกำหนดโดยวิธีที่คุณวางแผนที่จะใช้ค่าคงที่ของคุณ ตัวอย่างเช่นคุณไม่สามารถใช้const intวัตถุเป็นcaseป้ายกำกับ (ในขณะที่แมโครจะทำงาน) คุณไม่สามารถใช้const intวัตถุเป็นความกว้างบิตฟิลด์ (ในขณะที่แมโครจะทำงาน) ใน C89 / 90 คุณไม่สามารถใช้constวัตถุเพื่อระบุขนาดอาร์เรย์ (ในขณะที่แมโครทำงานได้) แม้แต่ใน C99 คุณไม่สามารถใช้constวัตถุเพื่อระบุขนาดของอาเรย์เมื่อคุณต้องการอาเรย์ที่ไม่ใช่VLA
หากนี่เป็นสิ่งสำคัญสำหรับคุณก็จะเป็นตัวเลือกของคุณ ส่วนใหญ่เวลาที่คุณจะไม่มีทางเลือก แต่กับการใช้งาน#defineใน C. และอย่าลืมอีกทางเลือกหนึ่งที่ก่อให้เกิดค่าคงที่จริงใน enumC.
ในconstวัตถุC ++ เป็นค่าคงที่ที่แท้จริงดังนั้นใน C ++ มันเกือบจะดีกว่าเสมอที่จะชอบconstชุดย่อย (ไม่จำเป็นต้องระบุอย่างชัดเจนstaticใน C ++)
const intอบเจ็กต์ในตัวพิมพ์เล็กและตัวพิมพ์ใหญ่นั้นผิดกฎหมายในทุกภาษาของ C (แน่นอนว่าคอมไพเลอร์ของคุณมีอิสระที่จะสนับสนุนเป็นส่วนเสริมภาษา C ++ ที่ไม่ได้มาตรฐาน
constหมายถึงอ่านอย่างเดียว const int r = rand();ถูกกฎหมายอย่างสมบูรณ์แบบ
constexprเมื่อเทียบกับการconstเป็นพิเศษกับstlภาชนะบรรจุเช่นหรือarray bitset
switch()แถลงการณ์ไม่ใช่caseอย่างใดอย่างหนึ่ง ฉันเพิ่งถูกจับในเรื่องนี้เช่นกัน☺
ความแตกต่างระหว่างstatic constและ#defineคือที่ก่อนหน้านี้ใช้หน่วยความจำและในภายหลังไม่ได้ใช้หน่วยความจำสำหรับการจัดเก็บ ประการที่สองคุณไม่สามารถส่งที่อยู่ของผู้นั้นในขณะที่คุณสามารถส่งที่อยู่ของผู้ที่#define static constที่จริงมันขึ้นอยู่กับสถานการณ์ที่เราอยู่ภายใต้เราต้องเลือกหนึ่งในสองคนนี้ ทั้งคู่อยู่ในสภาพที่ดีที่สุดภายใต้สถานการณ์ที่แตกต่างกัน โปรดอย่าคิดว่าอันนี้ดีกว่าอันอื่น ... :-)
ถ้าเป็นอย่างนั้นเดนนิสริตชี่ จะเป็นคนที่ดีที่สุดคนเดียว ... ฮ่าฮ่าฮ่า ... :-)
constใช้หน่วยความจำ GCC (ทดสอบกับ 4.5.3 และรุ่นที่ใหม่กว่า) ปรับconst intให้เป็นตัวอักษรโดยตรงในรหัสของคุณเมื่อใช้ -O3 ดังนั้นหากคุณพัฒนา RAM ในระดับต่ำ (เช่น AVR) คุณสามารถใช้ C const ได้อย่างปลอดภัยหากคุณใช้ GCC หรือคอมไพเลอร์อื่นที่เข้ากันได้ ฉันไม่ได้ทดสอบ แต่คาดหวังว่า Clang จะทำสิ่งเดียวกัน btw
ใน C #defineเป็นที่นิยมมากขึ้น คุณสามารถใช้ค่าเหล่านั้นในการประกาศขนาดอาร์เรย์ตัวอย่างเช่น:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
ANSI C ไม่อนุญาตให้คุณใช้static consts ในบริบทนี้เท่าที่ฉันรู้ ใน C ++ คุณควรหลีกเลี่ยงมาโครในกรณีเหล่านี้ คุณสามารถเขียน
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
และออกไปstaticเพราะการเชื่อมโยงภายในถูกบอกเป็นนัยโดยconst[ใน C ++ เท่านั้น]
const int MY_CONSTANT = 5;ไฟล์หนึ่งไฟล์และเข้าถึงด้วยไฟล์extern const int MY_CONSTANT;อื่นได้ ฉันไม่สามารถหาข้อมูลใด ๆ ในมาตรฐาน (อย่างน้อย C99) เกี่ยวกับconstการเปลี่ยนพฤติกรรมเริ่มต้น "6.2.2: 5 หากการประกาศตัวบ่งชี้สำหรับวัตถุที่มีขอบเขตและไม่มีข้อกำหนดระดับการจัดเก็บการเชื่อมโยงของมันเป็นภายนอก"
barคือ VLA (อาร์เรย์ความยาวแปรผัน); คอมไพเลอร์มีแนวโน้มที่จะสร้างรหัสราวกับว่ามันมีความยาวคงที่
ข้อเสียเปรียบอีกข้อconstใน C คือคุณไม่สามารถใช้ค่าในการเริ่มต้นอื่นconstได้
static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;
// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND
* NUMBER_OF_HANDS;
แม้สิ่งนี้จะไม่ทำงานกับ const เนื่องจากคอมไพเลอร์ไม่เห็นว่าเป็นค่าคงที่:
static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!
ฉันยินดีที่จะใช้พิมพ์constในกรณีเหล่านี้มิฉะนั้น ...
static uint8_t const ARRAY_SIZE = 16;ทันใดนั้นการคอมไพล์ของคุณทั้งหมดจึงไม่ใช่เรื่องยากอีกต่อไปโดยเฉพาะอย่างยิ่งเมื่อ#define ARRAY_SIZE 256มีการฝังสิบชั้นลึกลงไปในส่วนหัวที่พันกัน ชื่อตัวพิมพ์ใหญ่ทั้งหมดARRAY_SIZEกำลังถามถึงปัญหา จอง ALL_CAPS สำหรับมาโครและห้ามกำหนดมาโครที่ไม่ได้อยู่ในรูปแบบ ALL_CAPS
constได้ นี่สามารถอัปโหลดได้มากขึ้น!
หากคุณสามารถหนีไปstatic constได้มีข้อดีมากมาย มันเป็นไปตามหลักการของขอบเขตปกติสามารถมองเห็นได้ในตัวดีบั๊กและโดยทั่วไปแล้วจะปฏิบัติตามกฎที่ตัวแปรเชื่อฟัง
อย่างไรก็ตามอย่างน้อยในมาตรฐาน C ดั้งเดิมมันคงไม่เป็นจริง หากคุณใช้#define var 5คุณสามารถเขียนint foo[var];เป็นการประกาศ แต่คุณไม่สามารถทำเช่นนั้นได้ (ยกเว้นเป็นส่วนขยายคอมไพเลอร์ "ด้วยstatic const int var = 5;นี่ไม่ใช่กรณีใน C ++ ที่ซึ่งstatic constรุ่นนี้สามารถใช้งานได้ทุกที่ที่เป็น#defineไปได้และฉันเชื่อว่า เป็นกรณีที่มี C99
อย่างไรก็ตามอย่าตั้งชื่อ#defineค่าคงที่ด้วยชื่อตัวพิมพ์เล็ก มันจะแทนที่การใช้ชื่อที่เป็นไปได้ใด ๆ จนกว่าจะสิ้นสุดของหน่วยการแปล ค่าคงที่มาโครควรอยู่ในเนมสเปซของตัวเองอย่างมีประสิทธิภาพซึ่งเป็นตัวพิมพ์ใหญ่ทั้งหมดซึ่งอาจเป็นส่วนนำหน้า
constใน C99 ยังคงไม่คงที่จริง คุณสามารถประกาศขนาดอาร์เรย์ด้วย a constใน C99 แต่เนื่องจาก C99 รองรับ Array Length Variable ด้วยเหตุผลนี้มันจะทำงานเฉพาะที่อนุญาต VLA ยกตัวอย่างเช่นแม้ใน C99, คุณยังไม่สามารถใช้กับขนาดของการประกาศอาร์เรย์สมาชิกในconst struct
const intขนาดได้อย่างสมบูรณ์ราวกับว่าเป็น C ++ const หรือมาโคร ไม่ว่าคุณต้องการขึ้นอยู่กับการเบี่ยงเบนของ GCC จากมาตรฐานนี้เป็นทางเลือกของคุณเองฉันจะไปกับมันด้วยตัวคุณเองเว้นแต่คุณจะมองข้ามโดยใช้คอมไพเลอร์อื่นกว่า GCC หรือ Clang จริง ๆ มีคุณสมบัติเดียวกันที่นี่ 3.7)
ควรใช้ const แทน #define เสมอ นั่นเป็นเพราะ const ได้รับการดูแลโดยคอมไพเลอร์และ #define โดย preprocessor มันเหมือน #define ตัวเองไม่ได้เป็นส่วนหนึ่งของรหัส (พูดคร่าว ๆ )
ตัวอย่าง:
#define PI 3.1416
คอมไพเลอร์ชื่อสัญลักษณ์ PI อาจไม่สามารถมองเห็นได้ มันอาจจะถูกลบออกโดย preprocessor ก่อนที่จะได้รับรหัสแหล่งแม้แต่คอมไพเลอร์ เป็นผลให้ชื่อ PI อาจไม่ได้รับการป้อนลงในตารางสัญลักษณ์ สิ่งนี้อาจสร้างความสับสนหากคุณได้รับข้อผิดพลาดระหว่างการคอมไพล์ที่เกี่ยวข้องกับการใช้ค่าคงที่เนื่องจากข้อความแสดงข้อผิดพลาดอาจอ้างถึง 3.1416 ไม่ใช่ PI ถ้า PI ถูกกำหนดไว้ในไฟล์ส่วนหัวที่คุณไม่ได้เขียนคุณจะไม่รู้ว่ามาจากไหน 3.1416
ปัญหานี้ยังสามารถครอบตัดในดีบักเกอร์ที่เป็นสัญลักษณ์อีกครั้งเนื่องจากชื่อที่คุณกำลังเขียนโปรแกรมอาจไม่อยู่ในตารางสัญลักษณ์
สารละลาย:
const double PI = 3.1416; //or static const...
#define var 5mystruct.varจะทำให้คุณเดือดร้อนถ้าคุณมีสิ่งที่ต้องการ
ตัวอย่างเช่น,
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
ตัวประมวลผลล่วงหน้าจะแทนที่และรหัสจะไม่คอมไพล์ ด้วยเหตุนี้สไตล์การเขียนโปรแกรมดั้งเดิมแนะนำให้ค่าคงที่ทั้งหมด#defineใช้อักษรตัวใหญ่เพื่อหลีกเลี่ยงความขัดแย้ง
ฉันเขียนโปรแกรมทดสอบอย่างรวดเร็วเพื่อแสดงความแตกต่าง:
#include <stdio.h>
enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};
#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32
int main(int argc, char *argv[]) {
printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);
return(0);
}
สิ่งนี้รวบรวมด้วยข้อผิดพลาดและคำเตือนเหล่านี้:
main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
^
โปรดทราบว่า enum ให้ข้อผิดพลาดเมื่อ define ให้คำเตือน
คำนิยาม
const int const_value = 5;
ไม่ได้กำหนดค่าคงที่เสมอไป คอมไพเลอร์บางตัว (เช่นtcc 0.9.26 ) เพียงจัดสรรหน่วยความจำที่ระบุด้วยชื่อ "const_value" การใช้ตัวระบุ "const_value" คุณไม่สามารถแก้ไขหน่วยความจำนี้ได้ แต่คุณยังสามารถแก้ไขหน่วยความจำโดยใช้ตัวระบุอื่น:
const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.
นี่หมายถึงคำจำกัดความ
#define CONST_VALUE 5
เป็นวิธีเดียวที่จะกำหนดค่าคงที่ซึ่งไม่สามารถแก้ไขได้ด้วยวิธีการใด ๆ
#defineสามารถแก้ไขได้โดยแก้ไขรหัสเครื่อง
5ออกมา แต่ไม่มีใครแก้ไขได้#defineเพราะเป็นมาโครตัวประมวลผลล่วงหน้า ไม่มีอยู่ในโปรแกรมไบนารี หากต้องการแก้ไขสถานที่ทั้งหมดที่CONST_VALUEใช้สถานที่แห่งนั้นต้องทำทีละสถานที่
#define CONST 5แล้วif (CONST == 5) { do_this(); } else { do_that(); }และคอมไพเลอร์กำจัดelseสาขา คุณเสนอให้แก้ไขรหัสเครื่องเพื่อเปลี่ยนCONSTเป็น 6 อย่างไร
#defineไม่ได้พิสูจน์กระสุน
#defineไม่ได้เป็นวิธีที่เหมาะสมที่จะทำซ้ำผลของการเปลี่ยนแปลงค่าของที่ วิธีเดียวที่ทำได้คือแก้ไขซอร์สโค้ดและคอมไพล์ใหม่
แม้ว่าคำถามจะเกี่ยวกับจำนวนเต็ม แต่ก็เป็นที่น่าสังเกตว่า #define และ enums นั้นไร้ประโยชน์หากคุณต้องการโครงสร้างหรือสตริงคงที่ สิ่งเหล่านี้มักจะถูกส่งผ่านไปยังฟังก์ชั่นเป็นตัวชี้ (จำเป็นต้องมีสตริงด้วยโครงสร้างจะมีประสิทธิภาพมากขึ้น)
สำหรับจำนวนเต็มถ้าคุณอยู่ในสภาพแวดล้อมแบบฝังตัวที่มีหน่วยความจำที่ จำกัด มากคุณอาจต้องกังวลเกี่ยวกับที่เก็บค่าคงที่และวิธีการเข้าถึงคอมไพล์ คอมไพเลอร์อาจเพิ่มสอง consts ในเวลาทำงาน แต่เพิ่ม #defines สองครั้งในเวลารวบรวม #define คงที่อาจถูกแปลงเป็นหนึ่งหรือมากกว่าหนึ่ง MOV [ทันที] คำแนะนำซึ่งหมายความว่าค่าคงที่จะถูกเก็บไว้อย่างมีประสิทธิภาพในหน่วยความจำโปรแกรม ค่าคงที่ const จะถูกเก็บไว้ในส่วน. const ในหน่วยความจำข้อมูล ในระบบที่มีสถาปัตยกรรมของ Harvard อาจมีความแตกต่างในด้านประสิทธิภาพและการใช้หน่วยความจำแม้ว่าจะมีขนาดเล็กก็ตาม พวกเขาอาจมีความสำคัญสำหรับการเพิ่มประสิทธิภาพฮาร์ดคอร์ของวงใน
อย่าคิดว่าจะมีคำตอบสำหรับ "ซึ่งดีที่สุดเสมอ" แต่อย่างที่ Matthieu กล่าว
static const
เป็นประเภทที่ปลอดภัย #defineแม้ว่าสัตว์เลี้ยงที่ใหญ่ที่สุดของฉันด้วยคือเมื่อการดีบักในVisual Studioคุณไม่สามารถดูตัวแปร มันทำให้เกิดข้อผิดพลาดที่ไม่สามารถหาสัญลักษณ์ได้
อีกทางเลือกหนึ่ง#defineซึ่งให้การกำหนดขอบเขตที่เหมาะสม แต่มีพฤติกรรมเหมือนค่าคงที่ "ของจริง" คือ "enum" ตัวอย่างเช่น:
enum {number_ten = 10;}
ในหลายกรณีมีประโยชน์ในการกำหนดประเภทที่แจกแจงและสร้างตัวแปรของประเภทเหล่านั้น หากทำเช่นนั้นตัวแก้ไขอาจสามารถแสดงตัวแปรตามชื่อการแจงนับของพวกเขา
ข้อแม้ที่สำคัญอย่างหนึ่งในการทำเช่นนั้น: ใน C ++ ประเภทที่แจกแจงมีความเข้ากันได้ที่ จำกัด กับจำนวนเต็ม ตัวอย่างเช่นโดยค่าเริ่มต้นเราไม่สามารถดำเนินการทางคณิตศาสตร์กับพวกเขา ฉันพบว่าเป็นพฤติกรรมเริ่มต้นที่แปลกประหลาดสำหรับ enums; ในขณะที่มันคงจะดีถ้ามีประเภท "เข้มงวด enum" เนื่องจากความปรารถนาที่จะมี C ++ โดยทั่วไปเข้ากันได้กับ C ฉันคิดว่าพฤติกรรมเริ่มต้นของประเภท "enum" ควรใช้แทนกันได้กับจำนวนเต็ม
intดังนั้นจึงไม่สามารถใช้ "enum hack" กับประเภทจำนวนเต็มอื่น ๆ ได้ ( ประเภทการแจงนับเข้ากันได้กับชนิดจำนวนเต็มที่กำหนดใช้งานบางอย่างไม่จำเป็นintแต่ในกรณีนี้ชนิดไม่ระบุชื่อดังนั้นไม่สำคัญ)
intตัวแปรการแจงนับ (ซึ่งคอมไพเลอร์ได้รับอนุญาตให้ทำ) และพยายามพยายามกำหนดให้ตัวแปรเช่นนั้น สมาชิกของการแจงนับของตัวเอง ฉันหวังว่าคณะกรรมการมาตรฐานจะเพิ่มวิธีการประกาศประเภทจำนวนเต็มแบบพกพาด้วยความหมายที่ระบุ แพลตฟอร์มใด ๆโดยไม่คำนึงcharถึงขนาดควรจะสามารถประกาศประเภทที่ห่อหุ้ม mod 65536 แม้ว่าคอมไพเลอร์จะต้องเพิ่มAND R0,#0xFFFFคำสั่งจำนวนมากหรือเทียบเท่า
uint16_tได้ แต่แน่นอนว่าไม่ใช่ประเภทการแจงนับ มันเป็นการดีที่จะให้ผู้ใช้ระบุชนิดจำนวนเต็มที่ใช้เพื่อแสดงชนิดการแจงนับที่กำหนด แต่คุณสามารถบรรลุเอฟเฟ็กต์แบบเดียวกันได้ด้วยการใช้typedeffor uint16_tและ a series #defineสำหรับแต่ละค่า
2U < -1Lว่าเป็นจริงและอื่น ๆ ว่าเป็นเท็จและตอนนี้เราติดอยู่กับข้อเท็จจริงที่ว่าแพลตฟอร์มบางแห่งจะใช้การเปรียบเทียบระหว่างuint32_tและint32_tลงชื่อ และบางคนไม่ได้ลงนาม แต่นั่นไม่ได้หมายความว่าคณะกรรมการไม่สามารถกำหนดผู้สืบทอดที่เข้ากันได้กับ C ที่มีประเภทซึ่งความหมายจะสอดคล้องกับคอมไพเลอร์ทั้งหมด
ความแตกต่างง่ายๆ:
ณ เวลาประมวลผลล่วงหน้าค่าคงที่จะถูกแทนที่ด้วยค่าของมัน ดังนั้นคุณไม่สามารถใช้โอเปอเรเตอร์ dereference กับ define แต่คุณสามารถใช้โอเปอเรเตอร์ dereference กับตัวแปรได้
อย่างที่คุณคิดสมมุติว่าเร็วขึ้นคงที่ const
ตัวอย่างเช่น:
#define mymax 100
printf("address of constant is %p",&mymax);คุณไม่สามารถทำ
แต่มี
const int mymax_var=100
printf("address of constant is %p",&mymax_var);ที่คุณสามารถทำได้
เพื่อให้ชัดเจนยิ่งขึ้นการกำหนดจะถูกแทนที่ด้วยค่าของมันในขั้นตอนการประมวลผลล่วงหน้าดังนั้นเราจึงไม่ได้เก็บตัวแปรใด ๆ ไว้ในโปรแกรม เรามีโค้ดจากเซ็กเมนต์ข้อความของโปรแกรมที่ใช้การกำหนด
อย่างไรก็ตามสำหรับ const คงที่เรามีตัวแปรที่ได้รับการจัดสรรที่ไหนสักแห่ง สำหรับ gcc const แบบคงที่จะถูกจัดสรรในส่วนข้อความของโปรแกรม
ด้านบนฉันต้องการบอกเกี่ยวกับผู้ดำเนินการอ้างอิงดังนั้นแทนที่การอ้างอิงด้วยการอ้างอิง
constคัดเลือก C ไม่ได้มีค่าคงที่ symbolica อื่น ๆ กว่าenum-ค่าคงที่ A const intคือตัวแปร คุณสับสนกับภาษาและการใช้งานเฉพาะ ไม่มีความต้องการที่จะวางวัตถุ และมันไม่เป็นความจริงแม้แต่น้อยสำหรับ gcc: โดยทั่วไปแล้วจะวางconstตัวแปรที่ผ่านการรับรองใน.rodataส่วน แต่นั่นก็ขึ้นอยู่กับแพลตฟอร์มเป้าหมาย &และคุณหมายถึงที่อยู่ของผู้ประกอบการ
เราดูรหัสแอสเซมเบลอร์ที่ผลิตบน MBF16X ... ตัวแปรทั้งสองส่งผลให้มีรหัสเดียวกันสำหรับการดำเนินการทางคณิตศาสตร์ (เช่นเพิ่มทันที)
ดังนั้นจึงconst intเป็นที่ต้องการสำหรับการตรวจสอบประเภทในขณะที่#defineเป็นแบบเก่า อาจเป็นเฉพาะคอมไพเลอร์ ดังนั้นตรวจสอบรหัสแอสเซมเบลอร์ของคุณ
ฉันไม่แน่ใจว่าถ้าฉันถูก แต่ในความเห็นของฉันเรียก#defineค่า d เร็วกว่าการเรียกตัวแปรอื่น ๆ ที่ประกาศตามปกติ (หรือค่า const) เป็นเพราะเมื่อโปรแกรมทำงานและจำเป็นต้องใช้ตัวแปรที่ประกาศตามปกติบางอย่างมันต้องข้ามไปยังตำแหน่งที่แน่นอนในหน่วยความจำเพื่อรับตัวแปรนั้น
ในทางตรงกันข้ามเมื่อใช้#defineค่า d โปรแกรมไม่จำเป็นต้องข้ามไปยังหน่วยความจำที่จัดสรรใด ๆ เพียงใช้ค่า ถ้า#define myValue 7และเรียกโปรแกรมก็จะทำงานตรงเช่นเดียวกับเมื่อมันเป็นเพียงแค่การโทรmyValue7