อาร์เรย์ที่ปรับเปลี่ยนได้หลากหลายที่ขอบเขตไฟล์


87

ฉันต้องการสร้างอาร์เรย์คงที่เพื่อใช้กับไฟล์การใช้งาน Objective-C ของฉันที่คล้ายกับสิ่งนี้ที่ระดับบนสุดของไฟล์ ".m" ของฉัน:

static const int NUM_TYPES = 4;
static int types[NUM_TYPES] = { 
  1,
  2, 
  3, 
  4 };

ฉันวางแผนที่จะใช้ในNUM_TYPESภายหลังในไฟล์ดังนั้นฉันจึงต้องการใส่ไว้ในตัวแปร

อย่างไรก็ตามเมื่อฉันดำเนินการนี้ฉันได้รับข้อผิดพลาด

"ประเภท" ที่ปรับเปลี่ยนได้หลากหลายที่ขอบเขตไฟล์ "

ฉันรวบรวมว่าสิ่งนี้อาจเกี่ยวข้องกับขนาดอาร์เรย์ที่เป็นตัวแปร (ฉันไม่ได้รับข้อความนี้เมื่อฉันใส่ลิเทอรัลจำนวนเต็มเช่นstatic int types[4])

ฉันต้องการแก้ไขปัญหานี้ แต่บางทีฉันอาจจะคิดผิดทั้งหมด ... ฉันมี 2 เป้าหมายที่นี่:

  1. มีอาร์เรย์ที่สามารถเข้าถึงได้ทั่วทั้งไฟล์
  2. ในการห่อหุ้มNUM_TYPESเป็นตัวแปรดังนั้นฉันจึงไม่มีตัวอักษรเดียวกันกระจัดกระจายอยู่ตามที่ต่างๆในไฟล์ของฉัน

ข้อเสนอแนะใด ๆ ?

[แก้ไข] พบสิ่งนี้ในคำถามที่พบบ่อยเกี่ยวกับ C: http://c-faq.com/ansi/constasconst.html


2
จะเกิดอะไรขึ้นถ้าคุณทำมันเป็นคำจำกัดความแทน? #define kNUM_TYPES 4เหรอ?
Jorge Israel Peña

มันใช้งานได้ ... ด้วยเหตุผลบางอย่างฉันพยายามหลีกเลี่ยงการใช้พรีโปรเซสเซอร์เพราะฉันคิดว่าฉันจำได้ว่าอ่านที่ไหนสักแห่ง แต่ฉันเพิ่งหาข้อมูลเพิ่มเติมและไม่พบเหตุผลที่ดีที่จะไม่ใช้ในกรณีนี้ ฉันคิดว่ามันอาจจะเป็นที่ต้องการน้อยกว่าถ้าฉันสร้างอ็อบเจกต์ในพรีโปรเซสเซอร์ (เช่น@"An NSString literal") สิ่งเดียวที่ผิดพลาดกับโค้ดส่วนหนึ่งของคุณคือไม่จำเป็นต้องมีอัฒภาค
แซม

อ่าใช่ขอบคุณที่แจ้งให้ทราบและดีใจที่ช่วยได้
Jorge Israel Peña

คำตอบ:


63

เหตุผลสำหรับคำเตือนนี้คือconst ใน c ไม่ได้หมายถึงค่าคงที่ หมายความว่า "อ่านอย่างเดียว" ดังนั้นค่าจะถูกเก็บไว้ที่ที่อยู่หน่วยความจำและอาจเปลี่ยนแปลงได้ตามรหัสเครื่อง


3
การแก้ไขออบเจ็กต์ที่กำหนดไว้const(เช่นโดยการส่งออกconstจากตัวชี้และเก็บค่า) เป็นพฤติกรรมที่ไม่ได้กำหนด ดังนั้นค่าของวัตถุดังกล่าวจึงเป็นค่าคงที่เวลาคอมไพล์หรือรันไทม์ (ขึ้นอยู่กับระยะเวลาการจัดเก็บ) ไม่สามารถใช้ค่านี้ในนิพจน์คงที่เพียงเพราะมาตรฐาน C ไม่ได้บอกว่าสามารถเป็นได้ ( constอนุญาตให้ส่งและจัดเก็บค่าได้หากวัตถุปลายทางถูกกำหนดโดยไม่มีconstหรือจัดสรรแบบไดนามิกตัวอักษรสตริงconstจะไม่ถูกเขียน แต่ไม่สามารถเขียนถึงได้)
jilles

