Saya telah menulis kode contoh sederhana (juga tersedia di ideone) untuk menunjukkan di mana saya menemukan masalah. Ukuran mengembalikan hasil yang salah jika konstanta s. Di bawah ini adalah file main.c.

#include <stdint.h>
#include <stdio.h>

// comment this option if you know what is UB and want to avoit it 
#define I_DONT_KNOW_WHAT_IS_UB ( 1 )

struct _sa {
    uint32_t w;
    uint8_t const a[];
};

uint8_t const a[] = { 7,6,5,4,3,2,1,0 };

struct _sa const s = {
    .w = 8,
    .a = { 7,6,5,4,3,2,1,0 },
};

char const b[] = "line";

int main(void)
{
    #ifdef I_DONT_KNOW_WHAT_IS_UB
    printf("sizeof(a) = %d \n", (int)sizeof(a)); // = 8
    printf("sizeof(s) = %d \n", (int)sizeof(s)); // = 4
    printf("sizeof(b) = %d \n", (int)sizeof(b)); // = 5
    #else
    printf("sizeof(a) = %zu \n", sizeof(a)); // = 8
    printf("sizeof(s) = %zu \n", sizeof(s)); // = 4
    printf("sizeof(b) = %zu \n", sizeof(b)); // = 5
    #endif

    return 0;
}

Saya menggunakan ubuntu yang sudah tua:

uname -a
Linux imbearr 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

gcc --version
gcc (Ubuntu 9.3.0-11ubuntu0~14.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gcc main.c -o szof -Xlinker -Map=szof.map
grep -C 1 "\bs\b" ./szof.map 
                0x00000000004005e8                a
                0x00000000004005f0                s
                0x00000000004005fc                b

Jadi saya telah memeriksa ukuran melalui file peta tautan: 0x4005fc - 0x4005f0 = 12, 0x4005f0 - 0x4005e8 = 8.

Mengapa saya mendapatkan hasil seperti itu, apakah ini batasan atau bug gcc, mungkin ini kesalahan saya?

0
imbearr 11 Mei 2021, 16:55

2 jawaban

Jawaban Terbaik

Menanyakan ukuran struktur dengan anggota larik fleksibel hanya memberikan ukuran dasar struktur, tanpa anggota larik. C 2018 6.7.2.1 18 mengatakan:

… Dalam kebanyakan situasi, anggota array fleksibel diabaikan. Secara khusus, ukuran struktur seolah-olah anggota larik fleksibel dihilangkan kecuali bahwa itu mungkin memiliki lebih banyak bantalan tambahan daripada yang tersirat dari penghilangan itu ...

Jadi, sizeof s adalah ukuran yang akan dimiliki struktur jika anggota larik fleksibel a tidak ada, kecuali mungkin memiliki bantalan tambahan. Karena anggota uint32_t w; memerlukan empat byte, dan kompiler Anda tidak memasukkan bantalan tambahan dalam kasus ini, ukuran strukturnya adalah empat byte.

Catatan

Padding ekstra muncul dalam kasus seperti ini:

struct foo
{
    char c;
    int array[];
};

Dalam implementasi di mana int membutuhkan penyelarasan empat byte, kompiler akan memastikan anggota array disejajarkan dengan memasukkan tiga byte setelah anggota c, jadi sizeof (struct foo) akan menjadi empat.

2
Eric Postpischil 11 Mei 2021, 14:25

sizeof mengembalikan ukuran tipe parameter.

Jadi saat Anda menelepon sizeof(b), Anda sebenarnya bertanya, "Berapa ukuran struct _sa?"

Ukuran struct _sa adalah 4 byte, karena elemen .w membutuhkan 4 byte, dan elemen .a adalah array fleksibel yang membutuhkan nol-byte, karena array, seperti yang didefinisikan dalam jenis, tidak memiliki ukuran yang ditentukan.

5
abelenky 11 Mei 2021, 19:48