原文: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语言, 指针, 链表

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

  1. C 二维数组,以及自定义二维数组

    C 二维数组,以及自定义二维数组 我们通常情况下是这样定义一个二维数组的: int a[10][15]; 我们分别查看一下a,a[0],*a 都是一样的值吧 我们可以这么理解: a是一个数组的数组 a ...

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

    经常我们会在资源文件(res/strings.xml)定义字符串,一维数组,那定义二维数组?直接定义二维数组没找到,可以间接定义. 其实很简单,看过用过一次就可以记住了,一维数组估计大家经常用到,但是 ...

  3. Java 数组(三)二维数组

    如果一维数组的各个元素仍然是一个数组,那么它就是一个二维数组.二维数组常用于表示表,表中的信息以行和列的形式组织,第一个下标代表元素所在的行,第二个下标代表所在的列. 一.二维数组的创建 1.先声明, ...

  4. php 将一个或多个二维数组组合成一个二维数组并根据某个字段排序排序

    最近再写项目的时候,碰到一个问题:如何将一个或多个二维数组组合成一个二维数组并根据某个字段排序排序:实在是想不到哪个php库中有哪个函数能实现,只能自己写一个了,将代码写出来后,发现自己的代码繁琐,并 ...

  5. 06-01 Java 二维数组格式、二维数组内存图解、二维数组操作

    二维数组格式1 /* 二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的 ...

  6. C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

  7. java 基本语法(十) 数组(三) 二维数组

    1.如何理解二维数组? 数组属于引用数据类型数组的元素也可以是引用数据类型一个一维数组A的元素如果还是一个一维数组类型的,则,此数组A称为二维数组. 2.二维数组的声明与初始化 正确的方式: int[ ...

  8. JAVA中如何创建一个二维数组,然后给二维数组赋值!

    普通的赋值是:int[][] i = {{1,2,3},{2,3,4},{1,3,4}}; 如果是其他情况可以这样:比如: import java.util.* public class TT(){ ...

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

    通过typedef可以简单实现.也可以直接写. 写了两个简单的矩阵操作的函数简单示例. #include <stdio.h> #include <stdlib.h> const ...

随机推荐

  1. Kienct与Arduino学习笔记(2) 深度图像与现实世界的深度图的坐标

    转载请注明出处:http://blog.csdn.net/lxk7280 首先,要接触一下KinectOrbit这个摄像机库,这篇文章中有这个库的下载网址和简单的介绍:http://blog.csdn ...

  2. Ubuntu14.04设备JDK

    1.设备JDK 打开命令直插式工具.输入以下三个命令: sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo ap ...

  3. Struts2之—实现自己的结果集的定义ajax

    项目中我们常常遇到这种需求--页面部分刷新.比如:加入用户,转到加入用户页面时,页面自己主动载入了全部部门. 完整流程:选择所属部门,填写username和password,点击"注冊&qu ...

  4. apache kafka系列之-监控指标

    apache kafka中国社区QQ群:162272557 1.监控目标 1.当系统可能或处于亚健康状态时及时提醒,预防故障发生 2.报警提示 a.短信方式 b.邮件 2.监控内容 2.1 机器监控 ...

  5. 使用RESTClient插件数据模拟(GET,POST)提交

    1:在Firefox下载RESTClient插件安装 2:安装界面后, 3:点击设置头文件:(设请求地址有头部文件) 4:设置界面,当然有非常多选择.依据你的须要.一般在输入的时候有智能提示,我这里以 ...

  6. 推荐2一个在Java编码过程中得心应手的工具

    推荐2在编码过程中的减小不仅编码的量,挺easy工具上手:可适用Java反思与单探头Assert. 1 Mirror:Java反思 简单介绍 官网:http://projetos.vidageek.n ...

  7. ASP.Net中使用XMLDataSource

    在Web开发中,程序和数据库打交道是常有的事情.在平时使用过程中,使用较多的是MS SQLSERVER,因此经常用到SQLDataSource将数据绑定的数据控件上.有时数据量较小,无需要在数据库中创 ...

  8. Log4NET 数据库

    阅读目录 Log4NET简介 前提 详细步骤 回到顶部 Log4NET简介 log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种 ...

  9. 具体解释首页被K后SEOer必做的三大排除方法!

    近段时间.有非常多朋友向新辰抱怨说出大问题了,为神马site不到首页了,并且收录变成了0?唉,新辰不得不非常同情的告诉你:你的首页真的被K了!好了.作为一个职业SEOer.面对被K宛如已经看破红尘般没 ...

  10. 解决 Mybatis 元素类型为 "resultMap" 的内容必须匹配 "(constructor?,id*,result*,association*,collection*,discriminat

    在配置 mybatis mapper.xml文件时, 一不小心就会报如下类似的异常: Caused by: org.springframework.beans.factory.BeanCreation ...