birlik ve yapı hafıza paylaşımı

Nov 05 2020

Bir birlik içindeki iki yapıyı içeren bir sorunun cevabını bulmaya çalışıyordum.

Soruyu çevrimiçi hata ayıklayıcıya yazdım, bulduğum cevabı ve gerçek cevap birbirlerine el vermiyor. Biri açıklama ile cevapta bana yardım edebilir mi?

#include <stdio.h>

int main()
{
    union{
            struct{
                       char c[2];
                       char ch[2];
                  }s;
           struct {
                       short int i;
                       short int j;
                 }st;
       }u={12,1,15,1};

  printf("%d%d",u.st.i,u.st.j);
}

cevap 268ve271

Yanıtlar

1 0___________ Nov 05 2020 at 18:44

Ondalık sayılar bu tür testler için pek iyi değildir. Ayrıca tüm uyarıları da etkinleştirmelisiniz. Eğer bunu yaparsan alacaksın

<source>:25:8: warning: missing braces around initializer [-Wmissing-braces]

Öyleyse programınızı biraz yeniden yazalım:

int main()
{
    union
    {
        struct
        {
            char c[2];
            char ch[2];
        }s;
        struct 
        {
            short int i;
            short int j;
        }st;
    }u={.s = {{0x12,0x01},{0x15,0x01}}};  //better to show compiler what you want to initialize

  printf("%04hx %04hx",u.st.i,u.st.j);
}

Ve sonuç:

0112 0115

ilklendirmede kullandığımız sayıları açıkça gösteriyor. Rakamlar bize, bu sistemin en az anlamlı baytın ilk yerleştirildiği küçük endian sistemini kullandığını gösteriyor.

Derleyicinin gerekli herhangi bir dolguyu eklemekte özgür olduğunu bilmelisiniz. Bundan kaçınmak için derleyici uzantıları - yapı paketi kullanmanız gerekir.

1 Lundin Nov 05 2020 at 18:38
  • Onaltılık değiştirerek bu daha mantıklı başlayın: {0xC,0x1,0xF,0x1}. Bu, ondalık tabana / ondalık tabandan dönüştürme konusunda endişelenmeden, bellekte depolandıkları haliyle baytları görüntülememizi sağlar.
  • A'yı başlatırken union, ilk üye başlatılır, bu durumda struct s.
  • Yazmak daha temiz olurdu { {{0xC,0x1}, {0xF,0x1}} }ama ne yazık ki C, iç yapıların / dizilerin küme parantezlerinin çıkarılmasına izin vererek, sırf yapabildiğimiz için ilklendirme listelerimize dikkatsizce yazılmış saçmalıklar koymamızı sağlar.
  • Bir charbayt dizisinin bellek sırası, herhangi bir sistemde her zaman yukarıdan aşağıya doğrudur: ilk bayt en az önemli adrestedir. Yani: 0xC 0x1 0xF 0x1.
  • Açıkça söylemek gerekirse, derleyici yanlış hizalamayı telafi etmek için struct / union üyeleri arasında herhangi bir yere struct padding baytları eklemekte özgürdür. Bu özel durumda olmaz, ancak örneğin kullanırsak olur char c[3].
  • Şort kullanarak bu hafıza alanına "pun" yazdığınızda, kısa 1 bayttan büyük olduğu ve bir tamsayı türü olduğu için, bunlar kalıcılığa göre okunur.
  • Küçük bir endian CPU'da, bu nedenle, her bir kısay, 0xC'nin en az anlamlı bayt olduğunu varsayarsınız ve böylece ilk kısa, 010Conaltılık olarak sona erer .

Kodunuzu hex'e çevirirsek, daha net olmalıdır:

#include <stdio.h>

int main()
{
    union{
            struct{
                       char c[2];
                       char ch[2];
                  }s;
           struct {
                       short int i;
                       short int j;
                 }st;
       }u={ {{0xC,0x1}, {0xF,0x1}} };

  printf("%.4X\n%.4X",u.st.i,u.st.j);
}

Küçük endian işlemcide çıktı:

010C

010F

10Ch = 268d ve benzeri.