C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表
本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言评论数 3 ⁄ 被围观 1,775 views+

指针数组:

在一个数组中,如果它的元素全部都是指针类型的数据,那么这个数组称为指针数组。

定义:类型名 *数组名[数组长度];

char *suit[3] = {"first","second","third"};

指向指针的指针:

如果一个变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针数据的指针变量,又称多级指针,简称为指向指针的指针。

定义:类型标识符 * * 指针变量名;

利用指针变量访问另一个变量就是“间接访问”,在一个指针变量中存放一个目标变量的地址,就是“单级间址”。

对于数组suit,由于数组名本身就表示地址,所以可以直接创建二级指针:

char **p;
p = suit;
#include<stdio.h>
void main(){
	int a[5] = {1,3,5,7,9};
	int *num[5],i;
	int **p;
	for(i=0;i<5;i++){
		num[i] = &a[i];
	}
	p = num;
	for(i=0;i<5;i++){
		printf("%d",**p);
		p++;
	}
	printf("\n");
}

指向二维数组的指针:

二维数组的地址:

a=a[0][0]=a[0] a+1=a[1] a[0]+1=a[0][1]

a是行指针,*a是列指针,**a表示a[0][0]的值,*a表示a[0]的地址。 a[1]+2 等价于 *(a+1)+2

在行指针前面加上一个*就转换为了列指针,若a和a+1是行指针,则*a和*(a+1)是列指针。

指向数组元素的指针变量

#include<stdio.h>
void main(){
	int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}
	int *p;
	for(p = a[0]; p<a[0]+12; p++){
		if((p-a[0])%4 == 0)
			printf("\n");
		printf("%4d",*p);
	}
}

指向由m个元素构成的一维数组的指针变量

这种指针使得p+1不是指向a[0][1],而是指向a[1],p的增值以一位数组的长度为单位,这种指针称为行指针。

数据类型 (*指针变量名)[N];

int a[4][3], (*p)[3];

返回指针的函数

函数类型 * 函数名([形式参数类型声明表])
	{
		函数体
	}

指向函数的指针

指向函数的指针的一般定义形式:

数据类型 (*指针变量名)(参数类型列表)

调用方式:

(*指针变量名)(实际参数列表)

int (*FunctionPointer)(int a);
FunctionPointer = func;   //func为函数名
(*FunctionPointer)(100);

带参数的main函数

void main(int argc, char *argv[]){
	函数体
}

argc表示命令行参数个数,argv表示参数数组

指向结构体的指针

struct student *p;
struct student stu;
p = &stu;
//获取子元素的三种方法:
stu.name;
(*p).name;
p->name;  //指针的方法

指向结构体数组的指针

指向结构体数组的指针实际上与前面定义的指向二维数组的指针类似,可以理解为二位地址数组的行指针。

动态内存分配:

void *malloc(unsigned int size);

newptr = malloc(sizeof(struct node));

void free(void *p)

链表结构:

#include<stdio.h>
#define NULL 0
#define LEN sizeof(struct student)  /*定义节点的长度*/
#define NODE struct student
struct student
{
	char no[5];
	float score;
	struct student *next;
};

struct student *create(void);
void printlist(struct student *head);
NODE * insert(NODE *head, NODE *new, int i);
NODE * dellist(NODE *head,char no[]);

void main(){
	struct student *a;
	struct student test1={"abc",1.0,NULL};
	struct student *test2;
	a = create();
	printf("insert new node\n");

	test2 = &test1;
	a = insert(a,test2,2);
	printlist(a);

	printf("delete node\n");
	a = dellist(a,"2");
	printlist(a);

	getch();
}
/*创建一个具有头结点的单链表,返回单链表的头指针*/
struct student *create(void){
	struct student *head = NULL, *new1, *tail;
	int count = 0;
	for(;;)
	{
		new1 = (struct student *)malloc(LEN);  /*申请一个新结点的空间*/
		printf("Input the number of student No.%d(5bytes): ",count + 1);
		scanf("%5s",new1->no);
		if(strcmp(new1->no, "*") == 0)   /*这里不用加取址符号,因为no就表示数组的首地址*/
		{
			free(new1);   /*释放最后申请的结点空间*/
			break;  /*结束for语句*/
		}
		printf("Input the score of the student No.%d: ",count + 1);
		scanf("%f",&new1->score);
		count++;
		/*将新结点插入到链表尾,并设置新的尾指针*/
		if(count == 1){
			head = new1;   /*是第一个结点,置头指针*/
		} else
			tail->next = new1;  /*不是第一个结点,将新结点插入到链表尾*/
		tail = new1;    /*设置新的尾结点*/
	}
	/*置新结点的指针域为空*/
	new1->next = NULL;
	return(head);
}

/*输出链表*/
void printlist(struct student *head){
	struct student *p;
	p = head;
	if(head == NULL) {
		printf("List is empty!!!\n");
	} else {
		while(p!=NULL){
			printf("%5s %4.1f\n", p->no,p->score);
			p = p->next;
		}
	}
}

/*插入链表结点*/
NODE * insert(NODE *head, NODE *new, int i){
	NODE *pointer;
	/*将新结点插入到链表中*/
	if(head == NULL){
		head = new; new->next = NULL;
	} else {
		if(i == 0){
			new -> next = head;
			head = new;
		} else {
			pointer = head;
			/*查找单链表的第i个结点(pointer指向它)*/
			for(;pointer != NULL && i > 1; pointer = pointer->next,i--);
			if(pointer == NULL)
				printf("Out of the range,can‘t insert new node!\n");
			else {  /*一般情况下pointer指向第i个结点*/
				new -> next = pointer->next;
				pointer->next = new;
			}
		}
	}
	return(head);
}

