ตัวเลือกใดดีกว่าที่จะใช้ในข้อความด้านล่างใน 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 5
enum { 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. และอย่าลืมอีกทางเลือกหนึ่งที่ก่อให้เกิดค่าคงที่จริงใน enum
C.
ใน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 const
s ในบริบทนี้เท่าที่ฉันรู้ ใน 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 5
mystruct.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
ได้ แต่แน่นอนว่าไม่ใช่ประเภทการแจงนับ มันเป็นการดีที่จะให้ผู้ใช้ระบุชนิดจำนวนเต็มที่ใช้เพื่อแสดงชนิดการแจงนับที่กำหนด แต่คุณสามารถบรรลุเอฟเฟ็กต์แบบเดียวกันได้ด้วยการใช้typedef
for 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
และเรียกโปรแกรมก็จะทำงานตรงเช่นเดียวกับเมื่อมันเป็นเพียงแค่การโทรmyValue
7