C语言——地址、指针、结构(学习笔记)

14 篇文章 14 订阅

指针变量(指针):能够存储地址的变量
地址运算符&:&num表示“num的地址”
间接运输符*:当*符号后面紧跟一个指针时,表示这是一个地址被存储在其中的变量

数组、指针、地址

指针操作

指针运算

*ptNum++使用指针,然后给指针增1
*++ptNum在使用指针前,给指针增1
*ptNum–使用指针,然后给指针减1
*–ptNum在使用指针前,给指针减1

nums是数组名称,nPtr是指针(存nums[0]的地址)。
nPtr = nums;
注意:
*nPtr++ 有效
*num++ 无效
*nums 有效(nums[0])
*(nums+i) 有效(nums[i])

比较:(下面三条等价)
nPtr <= &nums[4];
nPtr <= nums + 4;
nPtr < nums + 5;

指针初始化

(下面两条顺序不能换)
int miles;
int *ptNum = &miles;
只有在声明ptNum之前miles本身被声明为整型变量才有效。
(ptNum是指向整数的指针,*ptNum是这个整数miles)

注意:
使用下标:如果程序按应用和手边数据的自然存储空间结构使用数组
使用指针:当讲解有关字符串和数据结构的知识时

传递和使用数组地址

一维数组元素能够用两种方式访问:

数组元素下表符号指针符号
元素0grade[0]*grade
元素1grade[1]*(grade+1)
元素2grade[2]*(grade+2)
………………

注意:保存到数组名称中的地址不能够被赋值语句改变。
类似grade=&grade[2];的语句是无效的

二维数组指针:

指针符号1指针符号2下标符号
*(*nums)*nums[0]nums[0][0]
*(*nums+1)*(nums[0]+1)nums[0][1]
*(*nums+2)*(nums[0]+1)nums[0][1]
((nums+1))*nums[1]nums[1][0]
((nums+1)+1)*(nums[1]+1)nums[1][1]
((nums+1)+2)*(nums[1]+2)nums[1][2]

使用指针创建字符串

下面两个初始化是有效的:
char message1[81] = “this is a string”;
char *message2 = “this is a string”;
从保存的观点看,message1和message2的空间分配是不同的。
message1:一个指定的81个存储空间被保留并且前17个位置被初始化。能够保存不同的字符串,但是每个字符串将覆盖前面已保存的字符。
message2:如果以后给它进行赋值,最初的字符串依然留在内存中,新的内存位置会分配给新的字符串。

message2例子:

#include <stdio.h>
int main()
{
	char *message2 = "this is a string";

	printf("\nThe string is %s", message2);
	printf("\nThe base address of this string is %p\n", message2);

	message2 = "A new message";
	printf("\nThe string is %s", message2);
	printf("\nThe base address of this string is %p\n", message2);

	return 0;
}

输出:
The string is this is a string
The base address of this string is 00420094
The string is A new message
The base address of this string is 00420038

指针数组

声明:char *seasons[4]
初始化:
seasons[0]=“Winter”;
seasons[1]=“Spring”;
seasons[2]=“Summer”;
seasons[3]=“Fall”;

char *seasons[4] = {“Winter”,
“Spring”,
“Summer”,
“Fall”};

例子:

#include <stdio.h>
int main()
{
	int n;
	char *seasons[4] = {"Winter",
			"Spring",
			"Summer",
			"Fall"};
	
	printf("\nEnter a month (use 1 for Jan., 2 for Feb.,etc.):");
	scanf("%d", &n);
	n = (n % 12) / 3;
	printf("The month entered is a %s month.\n", seasons[n]);

	return 0;
}

注意:
指针数组和数组指针的区别:

指针数组(是数组):数组中的每个元素都存放指针。
例:*p[4]
p[0]、p[1]、p[2]、p[3]里面存放的都是指针

数组的指针(是指针):存放数组的行指针。
例:(*p)[4](二维数组指针,其中4表示一行有4个元素)
*p是第0行的地址
*(p+1)是第1行的地址

结构

单一结构

例1
声明

struct
{
	int month;
	int day;
	int year;
}birth, current;

给出了一个名称为birth和一个名称为current的结构的形式

struct Date
{
	int month;
	int day;
	int year;
};

Date是结构类型名称,它创建了一个这种声明形式的新结构类型。
struct Date birth, current;

赋值:
birth.month = 12;
birth.day = 28;
birth.year = 1987;

struct Date birth = {12,28,1987};

例2
声明:

struct PayRecord
{
	char name[20];
	int idNum;
	double regRate;
	double otRate;
};

定义和初始化
struct PayRecord employee = {“H.Price”, 12387, 15.89, 25.5};

例3(把一个结构包含在另一个结构内)

strcut Date
{
	int month;
	int day;
	int year;
};
struct
{
	char name[20];
	struct Date birth;
}person;

赋值:
person.birth.month = 12;

结构数组

一个列表能够作为一个多个结构的单一数组处理。
例:
struct PayRecord {int idnum; char name[20]; double rate;};
10个这样的结构的数组能够定义为:
struct PayRecord employee[10];

传递结构

传递结构的副本:

#include <stdio.h>
struct Employee	/*声明一个全局结构类型*/
{
	int idNum;
	double payRate;
	double hours;
};

