ความต้องการของวงเล็บปีกกาว่างเปล่า '{}' ในตอนท้ายของอาร์เรย์ struct คืออะไร?


59

ฉันกดรหัส ใน Linux kernel:

static struct ctl_table ip_ct_sysctl_table[] = {
    {
        .procname   = "ip_conntrack_max",
        .maxlen     = sizeof(int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec,
    },
    // ...
    {
        .procname   = "ip_conntrack_log_invalid",
        .maxlen     = sizeof(unsigned int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec_minmax,
        .extra1     = &log_invalid_proto_min,
        .extra2     = &log_invalid_proto_max,
    },
    { }
};

นี่อาร์เรย์ของ structs { }ปลายกับ มันมีวัตถุประสงค์อะไรเพิ่ม?
โดยวิธีการบิตเหนือรหัสนี้มีอาร์เรย์ของ structsอื่น แต่ไม่มีวงเล็บปีกกาว่างเปล่าในตอนท้าย

เมื่อใดที่ฉันควรใช้วงเล็บปีกกาว่างที่ท้ายอาร์เรย์ของ struct


1
อืมจะเกิดอะไรขึ้นถ้ามันเพิ่มสัญญาณของจุดสิ้นสุดของอาร์เรย์เช่น 0 สัญญาณจุดสิ้นสุดของสตริง? เพียงแค่คาดเดา
Eraklon

4
นี่คือส่วนขยาย GCC ที่ไม่ได้มาตรฐาน และด้วยเหตุนี้มันน่าจะมาพร้อมกับเอกสารน้อยมากหรือไม่มีเลย ... ฉันเพิ่งอ่านเอกสารทั้งหมดและฉันไม่สามารถหาอะไรเกี่ยวกับรายการ initializer struct ที่ว่างเปล่าได้ -pedanticแต่มันรวบรวมเว้นแต่คุณจะบังคับให้เข้มงวดกับมาตรฐาน ISO
Lundin

9
อย่างไรก็ตามมันเป็นค่า "sentinel" ซึ่งเป็นรายการที่มีทุกสิ่งที่ตั้งค่าเป็นศูนย์ / NULL เพื่อทำเครื่องหมายจุดสิ้นสุดของอาร์เรย์
Lundin

ยามรักษาการณ์ยังเป็นคนธรรมดาในCPython โมดูลส่วนขยาย
MaxPowers

คำตอบ:


38

การเปลี่ยนแปลงนี้เป็นส่วนหนึ่งของsysctl net: ลบรหัสไบนารี sysctl ที่ไม่ได้ใช้ที่กระทำโดย Eric W. Biederman เปลี่ยนการเริ่มต้นขององค์ประกอบสุดท้ายของip_ct_sysctl_tableอาร์เรย์จาก{0}เป็น{}(และทำการเปลี่ยนแปลงคล้ายกับการเริ่มต้นอาร์เรย์อื่น ๆ อีกมากมาย)

{0}รูปแบบที่ดูเหมือนว่าจะได้รับรอบมากอีกต่อไปแม้ว่าทั้งสอง{0}หรือ{}ครั้งสุดท้ายองค์ประกอบการเริ่มต้นเป็นปกติ (ในซอร์สโค้ด Linux) อย่างชัดเจนเรียกว่าTerminating entryดังนั้นจึงมีแนวโน้มที่จะนำเสนอรูปแบบที่จะช่วยให้การบริโภคอาร์เรย์เหล่านี้โดยไม่ทราบความยาวของพวกเขา ยกเลิกการสิ้นเปลืองเมื่อกดปุ่มรายการที่ยกเลิกการกำหนดค่าเริ่มต้นเป็นศูนย์ เช่นสำหรับอาร์เรย์ที่คล้ายกันในsound/aoa/fabrics/snd-aoa-fabric-layout.cเจตนาของการเริ่มต้นเป็นศูนย์จะถูกกล่าวถึงอย่างชัดเจนแม้ในความคิดเห็นเช่น:

static struct codec_connection toonie_connections[] = {
  {
      .connected = CC_SPEAKERS | CC_HEADPHONE,
      .codec_bit = 0,
  },
  {} /* terminate array by .connected == 0 */
};

11
เป็นที่น่าสนใจที่จะทราบเหตุผลของพวกเขาสำหรับการวางมาตรฐาน C แทนส่วนขยาย GCC ที่เทียบเท่ากับการใช้งาน 100% สิ่งที่มันทำคือป้องกันโค้ดจากการคอมไพล์บนคอมไพเลอร์มาตรฐาน นั่นคือที่คาดคะเนได้เทียบเท่า 100% เนื่องจาก gcc ดูเหมือนจะไม่บันทึกคุณสมบัตินี้ ... นี่ไม่ใช่อาร์เรย์ที่มีความยาวเป็นศูนย์ แต่เป็นรายการตัวเริ่มต้นที่ว่างเปล่า
Lundin

@Lundin จะไม่int arr[] = {}(ระบุว่าเรากำลังใช้ส่วนขยาย initializer ว่างเปล่าของ GNU) ทำให้เกิดอาร์เรย์ว่างเปล่า เช่นขนาดของสิ่งarrมีชีวิต0?
dfri

1
@Lundin: หน้า cppreference มีความขัดแย้งกับถ้อยคำของ ISO / IEC 9899: 2011 ซึ่งอนุญาตให้ใช้ ((6.7.9 (21)) ไม่มีการเริ่มต้นจะ "น้อยลง" อย่างแน่นอนกว่าสมาชิกของการรวม นั่นไม่ใช่ส่วนขยายคอมไพเลอร์ที่แปลกประหลาด แต่ถูกต้องตามกฎหมาย C.
Damon

2
@Damon มันไม่ถูกต้อง C และเป็นที่รู้จักกันดี ... รวบรวมกับ gcc -pedantic-errors เพื่อให้เข้าใจว่าทำไมคุณต้องอ่านไวยากรณ์ที่แท้จริงสำหรับรายการ initializer ที่ด้านบนของ 6.7.9 ต้องมี initializer อย่างน้อยหนึ่งตัว อธิบายที่นี่: stackoverflow.com/questions/17589533/... { initializer-list }รายการตัวกำหนดค่าเริ่มต้นเฉพาะ: designation(opt) initializerหรือinitializer-list , designation(opt) initializer
Lundin

2
@Lundin ในกรณีนี้โดยเฉพาะไม่มีความคิด แต่ส่วนขยาย gcc ถูกใช้อย่างกว้างขวางในเคอร์เนล linux
bobsburner

20

คุณอาจคุ้นเคยกับสตริงที่ไม่มีการสิ้นสุด ctl_table ip_ct_sysctl_table[]เป็นอาร์เรย์ที่สิ้นสุดด้วยศูนย์เช่นรายการสุดท้ายที่มีสมาชิกทั้งหมดเป็นศูนย์


1
ดังนั้นเมื่อผ่านอาร์เรย์คุณรู้ว่าคุณได้มาถึงจุดสิ้นสุดเมื่อเช่นprocnameเป็นโมฆะหรือmaxlenเป็นศูนย์
พอลโอกิลวี่

1
@PaulOgilvie: ดีตัวอย่างไม่สมบูรณ์ procnameอาจเป็นchar[100]ในกรณีที่มัน""ไม่ใช่โมฆะ แต่อย่างอื่นใช่
MSalters

13

ความต้องการของวงเล็บปีกกาว่างเปล่า '{}' ในตอนท้ายของอาร์เรย์ struct คืออะไร?

เพื่อให้ชัดเจน: ไม่จำเป็นต้องใช้ "วงเล็บปีกกาว่างเปล่า '{}' ที่ท้ายอาร์เรย์อาร์เรย์" เพื่อให้เป็นไปตามข้อกำหนดด้านไวยากรณ์ของ C

เมื่อใดที่ฉันควรใช้วงเล็บปีกกาว่างที่ท้ายอาร์เรย์ของ struct

เมื่อรหัสต้องการค่าแมวมอง

บางครั้งมันก็มีประโยชน์สำหรับโปรแกรมที่จะมีองค์ประกอบอาร์เรย์สุดท้ายของศูนย์ทั้งหมด - แน่นอนในการตรวจสอบปลาย ความต้องการมาจากการใช้อาเรย์ของแอปพลิเคชันctl_table ip_ct_sysctl_table[]ไม่ใช่จากภาษาซีที่ต้องการ


9

เป็นองค์ประกอบเริ่มต้นหนึ่งศูนย์ที่ส่วนท้ายของอาร์เรย์เพื่อเพิ่มจำนวนองค์ประกอบของอาร์เรย์หนึ่งรายการ

พิจารณาตัวอย่างเล็ก ๆ นี้:

#include <stdio.h>

struct Test
{
  int x;
  int y;
} arr[] =
{
    {1,2},
    {3,4},
//  {}
};

int main(void) {
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

ขนาดของarrอาเรย์จะเปลี่ยนไปถ้าคุณไม่ใส่เครื่องหมายข้อคิดเห็น{}ในตอนท้ายของรายการอาเรย์เริ่มต้น

ขาออก:

ด้วย // {}(อาร์เรย์มี 2 องค์ประกอบ)

2

ด้วย {}(อาร์เรย์มี 3 องค์ประกอบ)

3

คำอธิบายเพิ่มเติม:

ip_ct_sysctl_tableอาร์เรย์จะใช้เฉพาะในสถานที่เดียวคือที่นี่:

in->ctl_table = kmemdup(ip_ct_sysctl_table,
                sizeof(ip_ct_sysctl_table),
                GFP_KERNEL);

เสริมเพิ่มขนาดรวม{}ip_ct_sysctl_table


1
นั่นไม่ใช่ "เพื่อเพิ่มจำนวนองค์ประกอบของอาร์เรย์" แต่เพื่อส่งสัญญาณจุดสิ้นสุดของอาร์เรย์
พอลโอกิลวี่

6
ฮ่า ๆ ๆ ความคิดคือไม่มีใครสามารถอธิบายได้อย่างสมบูรณ์ด้วยความมั่นใจแน่นอน คำแถลงความมั่นใจที่ใกล้ที่สุดคือคำว่า{ }initializer แต่ทำไมยังไม่ชัดเจน ดังนั้นสำหรับตอนนี้คำอาจเป็นความคิดที่ดี :)
ryyker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.