Linux C 深入分析结构体指针的定义与引用

关于结构体的基础知识,网上书上都一大堆,这里就不赘述了,下面我们要学习的是结构体指针。

介绍结构体指针之前,先给大家看一个小程序:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <malloc.h>  
  4.   
  5. struct Man  
  6. {  
  7.     char name[10];  
  8. };  
  9.   
  10. int main()  
  11. {  
  12.     struct Man N;  
  13.     N.name = "qiang";  
  14.     printf("%s\n",N.name);  
  15. }  

这段程序很简单,就是给结构体成员赋值,这里结构体成员是个数组,大家看看这种赋值方式有没有错,我们编译一下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/struct$ gcc -o struct4 struct4.c  
  2. struct4.c: In function ‘main’:  
  3. struct4.c:13:9: error: incompatible types when assigning to type ‘char[10]’ from type ‘char *’  
  4. 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 plaincopy
  1. <span style="color:#000000;">struct stu  
  2. {  
  3.     char name[20];  
  4.     long number;  
  5.     float score[4];  
  6. };  
  7. </span>  


再定义指向结构体类型变量的指针变量:
struct stu *p1, *p2 ;
定义指针变量p1、p2,分别指向结构体类型变量。引用形式为:指针变量→成员;这里我们要注意,非结构体指针引用类型是  结构体类型变量 . 成员;

下面我们看一个例子:

对指向结构体类型变量的正确使用。

 输入一个结构体类型变量的成员,并输出:

