之前在C语言结构体常见使用方法已经说过结构体其实是对一块空间的划分与使用,那么无论怎么折腾怎么改,都是这一亩三分地,只要找到相应地址,直接改也不奇怪(C的一大核心就是指针和地址)。
1.字符串覆盖其他成员:
简而言之,写入的字符串超出了长度,导致后边的成员被覆盖。
例如这种结构体和操作:
#include <stdio.h>
#include <string.h>
typedef struct{
int iTest;
char pcArray[20];
int iParam;
}s;
main(){
s s1;
s1.iParam = 5;
s1.iTest = 6;
printf("iTest:\t%p:%d\n",&s1.iTest,s1.iTest);
printf("iParam:\t%p:%d\n",&s1.iParam,s1.iParam);
strncpy(s1.pcArray,"Hello World,Hello World",23);
printf("pcArray:\t%p:%s\n",&s1.pcArray,s1.pcArray);
printf("iTest:\t%p:%d\n",&s1.iTest,s1.iTest);
printf("iParam:\t%p:%d\n",&s1.iParam,s1.iParam);
}
结果如下
[root@j struct]# gcc array.c
[root@j struct]# ./a.out
iTest: 0xbfbebc64:6
iParam: 0xbfbebc7c:5
pcArray: 0xbfbebc68:Hello World,Hello World
iTest: 0xbfbebc64:6
iParam: 0xbfbebc7c:6581362
因为字符串的超界操作,iParam已经被修改
=========================================================================================================================
补充(20160313):浏览量大,肯定是大家有需求,还是多补点吧。
关于嵌套结构体大小的计算:
关于结构体内部嵌套结构体,有以下两种写法容易产生混淆:
#include<iostream>
using namespace std;
struct ss1{
int a;
double b;
struct aa{
int aa;
double cc;
}aa;
int c;
}ss1;
struct ss2{
int a;
double b;
struct aa{
int aa;
double cc;
};
int c;
}ss2;
int main()
{
cout << sizeof(ss1) << endl;
cout << sizeof(ss2) << endl;
}
前者是在结构体ss1中声明
并定义了一个aa结构体对象aa,后者只是对结构体类型aa进行了声明,实际不包含,所以ss1与ss2大小不同,差12bytes。
关于C++结构体派生时的对齐优化:
因为派生类空间是在基类部分后边追加的,且互相不侵犯,等于另起炉灶,所以发生派生时,对齐不可优化。
32位,#pragma pack(4),正常情况下(如果前后是正常的,本例前是4bytes的int a,所以是正常对齐的),两个连续声明的char b和char c只占用2bytes(如果后边是个short),考虑到后边的int d,也只不过占用4bytes。但是发生继承时,就不能这样算了:
#include<iostream>
using namespace std;
struct A{
int a;
char b;
};
struct B:A{
char c;
int d;
long long e;
};
int main(){
cout << sizeof(struct A) << endl;
cout << sizeof(struct B) << endl;
}
中间两个char类型b和c看起来“连着”,实际上因为分属不同的“类部分”所以分别占用4bytes空间,最后B的大小是24,而不是20。