结构体分析

例如:
    当需要一个容器,能存储5个数据,者5个数据有1字节的,有2字节的也有4字节的时,用数组
不能满足要求了;此时需要用到结构;
 
1.关于结构
1)结构的定义
struct st //struct是一个关键字 st是用户自己定义的一个名字    
{    
    //可以定义多种类型
    int a;
    char b;
    short c;
};
 
2)结构的使用
void Function(person p)    
{    
    st s;    //声明一个自定义结构类型的数据;
    s.a = 10;    //给结构中的数据赋值
    s.b = 20;
    s.c = 30;
}    
说明:结构体在定义的时候,除了自身以外,可以使用任何类型。
也可以再结构中使用结构;
struct st1    
{    
    int a;
    int b;
};    
struct st2    
{    
    char a;
    short b;
    int arr[10];
    st1 s;
};    
void Funtion()    
{    
    st2 s2;
    
    s2.a = 'A';
    s2.b = 12;
    s2.arr[0] = 1;
    s2.arr[1] = 2;
    s2.arr[3] = 3;
    s2.s.a = 100;
    s2.s.b = 200;
    
    printf("%d\n",s2.s.a);
}
 
3)结构作返回值
代码:
struct student{
    char sex;
    int age;
    int score;
};
 
student fun()    
{    
    student s;
    s.sex = 1;
    s.age = 12;
    s.score = 100;
    return s;
}
 
int main(int argc, char* argv[])
{    
    student s = fun();
    getchar();
    return 0;
}
反汇编:
调用fun函数前:
    如果要返回一个结构,外层函数在编译时会给返回值预留空间;
    此时push进去的就是外层函数用来存储返回值的地址;
返回值:
总之:
    将结构体作为参数或返回值时,需要对一大片内存来回复制,非常消耗内存;
    最好不要用结构体当参数或返回值;
    可以将结构体定义为全局变量,或者用指针;
 
2.sizeof函数
sizeof函数用来获取类型或数据的字节数;
1)基本类型的sizeof,可以使用类型,也可以使用变量        
    printf("%d\n",sizeof(char));     
    printf("%d\n",sizeof(short int));    
    printf("%d\n",sizeof(int));       
    printf("%d\n",sizeof(long int));    
    printf("%d\n",sizeof(__int64));    
    printf("%d\n",sizeof(float));    
    printf("%d\n",sizeof(double));  
  
    int x = 10;    
    printf("%d\n",sizeof(x));
 
2)数组类型的sizeof        
    char arr1[10] = {0};    
    short arr2[10] = {0};    
    int arr3[10] = {0};    
        
    printf("%d\n",sizeof(arr1));    
    printf("%d\n",sizeof(arr2));    
    printf("%d\n",sizeof(arr3));    
        
    printf("%d\n",sizeof(arr1[10]));    
    printf("%d\n",sizeof(arr2[10]));    
    printf("%d\n",sizeof(arr3[10]));
 
3)结构体类型的sizeof        
    struct S1    
    {    
        char a;
        int b;
        char c;
    };    
    struct S2    
    {    
        int a;
        char b;
        char c;
    };    
    int main(int argc, char* argv[])    
    {    
        S1 s1;
        S2 s2;
        
        printf("%d\n",sizeof(s1));
        printf("%d\n",sizeof(s2));
        
        printf("%d\n",sizeof(S1));
        printf("%d\n",sizeof(S2));
        
        return 0;
    }    
 
 
 
3.结构对齐
1)结构体的大小
例如:下面的结构sizeof获得的结果为24
struct Test    
{    
    int a ;    
    __int64 b ;    
    char c ;    
    char d ;    
};
而相同的结构,调换了成员顺序后sizeof的结果为16
struct Test    
{   
    __int64 b ;  
    int a ;    
    char c ;    
    char d ;    
};
产生这一现象的原因是结构的数据对齐;
 
2)为什么有结构对齐
本质上是效率和空间二选一的结果;
 
3)对齐参数
对齐参数:n为字节对齐数,其取值为1、2、4、8,默认是8。
                            
如果这个值比结构体成员的sizeof值小,那么该成员的偏移量应该以此值为准,                            
即是说,结构体成员的偏移量应该取二者的最小值.
 
自定义对齐参数的代码:将结构体的对齐参数设为n
#pragma pack(n)
    结构体
#pragma pack()
 
例如:同样的结构在不同对齐参数下的内存空间
 
4)vc6中设置默认对齐参数
项目右键-->setting-->C/C++-->Code Generation                            
                            
如果这个值比结构体成员的sizeof值小,那么该成员的偏移量应该以此值为准,                            
即是说,结构体成员的偏移量应该取二者的最小值,
 
5)对齐原则
原则一:数据成员对齐规则:结构的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从                                    
该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储).                                    
                                    
原则二:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
                                                                        
原则三:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。                                    
(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储.)   
                                                                     
原则四:对齐参数如果比结构体成员的sizeof值小,该成员的偏移量应该以此值为准.                                    
也就是说,结构体成员的偏移量应该取二者的最小值.  
 
6)结构对齐案例
 
7)建议
为了节省内存空间;建议结构中的成员按照数据类型由小到大的顺序进行书写                          
 
4.typedef
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。
这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
 
1)对已有类型定义别名 
typedef unsigned char BYTE;        
typedef unsigned short WORD;        
typedef unsigned int DWORD;  
 
 2)一维数组类型的定义格式
typedef int vector[10];            
            
int main(int argc, char* argv[])            
{            
    vector v;        
    v[0] = 1;        
    v[1] = 2;        
    v[2] = 3;        
    v[3] = 4;        
    v[4] = 5;        
    return 0;        
}
 
3) 二维数组类型的定义格式
typedef int name[5][5];            
typedef int nameTable[5][5][5];            
            
int main(int argc, char* argv[])            
{            
    name v;        
    nameTable n;        
            
    v[0][0] = 1;        
    v[0][1] = 2;        
    v[0][2] = 3;        
    v[0][3] = 4;        
    v[0][4] = 5;        
            
    n[0][0][0] = 1;        
            
    return 0;        
}
              
4)结构体的定义格式
typedef struct student        
{        
    int x;    
    int y;    
}stu;        
 
5.给字符数组赋值
如果在c语言中想要保存字符串,可以用char数组;
头文件string.h中的strcpy函数可以用来给字符数组赋值;
步骤:
    第一步:    #include "string.h"
    第二步:    
    char arr[10];
    strcpy(arr,"中国");
例如:
#include "stdio.h"
#include "string.h"
 
typedef struct student{
    char sex;
    int age;
    int score;
    char name[30];
}stu;
 
void fun()    
{    
    stu s[5];    //结构数组
    s[0].sex = 'M';
    s[0].age = 12;
    s[0].score = 100;
    strcpy(s[0].name, "张三");
 
    printf("sex:%c,age:%d,score:%d,name:%s",s[0].sex,s[0].age,s[0].score,s[0].name);
}
 
int main(int argc, char* argv[])
{    
    fun();
    getchar();
    return 0;
}
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/ShiningArmor/p/11578556.html
今日推荐