Linux C 深入分析结构体指针的定义与引用
2016-06-18 23:33
330 查看
关于结构体的基础知识,网上书上都一大堆,这里就不赘述了,下面我们要学习的是结构体指针。
介绍结构体指针之前,先给大家看一个小程序:
[cpp] view
plain copy
#include <stdio.h>
#include <string.h>
#include <malloc.h>
struct Man
{
char name[10];
};
int main()
{
struct Man N;
N.name = "qiang";
printf("%s\n",N.name);
}
这段程序很简单,就是给结构体成员赋值,这里结构体成员是个数组,大家看看这种赋值方式有没有错,我们编译一下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ gcc -o struct4 struct4.c
struct4.c: In function ‘main’:
struct4.c:13:9: error: incompatible types when assigning to type ‘char[10]’ from type ‘char *’
fs@ubuntu:~/qiang/struct$
13行报错,就是赋值那行,报错原因是“字符分配的类型是不兼容的类型”
我们看看这句N.name = "qiang",右边是字符串常量,这里其实是字符串的首地址,就是一个地址,我们以前 char a[] = "qiang"没错啊,为什么这里报错了,我们看看左值,N.name, name 是数组名,是代表数组的首地址啊,但是我们要记住,这里name是个地址常量,是不能给常量赋值的,所以会报错,那我们如何给一个结构体中的字符数组赋值呢?我们这里用strcpy(N.name,"qiang") ! 当然我们N.name[1] = 'q',这样是可以的。
下面开始讲结构体指针:
一、指向结构体类型变量的使用
首先让我们定义结构体:
[cpp] view
plain copy
<span style="color:#000000;">struct stu
{
char name[20];
long number;
float score[4];
};
</span>
再定义指向结构体类型变量的指针变量:
struct stu *p1, *p2 ;
定义指针变量p1、p2,分别指向结构体类型变量。引用形式为:指针变量→成员;这里我们要注意,非结构体指针引用类型是 结构体类型变量 . 成员;
下面我们看一个例子:
对指向结构体类型变量的正确使用。
输入一个结构体类型变量的成员,并输出:
[cpp] view
plain copy
#include <stdlib.h>
#include <stdio.h>
struct data
{
int day,month,year;
};
struct stu
{
char name[20];
long num;
struct data birthday; /*嵌套的结构体类型成员*/
};
int main()
{
struct stu *student; /*定义结构体类型指针*/
student = malloc(sizeof(struct stu)); /*为指针变量分配安全的地址*/
printf("Input name,number,year,month,day:\n");
scanf("%s",student->name); /*输入学生姓名、学号、出生年月日*/
scanf("%ld",&student->num);
scanf("%d%d%d",&student->birthday.year,&student->birthday.month,
&student->birthday.day);
printf("\nOutputname,number,year,month,day\n");
/*打印输出各成员项的值*/
printf("%8s %5ld %d//%d//%d\n",student->name,student->num,
student->birthday.year,student->birthday.month,
student->birthday.day);
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct/tmp$ ./struct1
Input name,number,year,month,day:
xiao
10086
2012
12
22
Outputname,number,year,month,day
xiao 10086 2012//12//22
fs@ubuntu:~/qiang/struct/tmp$
程序中使用结构体类型指针引用结构体变量的成员,需要通过C提供的函数malloc()来为指针分配安全的地址。函数sizeof()返回值是计算给定数据类型所占内存的字节数。指针所指各成员形式为:
[cpp] view
plain copy
student->name
student->num
student->birthday.year
student->birthday.month
student->birthday.day
二、指向结构体类型数组的指针的使用
定义一个结构体类型数组,其数组名是数组的首地址,这一点前面的课程介绍得很清楚。
定义结构体类型的指针,既可以指向数组的元素,也可以指向数组,在使用时要加以区分。
上个例子中定义了结构体类型,根据此类型再定义结构体数组及指向结构体类型的指针
[cpp] view
plain copy
struct data
{
intday,month,year;
};
struct stu/*定义结构体*/
{
char name[20];
long num;
struct data birthday;/*嵌套的结构体类型成员*/
};
[cpp] view
plain copy
struct stustudent[4],*p; /*定义结构体数组及指向结构体类型的指针*/
使p=student,此时指针p就指向了结构体数组student。
p是指向一维结构体数组的指针,对数组元素的引用可采用三种方法。
1)地址法
student+i和p+i均表示数组第i个元素的地址,数组元素各成员的引用形式为:
(student+i)->name、(student+i)->num和(p+i)->name、(p+i)->num等。student+i和p+i与&student[i]意义相同。
2)指针法
若p指向数组的某一个元素,则p++就指向其后续元素。
3)指针的数组表示法
若p=student,我们说指针p指向数组student,p[i]表示数组的第i个元素,其效果与student[i]等同。对数组成员的引用描述为:p[i].name、p[i].num等
指向结构体数组的指针变量的使用:
[cpp] view
plain copy
#include <stdio.h>
#include <malloc.h>
struct data/*定义结构体类型*/
{
int year,month,day;
};
struct stu/*定义结构体类型*/
{
char name[20];
long num;
struct data birthday;
};
int main()
{
int i;
struct stu *p,student[4]={{"liying",1,1978,5,23},{"wangping",2,1979,3,14},
{"libo",3,1980,5,6},{"xuyan",4,1980,4,21}};
/*定义结构体数组并初始化*/
p = student;/*将数组的首地址赋值给指针p,p指向了一维数组student*/
printf("Outputname,number,year,month,day\n");
for(i = 0;i < 4;i++)/*采用指针法输出数组元素的各成员*/
printf("%8s %6ld %d//%d//%d\n",(p+i)->name,(p+i)->num,
(p+i)->birthday.year,(p+i)->birthday.month,
(p+i)->birthday.day);
return 0;
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct/tmp$ ./struct2
Outputname,number,year,month,day
liying 1 1978//5//23
wangping 2 1979//3//14
libo 3 1980//5//6
xuyan 4 1980//4//21
fs@ubuntu:~/qiang/struct/tmp$
附:给大家看一个有意思的程序:
写出一个模拟时钟程序
分析:我们知道时间有时 分 秒 组成,这里用结构体表示
代码如下:
[cpp] view
plain copy
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
typedef struct Clock
{
int hour;
int minute;
int second;
}Clock;
update(Clock *p)
{
p->second++;
if(p->second == 60)
{
p->second = 0;
p->minute++;
}
if(p->minute == 60)
{
p->minute = 0;
p->hour++;
}
if(p->hour == 24)
p->hour = 0;
}
Display(Clock *p)
{
printf("\r%02d:%02d:%02d",p->hour,p->minute,p->second);//%02d中0 输出数值时指定左面不使用的空位置自动填0,达到00:00:00效果
fflush(stdout);//前面曾经讲过,printf属于行缓冲,遇到\n或程序结束才会输出,这里没有\n,所以用fflush刷新;
}
int main()
{
Clock *clock;
clock = (Clock *)malloc(sizeof(Clock));
memset(clock,'\0',sizeof(Clock));//时钟初始化
while(1)
{
sleep(1);
update(clock);
Display(clock);
}
free(clock);
return 0;
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ ./clock
00:00:01
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ ./clock
00:00:55
这里是个动态效果,大家可以打印出来看一下
介绍结构体指针之前,先给大家看一个小程序:
[cpp] view
plain copy
#include <stdio.h>
#include <string.h>
#include <malloc.h>
struct Man
{
char name[10];
};
int main()
{
struct Man N;
N.name = "qiang";
printf("%s\n",N.name);
}
这段程序很简单,就是给结构体成员赋值,这里结构体成员是个数组,大家看看这种赋值方式有没有错,我们编译一下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ gcc -o struct4 struct4.c
struct4.c: In function ‘main’:
struct4.c:13:9: error: incompatible types when assigning to type ‘char[10]’ from type ‘char *’
fs@ubuntu:~/qiang/struct$
13行报错,就是赋值那行,报错原因是“字符分配的类型是不兼容的类型”
我们看看这句N.name = "qiang",右边是字符串常量,这里其实是字符串的首地址,就是一个地址,我们以前 char a[] = "qiang"没错啊,为什么这里报错了,我们看看左值,N.name, name 是数组名,是代表数组的首地址啊,但是我们要记住,这里name是个地址常量,是不能给常量赋值的,所以会报错,那我们如何给一个结构体中的字符数组赋值呢?我们这里用strcpy(N.name,"qiang") ! 当然我们N.name[1] = 'q',这样是可以的。
下面开始讲结构体指针:
一、指向结构体类型变量的使用
首先让我们定义结构体:
[cpp] view
plain copy
<span style="color:#000000;">struct stu
{
char name[20];
long number;
float score[4];
};
</span>
再定义指向结构体类型变量的指针变量:
struct stu *p1, *p2 ;
定义指针变量p1、p2,分别指向结构体类型变量。引用形式为:指针变量→成员;这里我们要注意,非结构体指针引用类型是 结构体类型变量 . 成员;
下面我们看一个例子:
对指向结构体类型变量的正确使用。
输入一个结构体类型变量的成员,并输出:
[cpp] view
plain copy
#include <stdlib.h>
#include <stdio.h>
struct data
{
int day,month,year;
};
struct stu
{
char name[20];
long num;
struct data birthday; /*嵌套的结构体类型成员*/
};
int main()
{
struct stu *student; /*定义结构体类型指针*/
student = malloc(sizeof(struct stu)); /*为指针变量分配安全的地址*/
printf("Input name,number,year,month,day:\n");
scanf("%s",student->name); /*输入学生姓名、学号、出生年月日*/
scanf("%ld",&student->num);
scanf("%d%d%d",&student->birthday.year,&student->birthday.month,
&student->birthday.day);
printf("\nOutputname,number,year,month,day\n");
/*打印输出各成员项的值*/
printf("%8s %5ld %d//%d//%d\n",student->name,student->num,
student->birthday.year,student->birthday.month,
student->birthday.day);
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct/tmp$ ./struct1
Input name,number,year,month,day:
xiao
10086
2012
12
22
Outputname,number,year,month,day
xiao 10086 2012//12//22
fs@ubuntu:~/qiang/struct/tmp$
程序中使用结构体类型指针引用结构体变量的成员,需要通过C提供的函数malloc()来为指针分配安全的地址。函数sizeof()返回值是计算给定数据类型所占内存的字节数。指针所指各成员形式为:
[cpp] view
plain copy
student->name
student->num
student->birthday.year
student->birthday.month
student->birthday.day
二、指向结构体类型数组的指针的使用
定义一个结构体类型数组,其数组名是数组的首地址,这一点前面的课程介绍得很清楚。
定义结构体类型的指针,既可以指向数组的元素,也可以指向数组,在使用时要加以区分。
上个例子中定义了结构体类型,根据此类型再定义结构体数组及指向结构体类型的指针
[cpp] view
plain copy
struct data
{
intday,month,year;
};
struct stu/*定义结构体*/
{
char name[20];
long num;
struct data birthday;/*嵌套的结构体类型成员*/
};
[cpp] view
plain copy
struct stustudent[4],*p; /*定义结构体数组及指向结构体类型的指针*/
使p=student,此时指针p就指向了结构体数组student。
p是指向一维结构体数组的指针,对数组元素的引用可采用三种方法。
1)地址法
student+i和p+i均表示数组第i个元素的地址,数组元素各成员的引用形式为:
(student+i)->name、(student+i)->num和(p+i)->name、(p+i)->num等。student+i和p+i与&student[i]意义相同。
2)指针法
若p指向数组的某一个元素,则p++就指向其后续元素。
3)指针的数组表示法
若p=student,我们说指针p指向数组student,p[i]表示数组的第i个元素,其效果与student[i]等同。对数组成员的引用描述为:p[i].name、p[i].num等
指向结构体数组的指针变量的使用:
[cpp] view
plain copy
#include <stdio.h>
#include <malloc.h>
struct data/*定义结构体类型*/
{
int year,month,day;
};
struct stu/*定义结构体类型*/
{
char name[20];
long num;
struct data birthday;
};
int main()
{
int i;
struct stu *p,student[4]={{"liying",1,1978,5,23},{"wangping",2,1979,3,14},
{"libo",3,1980,5,6},{"xuyan",4,1980,4,21}};
/*定义结构体数组并初始化*/
p = student;/*将数组的首地址赋值给指针p,p指向了一维数组student*/
printf("Outputname,number,year,month,day\n");
for(i = 0;i < 4;i++)/*采用指针法输出数组元素的各成员*/
printf("%8s %6ld %d//%d//%d\n",(p+i)->name,(p+i)->num,
(p+i)->birthday.year,(p+i)->birthday.month,
(p+i)->birthday.day);
return 0;
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct/tmp$ ./struct2
Outputname,number,year,month,day
liying 1 1978//5//23
wangping 2 1979//3//14
libo 3 1980//5//6
xuyan 4 1980//4//21
fs@ubuntu:~/qiang/struct/tmp$
附:给大家看一个有意思的程序:
写出一个模拟时钟程序
分析:我们知道时间有时 分 秒 组成,这里用结构体表示
代码如下:
[cpp] view
plain copy
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
typedef struct Clock
{
int hour;
int minute;
int second;
}Clock;
update(Clock *p)
{
p->second++;
if(p->second == 60)
{
p->second = 0;
p->minute++;
}
if(p->minute == 60)
{
p->minute = 0;
p->hour++;
}
if(p->hour == 24)
p->hour = 0;
}
Display(Clock *p)
{
printf("\r%02d:%02d:%02d",p->hour,p->minute,p->second);//%02d中0 输出数值时指定左面不使用的空位置自动填0,达到00:00:00效果
fflush(stdout);//前面曾经讲过,printf属于行缓冲,遇到\n或程序结束才会输出,这里没有\n,所以用fflush刷新;
}
int main()
{
Clock *clock;
clock = (Clock *)malloc(sizeof(Clock));
memset(clock,'\0',sizeof(Clock));//时钟初始化
while(1)
{
sleep(1);
update(clock);
Display(clock);
}
free(clock);
return 0;
}
执行结果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ ./clock
00:00:01
[cpp] view
plain copy
fs@ubuntu:~/qiang/struct$ ./clock
00:00:55
这里是个动态效果,大家可以打印出来看一下
相关文章推荐
- Linux C 内存管理
- Linux 应用---make及makefile的编写
- Linux C 中断言assert()使用简介
- 从头学习linux C 冒泡法排序
- linux C 学习 简单字符串逆序输出
- CentOS关闭图形界面(x window)
- Linux 常用到的功能及命令-FAQ
- 正则表达式理解
- ArchLinux 下文件描述符
- Linux C学习---递归函数
- Linux c学习--从标准输入输出看流和缓冲区
- Linux C 编程技巧--利用有限状态机模型编程
- linux C --深入理解字符串处理函数 strlen() strcpy() strcat() strcmp()
- gdb调试程序3
- Linux C编程---指针数组简析(二维数组、多级指针)
- linux的文件系统
- Linux C编程学习--main()函数简析
- linux C 学习---函数指针
- Linux C 指针练习
- Linux C 函数练习