[cpp] view plaincopy
  1. #include <stdlib.h>   
  2. #include <stdio.h>  
  3.   
  4. struct data   
  5. {  
  6.     int day,month,year;  
  7. };  
  8.   
  9. struct stu   
  10. {  
  11.     char name[20];  
  12.     long num;  
  13.     struct data birthday; /*嵌套的结构体类型成员*/  
  14. };  
  15.   
  16. int main()   
  17. {  
  18.     struct stu *student; /*定义结构体类型指针*/  
  19.     student = malloc(sizeof(struct stu)); /*为指针变量分配安全的地址*/  
  20.     printf("Input name,number,year,month,day:\n");  
  21.     scanf("%s",student->name); /*输入学生姓名、学号、出生年月日*/  
  22.     scanf("%ld",&student->num);  
  23.     scanf("%d%d%d",&student->birthday.year,&student->birthday.month,  
  24.             &student->birthday.day);  
  25.       
  26.     printf("\nOutputname,number,year,month,day\n");  
  27. /*打印输出各成员项的值*/  
  28.     printf("%8s    %5ld  %d//%d//%d\n",student->name,student->num,  
  29.         student->birthday.year,student->birthday.month,  
  30.         student->birthday.day);  
  31. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/struct/tmp$ ./struct1  
  2. Input name,number,year,month,day:  
  3. xiao  
  4. 10086  
  5. 2012  
  6. 12  
  7. 22  
  8.   
  9. Outputname,number,year,month,day  
  10.     xiao    10086  2012//12//22  
  11. fs@ubuntu:~/qiang/struct/tmp$   

程序中使用结构体类型指针引用结构体变量的成员,需要通过C提供的函数malloc()来为指针分配安全的地址。函数sizeof()返回值是计算给定数据类型所占内存的字节数。指针所指各成员形式为:

[cpp] view plaincopy
  1. student->name  
  2. student->num  
  3. student->birthday.year  
  4. student->birthday.month  
  5. student->birthday.day  

 

二、指向结构体类型数组的指针的使用
        定义一个结构体类型数组,其数组名是数组的首地址,这一点前面的课程介绍得很清楚。
        定义结构体类型的指针,既可以指向数组的元素,也可以指向数组,在使用时要加以区分。

上个例子中定义了结构体类型,根据此类型再定义结构体数组及指向结构体类型的指针

[cpp] view plaincopy
  1. struct data  
  2. {  
  3. intday,month,year;  
  4. };  
  5. struct stu/*定义结构体*/  
  6. {  
  7. char name[20];  
  8. long num;  
  9. struct data birthday;/*嵌套的结构体类型成员*/  
  10. };  
[cpp] view plaincopy
  1. 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 plaincopy
  1. #include <stdio.h>  
  2. #include <malloc.h>  
  3.   
  4. struct data/*定义结构体类型*/  
  5. {  
  6.     int year,month,day;  
  7. };  
  8.   
  9. struct stu/*定义结构体类型*/  
  10. {  
  11.     char name[20];  
  12.     long num;  
  13.     struct data birthday;  
  14. };  
  15.   
  16. int main()  
  17. {  
  18.     int i;  
  19.     struct stu *p,student[4]={{"liying",1,1978,5,23},{"wangping",2,1979,3,14},  
  20.         {"libo",3,1980,5,6},{"xuyan",4,1980,4,21}};  
  21.     /*定义结构体数组并初始化*/  
  22.     p = student;/*将数组的首地址赋值给指针p,p指向了一维数组student*/  
  23.     printf("Outputname,number,year,month,day\n");  
  24.     for(i = 0;i < 4;i++)/*采用指针法输出数组元素的各成员*/  
  25.         printf("%8s %6ld   %d//%d//%d\n",(p+i)->name,(p+i)->num,  
  26.                 (p+i)->birthday.year,(p+i)->birthday.month,  
  27.                 (p+i)->birthday.day);  
  28.   
  29.     return 0;  
  30. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/struct/tmp$ ./struct2  
  2. Outputname,number,year,month,day  
  3.   liying      1   1978//5//23  
  4. wangping      2   1979//3//14  
  5.     libo      3   1980//5//6  
  6.    xuyan      4   1980//4//21  
  7. fs@ubuntu:~/qiang/struct/tmp$   


 

附:给大家看一个有意思的程序:

写出一个模拟时钟程序

分析:我们知道时间有时 分 秒 组成,这里用结构体表示

代码如下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <malloc.h>  
  4. #include <string.h>  
  5.   
  6. typedef struct Clock  
  7. {  
  8.     int hour;  
  9.     int minute;  
  10.     int second;  
  11. }Clock;  
  12.   
  13. update(Clock *p)  
  14. {  
  15.     p->second++;  
  16.   
  17.     if(p->second == 60)  
  18.     {  
  19.         p->second = 0;  
  20.         p->minute++;  
  21.     }  
  22.   
  23.     if(p->minute == 60)  
  24.     {  
  25.         p->minute = 0;  
  26.         p->hour++;  
  27.     }  
  28.     if(p->hour == 24)  
  29.         p->hour = 0;  
  30. }  
  31.   
  32. Display(Clock *p)  
  33. {  
  34.     printf("\r%02d:%02d:%02d",p->hour,p->minute,p->second);//%02d中0 输出数值时指定左面不使用的空位置自动填0,达到00:00:00效果  
  35.     fflush(stdout);//前面曾经讲过,printf属于行缓冲,遇到\n或程序结束才会输出,这里没有\n,所以用fflush刷新;  
  36. }  
  37.   
  38. int main()  
  39. {  
  40.     Clock *clock;  
  41.     clock = (Clock *)malloc(sizeof(Clock));  
  42.     memset(clock,'\0',sizeof(Clock));//时钟初始化  
  43.   
  44.     while(1)  
  45.     {  
  46.         sleep(1);  
  47.         update(clock);  
  48.         Display(clock);  
  49.     }  
  50.     free(clock);  
  51.     return 0;  
  52. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/struct$ ./clock  
  2. 00:00:01  
[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/struct$ ./clock  
  2. 00:00:55  

这里是个动态效果,大家可以打印出来看一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20155313 预备作业二

你有什么技能比大多人&#xff08;超过90%以上&#xff09;更好&#xff1f;针对这个技能的获取你有什么成功的经验&#xff1f;与老师博客中的学习经验有什么共通之处&#xff1f; 说到一个比90%的人要强的技能&#xff0c;我一下子很惆怅&#xff0c;说起来&#xff0c;从小家…

react 父子组件之间相互传值

From: https://blog.csdn.net/luzhaopan/article/details/85003362 1、定义父组件 import React, { PureComponent } from react; export default class Father extends PureComponent { render(){ return( <div> …

android 多线程概述

android多线程&#xff0c;一直是一个麻烦的事情&#xff0c;要掌握它的本质&#xff0c;我们需要搞清楚一个问题&#xff0c;linux多线程的本质。 我们这篇文章&#xff0c;来讨论以下的议程&#xff1a; 了解linux的历程&#xff0c;了解android的异步任务机制&#xff0c;了…

Linux 进程间通讯详解一

进程间的通讯 两台主机间的进程通讯 --socket一台主机间的进程通讯 --管道&#xff08;匿名管道&#xff0c;有名管道&#xff09; --System V进程间通信&#xff08;IPC&#xff09;包括System V消息队列&#xff0c;System V信号量&#xff0c;System V共享内存 --socket 进程…

Linux C 函数指针应用---回调函数

&#xff08;这里引用了知乎上一些知友的回答&#xff0c;感觉不错&#xff0c;有助于理解&#xff0c;这里引用作为借鉴&#xff0c;如有冒犯&#xff0c;烦请告知&#xff09; 我们先来回顾一下函数指针&#xff0c;函数指针是专门用来存放函数地址的指针&#xff0c;函数地址…

laravel+vue开发环境搭建

From: https://www.jianshu.com/p/1c2cc11ba46f 描述 最近通过laravel在公司做了一些项目&#xff0c;但本身前端出身的我&#xff0c;总是感觉lphp开发过程中,前端写好页面&#xff0c;然后后端还需要再套blade模板&#xff0c;感觉这样开发效率太慢&#xff0c;太low。于是自…

GC Blocks Lost等待事件

在Oracle RAC环境中&#xff0c;无论我们从AWR自动负载性能报告、Statspack或者Grid Control中都可以找到Oracle数据库软件所收集的全局缓存工作负载统计信息(global cache work load statistics)&#xff1b;其中就包含了全局缓存块丢失(Global cache lost blocks)的统计信息(…

What's VPC (by quqi99)

作者&#xff1a;张华 发表于&#xff1a;2014-12-09版权声明&#xff1a;可以任意转载&#xff0c;转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) VPC&#xff08;virtual private cloud&#xff0c;虚拟私有云&#xff…

WCF简单教程(5) 用IIS做Host

第五篇&#xff1a;用IIS做Host之前几篇的Demo中&#xff0c;我们一直在用控制台程序做Server&#xff0c;今天换IIS来做Host&#xff0c;在Web Application中添加WCF的服务。其实在Web Application中添加WCF服务是最简单的&#xff0c;“新建项”中有专用的“WCF服务”&#x…

黑苹果折腾记

From: https://fishedee.com/2018/10/04/%E9%BB%91%E8%8B%B9%E6%9E%9C%E6%8A%98%E8%85%BE%E8%AE%B0/ 1 概述 黑苹果折腾记&#xff0c;原来的Macbook Pro已经不太好用了&#xff0c;运行编译时就开始风扇呼呼声的响&#xff0c;我只有想办法将苹果安装上现有的台式机上了。 类…

解决爬虫中文乱码问题

解决爬虫中文乱码问题 今天群里有个人反映某个网址爬出来的网页源代码出现中文乱码&#xff0c;我研究了半天&#xff0c;终于找到了解决方法。 一开始&#xff0c;我是这样做的&#xff1a; import requestsurl http://search.51job.com/jobsearch/search_result.php?fromJs…

记录每个用户的操作记录(命令)

通过设置日志文件可以对每个用户的每一条命令进行记录&#xff0c;这一功能默认是不开放的&#xff0c;为了打开它&#xff0c;需要安装pacct工具&#xff0c;并执行以下命令&#xff1a; #touch /var/log/pacct #accton /var/log/pacct 执行读取命令lastcomm [user name] –f …

多进程 VS 多线程

在Linux下编程多用多进程编程少用多线程编程。 IBM有个家伙做了个测试&#xff0c;发现切换线程context的时候&#xff0c;windows比linux快一倍多。进出最快的锁&#xff08;windows2k的 critical section和linux的pthread_mutex&#xff09;&#xff0c;windows比linux的要快…

黑苹果SSDT使用

From: https://blog.csdn.net/qq_33544860/article/details/77320073 1.在Clover引导界面&#xff0c;按一下&#xff3b;F4&#xff3d;,就会在EFI\CLOVER\ACPI\origin\生成好多*.aml的文件&#xff0c;例如APIC.aml&#xff0c;BGRT.aml&#xff0c;DSDT.aml&#xff0c;HPE…

c# 如何在webbrowser控件执行一段JS代码

var doc this.WebBrowser.Document.DomDocument as IHTMLDocument2; var win doc.parentWindow as IHTMLWindow2;string jscode "//这里写JS代码";win.execScript(jscode, "javascript");转载于:https://www.cnblogs.com/pasijiubiehuozhe/p/6201439.ht…

一夜暴富之前的漫漫长路

一夜暴富之前的漫漫长路发布于&#xff1a;2013-08-05 09:50阅读数&#xff1a;987那你现在在做什么&#xff1f; 唉&#xff0c;我讨厌这个问题。 事实上&#xff0c;我正在努力做一个新的项目&#xff0c;但没有取得任何的进展。 但是&#xff0c;我并没有抱怨什么&#xff0…

java开发过程中,报错Dangling meta character '*' near index 0,解决办法

From: https://blog.csdn.net/zhouzhiwengang/article/details/53493810 1、split方法转化字符串为数组&#xff1a; String[] strPicArr map.get("hw_pic").toString().split("*"); 报错&#xff1a; java.util.regex.PatternSyntaxException: Dangling…

演示:Linux工程环境应用实训(防火墙、NAT、静态路由)详细配步骤

各位童鞋注意&#xff1a;该实验完成可以使用GNS3与4虚拟机进行桥接&#xff0c;然后在一台物理计算机上完成&#xff0c;不虽要去拿真正的4台服务器或者交换机路由器来连成一个网络&#xff0c;现在大家都使用网络仿真教学与实验&#xff01;Linux工程环境应用实训&#xff08…

Linux架构

Linux架构 作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; 我以下图为基础&#xff0c;说明Linux的架构(architecture)。(该图参考《Advanced Programming in Unix Environment》) 最内层是硬件…

Linux C学习--getline()函数

getline()函数是什么&#xff1f;百度百科这样解释&#xff1a; getline不是C库函数&#xff0c;而是C库函数。它会生成一个包含一串从输入流读入的字符的字符串&#xff0c;直到以下情况发生会导致生成的此字符串结束。1&#xff09;到文件结束&#xff0c;2&#xff09;遇到函…