自学C语言--结构···笔记

一、声明结构类型

结构是包含了一些值的集合。

结构类型声明的含义:描述了一个结构的组织布局。

e.g.

struct title  {

      int a;

      char b [ num ] ;

}   ;

注:title是结构类型的标记。

二、创建结构类型的变量

创建结构类型的变量:struct  title  library;

注:如果需要多次使用结构模板,就要使用带标记的形式。

三、初始化结构

e.g.

struct  title  library = { 15,"hello" } ; 

注:使用在一对花括号中括起来的初始化列表进行初始化,各初始化项用逗号隔开。

四、访问结构类型的成员

结构成员运算符( )

e.g.  library b

注:   .   比&的优先级高。

五、结构数组 

1、声明结构数组

e.g. struct  title  library [ MAX ] ;

2、访问结构数组成员

e.g. library  [ 0 ] . b

注:library  [ 0 ]是结构变量名。

3、使用结构数组的函数
#include <stdio.h>
#define FUNDLEN 50
#define R 2

struct funds
{
	char bank[FUNDLEN];
	double bankfund;
	char save[FUNDLEN];
	double savefund;
};

double sum(const struct funds money [],int n);

int main()
{
	struct funds account[R] = {
		{
			"A Bank",
			5000.0,
			"Hello",
			1000.1
		},
		{
			"B Bank",
			4000.0,
			"world",
			2000.1
		}
	};
	
	printf("Total is %.2f\n",sum(account,R));  //数组名是数组首元素的地址,
//所以account等价于&account[0]
	
	return 0;
}

double sum(const struct funds money[],int n)
{
	double total;
	int i;
	
	for (i=0,total=0;i<n;i++)
	{
		total+=money[i].bankfund+money[i].savefund;
	}
	return total;
}

六、嵌套结构

#include <stdio.h>
#define LEN 20
const char * msgs[5] =
{
    "    Thank you for the wonderful evening, ",
    "You certainly prove that a ",
    "is a special kind of guy. We must get together",
    "over a delicious ",
    " and have a few laughs"
};

struct names {                     // first structure
    char first[LEN];
    char last[LEN];
};

struct guy {                       // second structure
    struct names handle;           // nested structure
    char favfood[LEN];
    char job[LEN];
    float income;
};

int main(void)
{
    struct guy fellow = {   // initialize a variable
        { "Ewen", "Villard" },
        "grilled salmon",
        "personality coach",
        68112.00
    };
    
    printf("Dear %s, \n\n", fellow.handle.first);
    printf("%s%s.\n", msgs[0], fellow.handle.first);
    printf("%s%s\n", msgs[1], fellow.job);
    printf("%s\n", msgs[2]);
    printf("%s%s%s", msgs[3], fellow.favfood, msgs[4]);
    if (fellow.income > 150000.0)
        puts("!!");
    else if (fellow.income > 75000.0)
        puts("!");
    else
        puts(".");
    printf("\n%40s%s\n", " ", "See you soon,");
    printf("%40s%s\n", " ", "Shalala");
    
    return 0;
}

七、结构指针

1、定义

e.g. struct  title * book ;

如果book是一个title类型的结构变量名,book=&library;

注:结构名不是结构变量的地址,因此要在结构名前面加上&。

2、用指针访问成员

第一种方法:间接结构成员运算符:结构指针->成员变量

如果book=&library , 那么 book-> b等价于 library . b。

第二种方法:library [ 0 ] .b == ( *book ).b

注:必须使用(),因为 . 运算符的优先级比 * 运算符的优先级高。

即:library [ 0 ] .b == ( *book ).b == book-> b

八、结构体传参

#include <stdio.h>

struct S
{
int a;
int b
};

void print1(struct S s)

{
   printf("%d\n",s.a);
}

void print2(struct S *z)
{
   printf("%d\n",z->a);
}


int main()
{
   struct S m = { 0, 1 } ;

   print1(m);

   print2(&m);
 
   return 0;
}

注:第一个函数传递结构体;第二个函数传递结构体地址。

九、向函数传递结构信息

1、把结构作为参数传递

  // 定义一个包含两个整型成员的结构体:

struct Point {
    int x;
    int y;
};
 

  //  定义一个函数,接受一个Point类型的结构体变量,并打印它的成员: 

void printPoint(struct Point p) {
    printf("x = %d, y = %d\n", p.x, p.y);
}
 

   //  定义一个Point类型的变量,并把它传递给printPoint函数:

struct Point p = {3, 4};
printPoint(p);
 
2、把结构成员作为参数传递
#include <stdio.h>
#define FUNDLEN 50

struct funds {
    char   bank[FUNDLEN];
    double bankfund;
    char   save[FUNDLEN];
    double savefund;
};

double sum(double, double);

int main(void)
{
    struct funds stan = {
        "Garlic-Melon Bank",
        4032.27,
        "Lucky's Savings and Loan",
        8543.94
    };
    
    printf("Stan has a total of $%.2f.\n",
           sum(stan.bankfund, stan.savefund) );
    return 0;
}

/* adds two double numbers */
double sum(double x, double y)
{
    return(x + y);
}
3、把结构地址作为参数传递
#include <stdio.h>
#define FUNDLEN 50

struct funds {
    char   bank[FUNDLEN];
    double bankfund;
    char   save[FUNDLEN];
    double savefund;
};

double sum(const struct funds *);  /* argument is a pointer */

int main(void)
{
    struct funds stan = {
        "Garlic-Melon Bank",
        4032.27,
        "Lucky's Savings and Loan",
        8543.94
    };
    
    printf("Stan has a total of $%.2f.\n", sum(&stan));
    
    return 0;
}

double sum(const struct funds * money)
{
    return(money->bankfund + money->savefund);
}

十、其他的结构特性

1、可以把一个结构赋值给另一个结构,但是数组不能。

e.g.  bike = cycle;//其中book和cycle都是结构名

2、可以把一个结构初始化为相同类型的另一个结构。

e.g. struct name right = {"Tom","James"};

struct name false=right; 

3、用字符数组来存储结构中的字符串,不推荐用字符指针。但是如果用malloc()分配内存并使用指针存储该地址,那么在结构中使用指针处理字符串。

十一、结构的复合字面量

语法:把类型名放在圆括号中,后面紧跟一个用花括号括起来的初始化列表。

e.g. 一个表示学生信息的结构体类型:

struct student {
    char name[20];
    int age;
    char gender;
};
 

复合字面量: 

struct student s = {"Tom", 18, 'M'};
 

e.g.还可以把复合字面量作为函数的参数。

十二、结构体内存对齐

(1)、结构体的对齐规则:

1.第一个成员在与结构体变量偏移量为0的地址处。

2.其他成员变量要对齐到对齐数的整数倍的地址处。其中:对齐数=编译器默认的一个对齐数与该成员大小其中的较小值。注:VS中默认的对齐数值为8

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

(2)、为什么存在内存对齐

1.移植原因:

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2.性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。结构体的内存对齐是拿空间来换取时间的做法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值