今天看MFC程序设计的时候,有这样一段源代码:

        struct {
            LOGPALETTE lp;
            PALETTEENTRY ape[63];
        } pal;

        LOGPALETTE* pLP = (LOGPALETTE*) &pal;
        pLP->palVersion = 0x300;
        pLP->palNumEntries = 64;

        for (int i=0; i<64; i++) {
            pLP->palPalEntry[i].peRed = 0;
            pLP->palPalEntry[i].peGreen = 0;
            pLP->palPalEntry[i].peBlue = 255 - (i * 4);
            pLP->palPalEntry[i].peFlags = 0;
        }

    可以查到,结构体LOGPALETTE的定义如下:

typedef struct tagLOGPALETTE {
    WORD        palVersion;
    WORD        palNumEntries;
    PALETTEENTRY        palPalEntry[1];
} LOGPALETTE;

  初看之下,觉得很奇怪,平时一般没这么做过(是不是觉得那个结构体指针的强制类型转换很是奇妙啊,还有后面循环中的数组访问不是越界了吗?)

仔细分析,发现其实没问题的。结构体就是一块内存区域,里面依次存放着各个成员变量,当把它们组织在一起的时候,它们是连续存放的。所以就有后面的pal结构体中的数组恰好接上了原来LOGPALETTE数组中大小为1的数组,可以连续访问,至于指针的强制类型转换:因为指针变量的大小都是一样的,类型转换只是换一种方式解释它所指向的内存区而已。为了验证这个想法, 我写了一个小的程序:

#include<stdio.h>
typedef struct tagIntegerArray{
 int NumInteger;
 int a[1];
}IntegerArray;
void main(){
 struct {
  IntegerArray ia;
  int m[31];
 }ib;
 IntegerArray* pIa = (IntegerArray*)&ib;
 pIa->NumInteger  = 32;
 for(int i = 0; i < 32; i++){
  pIa->a[i] = i + 1;
 }
 for(int j = 0; j < 32; j++){
  printf("%d\n", pIa->a[j]);
 }
}

可以说,从这里,又学到了一招,怎么解决C数组中的不定长数组问题、


Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