3
@jilles "อาจเปลี่ยนแปลงได้ด้วยรหัสเครื่อง" ไม่ได้หมายความว่าผู้เขียนคำตอบนี้หมายความว่า "อาจมีการเปลี่ยนแปลงโดยรหัส C" นอกจากนี้ยังมีเหตุผลที่ดีอีกประการหนึ่ง: อาจมีexternค่าคงที่ใน TU ที่แตกต่างกันซึ่งไม่ทราบค่านี้เมื่อรวบรวม TU ปัจจุบัน

15
วิธีปรับปรุงคำตอบนี้คือการแสดงวิธีแก้ไขปัญหานี้
George Stocker

33

หากคุณกำลังจะใช้ตัวประมวลผลล่วงหน้าตามคำตอบอื่น ๆ คุณสามารถกำหนดให้คอมไพเลอร์กำหนดค่าของโดยNUM_TYPESอัตโนมัติ:

#define NUM_TYPES (sizeof types / sizeof types[0])
static int types[] = { 
  1,
  2, 
  3, 
  4 };

ว้าวเจ๋งมาก ... ฉันไม่รู้ว่ามันเป็นไปได้ ฉันคิดว่าค่าใช้จ่ายของการคำนวณนี้มีค่าเล็กน้อย ฉันอาจคิดว่าคอมไพเลอร์สามารถปรับให้เป็นค่าคงที่ได้หรือไม่?
แซม

2
ใช่ผลลัพธ์ของsizeofบนวัตถุเช่นนั้นคือค่าคงที่เวลาคอมไพล์
คาเฟ่


11

นอกจากนี้ยังสามารถใช้การแจงนับ

typedef enum {
    typeNo1 = 1,
    typeNo2,
    typeNo3,
    typeNo4,
    NumOfTypes = typeNo4
}  TypeOfSomething;

4

ตามที่อธิบายไว้แล้วในคำตอบอื่น ๆconstใน C หมายความว่าตัวแปรเป็นแบบอ่านอย่างเดียว มันยังคงเป็นค่ารันไทม์ อย่างไรก็ตามคุณสามารถใช้enumเป็นค่าคงที่จริงใน C:

enum { NUM_TYPES = 4 };
static int types[NUM_TYPES] = { 
  1, 2, 3, 4
};

3

Imho นี่เป็นข้อบกพร่องในคอมไพเลอร์ c หลายตัว ฉันทราบข้อเท็จจริงว่าคอมไพเลอร์ที่ฉันทำงานด้วยไม่ได้เก็บตัวแปร "static const" ไว้ที่แอดเดรส แต่แทนที่การใช้ในโค้ดด้วยค่าคงที่มาก สิ่งนี้สามารถตรวจสอบได้เนื่องจากคุณจะได้รับการตรวจสอบเดียวกันสำหรับโค้ดที่ผลิตเมื่อคุณใช้คำสั่ง prerocessors #define และเมื่อคุณใช้ตัวแปร const แบบคงที่

ไม่ว่าจะด้วยวิธีใดคุณควรใช้ตัวแปร const แบบคงที่แทน #defines เมื่อใดก็ตามที่เป็นไปได้เนื่องจากคงที่เป็นประเภทที่ปลอดภัย


ฟังดูไม่ดีนักเนื่องจากคุณสามารถรับที่อยู่ของstatic constตัวแปรได้ พฤติกรรมที่คุณอธิบายอาจเป็นการเพิ่มประสิทธิภาพที่ถูกต้อง แต่ก็ไม่ใช่สิ่งที่จะใช้ได้ผลเสมอไป
ผ่อนคลาย

มันเป็นเรื่องปกติดี เป็นเรื่องปกติที่คอมไพเลอร์ C จะแทนที่การใช้ตัวแปรส่วนกลางของ const แต่ละตัวด้วยค่าคงที่ทุกที่ที่เป็นไปได้ หากการอ้างอิงถึงตัวแปรทั้งหมดถูกแปลงเป็นค่าคงที่แล้วคอมไพเลอร์สามารถลบออกทั้งหมดได้ หากคุณใช้ที่อยู่ที่ใดก็ตามจะไม่ถูกลบออก ไม่มีการเปลี่ยนแปลงใด ๆ ที่ตามมาตรฐานภาษา C ไม่อนุญาตให้โกลบอลอาร์เรย์ที่มีตัวแปรเป็นขนาดไม่ว่าตัวแปรจะเป็น const หรือไม่ก็ตาม
Evan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.