double calcNet(struct Employee);	/*函数原型*/

int main()
{
	struct Employee emp = {6787, 8.93, 40.5};
	double netPay;

	netPay = calcNet(emp);	/*传递emp中的数值的副本*/
	printf("The net pay of employee &d is $%6.2f\n", emp.idNum, netPay);

	return 0;
}

double calcNet(struct Empolyee temp)	/*temp是具有结构Employee的数据类型*/
{
	return(temp.payRate * temp.hours);
}

传递结构的地址:

#include <stdio.h>
struct Employee	/*声明一个全局结构类型*/
{
	int idNum;
	double payRate;
	double hours;5
};

double calcNet(struct Employee *);	/*函数原型*/

int main()
{
	struct Employee emp = {6787, 8.93, 40.5};
	double netPay;

	netPay = calcNet(&emp);	/*传递一个地址*/
	printf("The net pay of employee &d is $%6.2f\n", emp.idNum, netPay);

	return 0;
}

double calcNet(struct Empolyee *pt)	/*pt是一个指向一个Employee类型结构的指针*/
{
	return(pt->payRate * pt->hours);
}

注意:传递副本和传递地址中,函数原型、调用函数、函数首部行的区别

(*pt).idNum能够用pt->idNum取代,指pt里的地址指向的结构中的idNum成员
(*pt).payRate能够用pt->payRate取代
(*pt).hours能够用pt->hours取代

自增自减:
++pt->hours hours成员先被访问,后自增1(->比++优先级高)
(pt++)->hours hours成员被访问后,pt中地址增1
(++pt)->hours pt中地址增1,再hours成员被访问

联合

是一种保留两个或多个变量在内存中相同区域的数据类型。

声明:

union
{
	char key;
	int num;
	double price;
}val;

union DateTime
{
	long days;
	double time;
};
union DateTime first, second, *pt;

联合可以是结构和数组的成员,结构、数组和指针可以是联合的成员。

struct
{
	char uType;
	union
	{
		char *text;
		double rate;
	}uTax;
}flag;

变量rate被引用为:flag.uTax.rate
地址保存到指针text中的字符串的第一个字符的访问方式是:*flag.uTax.text

结构和联合的区别:

1、在同一时刻,结构体的每个成员都有值,但是联合体在同一时刻只有一个成员有值。
2、当结构体变量的其中一个成员进行修改时,对其他成员没有影响;但修改联合体时,会将原来的成员值覆盖。

动态数据结构

链表

(用结构)

struct TeleType
{
	char name[30];
	char phoneNum[15];
	struct TeleType *nextaddr;
};

最后一个成员是一个指针,适合于保存一个TeleType类型结构的地址。

#include <stdio.h>
#define MAXNAME 30
#define NAXPHONE 15

struct TeleType
{
	char name[30];
	char phoneNum[15];
	struct TeleType *nextaddr;
};

int main()
{
	struct TeleType t1 = {"Acme, Sam", "(555) 898-2392"};
	struct TeleType t2 = {"Dolan, Edith", "(555) 682-3104"};
	struct TeleType t3 = {"Lanfrank, John", "(555) 718-4581"};
	struct TeleType *first;
	void display(struct TeleType *);

	first = &t1;
	t1.nextaddr = &t2;
	t2.nextaddr = &t3;
	t3.nextaddr = NULL;

	display(first);

	return 0;
}

void display(struct TeleType *contents)
{
	while(contents != NULL)
	{
		printf("%-30s %-20s\n", contents->name, contents->phoneNum);
		contents = contents->nextaddr;
	}
}

动态内存分配

函数:(头文件stdlib.h)
malloc()、calloc()、realloc()、free()

例:
malloc(10 * sizeof(char))请求足够的内存保存10个字符
malloc(sizeof(int))请求足够的内存保存一个整型数

grades = malloc(sizeof(int)); /变量grades是一个指向整型的指针/
(int *)grades; /定义grades为一个整型的地址/

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int numgrades, i;
	int *grades;

	printf(\nEnter the number of grades to be processed: ");
	scanf("%d", &numgrades);
	
	/*这里是进行请求存储区的地方*/
	grades = (int *)malloc(numgrades * sizeof(int));

	/*在这里我们检查这个分配是否被满足*/
	if (grades == (int *) NULL)
	{
		printf("\nFailed to allocate grades array\n");
		exit(1);
	}
	
	for (i=0; i<numgrades; i++)
	{
		printf("Enter a grade: ");
		scanf("%d", &grades[i]);
	}
	
	printf("\nAn array was created for %d integers", numgrades);
	printf("\nThe values stored in the array are: \n");
	
	for (i=0; i<numgrades; i++)
		printf("%d\n",grades[i]);

	free(grades);	/*存储区不需要时,把分配的存储块归还给堆是良好的习惯*/
	
	return 0;
}

为结构动态地分配内存:

struct OfficeInfo
{
	任意数量的数据成员在此声明;
};

struct OfficeInfo *off;	/*创建一个指针存储这个被分配的地址*/

/*为一个结构空间请求空间*/
off = (struct OfficeInfo *)malloc(sizeof(struct OfficeInfo));

/*检查空间是否被分配*/
if (off == (struct OfficeInfo *) NULL)
{
	printf("\nAllocation of office info structure failed\n");
	exit(1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值