/*删除链表*/
NODE * dellist(NODE *head,char no[]){
	NODE *front;    /*front表示要删除结点的前一个结点*/
	NODE *cursor;   /*cursor表示当前要删除的结点*/
	if(head == NULL) {  /*空链表*/
		printf("\nList is empty\n");
		return(head);
	}
	if(strcmp(head->no,no == 0)){  /*要删除的结点是表头结点*/
		front = head;
		head = head->next;
		free(front);
	} else {  /*非表头结点*/
		front = head;
		cursor = head->next;
		/*通过循环移动到要删除的结点的位置*/
		while(cursor != NULL && strcmp(cursor->no,no) != 0) {
			front = cursor;
			cursor = cursor ->next;
		}
		if(cursor != NULL){   /*找到需要删除的结点进行删除操作*/
			front->next = cursor->next;
			free(front);
		} else {
			printf("%5s has not been found!",*no);
		}
	}
	return(head);
}

除了文章中有特别说明,均为IT宅原创文章,转载请以链接形式注明出处。

本文链接:http://www.itzhai.com/c-language-syntax-notes-advanced-usage-of-two-dimensional-array-of-pointers-to-a-pointer-list-pointer-array-pointer-structure.html

关键字: C语言, 指针, 链表

时间: 2024-10-10 20:08:44

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com的相关文章

Android 在资源文件(res/strings.xml)定义一维数组,间接定义二维数组

经常我们会在资源文件(res/strings.xml)定义字符串,一维数组,那定义二维数组?直接定义二维数组没找到,可以间接定义. 其实很简单,看过用过一次就可以记住了,一维数组估计大家经常用到,但是二维数组应该比较少用,因为只能间接定义二维数组. 数组的定义: 数组就是一次性定义相同数据类型的一组变量数组定义. 数组的特点: 1.数组是相同数据类型的元素的集合. 2.数组中的各元素是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起. 3.数组元素用整个数组的名字和它自己在数组中的顺序位

数组合并函数,二维数组相同字段合并到一起。

一般从数据库中提取数据时,会遇到各种各样类型的数据,要求也不尽相同.自己这两天开发的时候遇到一个很纠结的问题,如下: 比如一个二维数组是这样的: Array ( [0] => Array ( [uid] => 231 [username] => 123456 [active] =>aaaa [transfer] =>1111 ) [1] => Array ( [uid] => 231 [username] =>123456 [active] => bb

一维数组与二维数组的拼接与二维数组增加行

一维数组与二维数组的拼接 numpy有很多的拼接函数.比如hstack和vstack等.网上又很多这样的总结帖子.但是两个数组能拼接的条件就是得满足两个数组的维度要相同.所以二维数组和一维数组拼接的时候需要使用newaxis将一维数组转化为二维数组,也就是shape从(3,)转化为(3,1). a = np.array([1,2,3]); b = np.array([[1],[2],[3]]); #将一维数组a转化为二维数组 a = a[:,np.newaxis]; c = np.concate

数组的初始化和二维数组、指针与数组

1.数组的初始化,比较简单,实例程如下: #include<stdio.h> # define M 12 int main(void){ int days[M]={31,28,31,30,31,30,31,30,30,31,30,31}; int i; for(i=0;i<M;i++) printf("Months %d has %2d days.\n",i+1,days[i]); return 0; } 运行结果如下: 2.未经初始化的数组: 实例程序: #incl

一维数组对象转成二维数组

一.关于PHP把装着item为对象的一维数组转成二维数组的疑问 背景:新增帖子的时候,选择标签时,可以选择多个,后端接口是需要传入的是一个二维数组. /** * @Title 修改精选内容 * @Params $id 记录ID * @Params $tags 标签组 array( * array( * 'name' => '桌面文化', * 'tag_id' => '2' * ) */ public function update($id = 0,$tags = array()) 困惑:后端接

c#(6)——数组的应用和二维数组

人类思维--计算机逻辑思维逻辑思维--代码实现 写书法:描红——临摹——碑贴——自成一体——草 复习:数组:一维,二维,多维一维:豆角.连续,同一类型.定义:数据类型[] 数组名=new 数据类型[长度]{.,.,.,.};赋值:数组名[下标] = 值取值:数组名[下标]灵活运用:与for循环的结合应用.1.求最大值,最小值.2.求总和,平均.3.随机(生成下标)抽值. 数组的应用:(一).冒泡排序.1.冒泡排序是用双层循环解决.外层循环的是趟数,里层循环的是次数.2.趟数=n-1:次数=n-趟

【C语言】【面试题】【笔试题】二维数组中的查找,杨氏矩阵

#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <math.h> #include<windows.h> int find(int arr[], int rows, int columns, int num) {     int find = 0;     if (arr != NULL && rows > 0 &

c语言 函数返回二位数组 函数参数为二维数组

通过typedef可以简单实现.也可以直接写. 写了两个简单的矩阵操作的函数简单示例. #include <stdio.h> #include <stdlib.h> const int ROW = 3; const int COL = 4; typedef int (* mat_pointer)[COL]; mat_pointer init_mat(mat_pointer a) { for (int i = 0; i < ROW; ++i) for (int j = 0; j

C语言 二维数组(指针)动态分配和释放(转)

C 二维数组(指针)动态分配和释放 先明确下概念: 所谓32位处理器就是一次只能处理32位,也就是4个字节的数据,而64位处理器一次就能处理64位,即8个字节的数据.如果我们将总长128位的指令分别按照16位.32位.64位为单位进行编辑的话:旧的16位处理器,比如Intel 80286 CPU需要8个指令,32位的处理器需要4个指令,而64位处理器则只要两个指令,显然,在工作频率相同的情况下,64位处理器的处理速度会比16位.32位的更快.而且除了运算能力之外,与32位处理器相比,64位处理器