Linux C 程序 (13)

C语言预处理,结构体

C语言预处理命令
1.宏定义

1.无参数宏

1    #define 标识符 字符串
2            #代表本行是编译预处理命名
3            习惯上,宏定义大写
4            代替一个字符串,介绍重复书写某个字符串的工作量
5            有意义的宏代表无规律的字符串,增强可读性
6            范围:宏定义开始到本源程序文件结束,可以使用#undef提前终止作用范围
7            宏定义允许嵌套,前面定义了的宏可以被后面的宏使用    

2.有参数宏

 1    #define 标识符(形参表) 字符串
 2 #include<stdio.h>
 3 #define  MAX(x, y)   (x > y ? x : y)
 4
 5 int main (){
 6         int a = 5 , b = 10 , max ;
 7         //MAX(a ,b)被宏替代
 8         max = MAX(a , b);
 9         printf("max=%d",max);
10 }
11
12             宏名与形参表的圆括号之间不能有空格
13             字符串内的形参最好用括号括起来
14             #define MUL(x, y) x*y
15             c = MUL(a+1,b+1);  ==>  a+1*y+1
16             应该为(a+1)*(b+1)
17             所以:#define MUL(x,y) (x)*(y)
18             有参数的宏的形参不是变量,不分配内存空间,不说明类型参数
19             预处理程序认为有参数宏的实参是字符串a+1先去替换x而不是先运算a+1再替换x
20             宏替换不会占用运行时间,只是编译时间长一些,而函数调用会占运行时间,一般用宏来代表一些比较简单的表达式。

2.文件包含#include

1 文件包含命令是把指定文件全部包含进来,插入到命令所在位置,取代原来的命令行,由当前文件和指定文件组成一个文件,一起编译。
2 一个#include只包含一个文件
3 #include<>  和 #include ""
4 区别查找指定文件的位置不同。
5 尖括号只在缺省目录里找文件,缺省目录由用户设置的编程环境所决定。
6 双引号先在    源程序文件所在的当前目录找指定文件,没有的话再在缺省目录里找。

3.条件编译
对一部份内容指定编译条件。

 1     1.范式一
 2     #ifndef 标识符
 3     .....
 4     #endif
 5     eg:
 6     #ifndef _getkey_h
 7         #define _getkey_h
 8         #include<sys/types.h>
 9     #endif
10     如果没有定义常量 _getkey_h则定义_getkey_h然后把sys/types.h包含进来
11     2.范式二
12     #ifndef 标识符
13     ...1...
14     #else
15     ...2...
16     #endif
17     如果没有定义标识符,编译1,否则编译2
18     3.范式三
19     #ifdef
20     ......
21     #endif
22     定义了标识符,就编译
23         eg:#ifdef  DEBUG
24                     printf("debug----");
25              #endif
26         在调试程序的时候在源程序头部加入
27         #define DEBUG
28         用于调试
29         4.范式四
30         #ifdef 标识符
31         ......
32         #else
33         ......
34         #endif
35         5.范式五
36         #if 表达式
37         ......
38         #endif
39         表达式成立,编译
40         6.范式六
41         #if 表达式
42         ......
43         #else
44         ......
45         #endif

4.结构体和共用体
   1.声明和引用结构体

 1    struct 结构体名
 2    {
 3        成员列表
 4    };
 5    声明结构体也是一个C语言语句,分号来结束,相当于构造了一个新的数据类型
 6    struct person
 7    {
 8        char name[20];
 9        int age;
10        char sex;
11        char phone[15];
12    };
13    struct person p1,p2;
14    系统为这个person结构体分配的内存为20+4+1+15=40字节
15    printf("%d",sizeof(p1));
16    如果把char phone[15]改为char phone[16],结果不是41,而是44
17    //内存为了提高访问效率有一个规则:4字节对齐
18    申明结构体时也可以同时定义变量
19    struct person
20    {
21        char name[20];
22        ......
23    }p1,p2;
24    另一种方式:没有声明结构体名,不能再定义其他结构体
25    struct
26    {
27        char name[20];
28        ......
29    }p1,p2;

2.引用和初始化结构体变量

1  struct person p1;
2    strcpy(p1.name,"fubin");
3    p1.age=23;
4    p1.sex=‘m‘;
5    strcpy(p1.name,"18573116140");
6    printf("%s",p1.name);
7    "."是成员运算符,在所有运算符中优先级最高

3.结构体和数组

 1  struct person p[2] = {{"f1",21,‘m‘,"123456789"},{"f2",22,‘w‘,"123456789"}};
 2    eg:
 3        #include<stdio.h>
 4         #include<string.h>
 5 int main(){
 6         struct student {
 7                 int number;
 8                 char name[20];
 9                 char sex ;
10                 int age;
11                 char addr[30];
12         };
13
14         struct student s[3] = {{10000,"zhaang",‘m‘,21,"shenzheng"},{10001,"li",‘w‘,23,"guangzhou"}};
15
16         s[2].number=10002;
17         s[2].sex=‘m‘;
18         s[2].age=23;
19         strcpy(s[2].name,"fubin");
20         strcpy(s[2].addr,"hunanchangsha");
21         int i;
22         for(i = 0 ; i < sizeof(s)/sizeof(s[0]) ; i++){
23                 printf("%d,%s,%c,%d,%s\n",s[i].number,s[i].name,s[i].sex,s[i].age,s[i].addr);
24         }
25         return 0;
26 }

获得结构体数组的长度的方法:sizeof(s)/sizeof(s[0]);

4.结构体和指针

 1     结构体中的成员是按顺序连续存放在内存中,一个结构体指针指向结构体变量,结构体指针保存的值是它所指向的结构体变量的内存首地址。
 2     struct student s1;
 3     struct student *p;
 4     s1.number=10002;
 5     s1.sex=‘m‘;
 6     s1.age=23;
 7     strcpy(s1.name,"fubin");
 8     strcpy(s1.addr,"123124134");
 9     p=&s1;
10     printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr);
11
12     (*p).number  =====  p->number
13     一般不用前者
14     p->number++ 得到number,使用之后再加1
15     ++p->number 先加1,再使用

5。指向结构体数组的指针

 1     eg:
 2 #include<stdio.h>
 3 #include<string.h>
 4 int main(){
 5         struct student {
 6                 int number;
 7                 char name[20];
 8                 char sex ;
 9                 int age;
10                 char addr[30];
11         };
12
13         struct student s[3] = {{1000,"fafa",‘m‘,34,"shenz"},{1001,"hioh",‘w‘,23,"guangzhou"},{1002,"fe",‘m‘,12,"dongguan"}};
14
15         struct student *p;
16         for(p=s ; p < s+3 ; p++){
17                 printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr);
18         }
19
20         return 0;
21
22 }

6.结构体指针做函数的参数

1 void print_struct(struct student *p){
2     p->age++;
3     printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr);
4 }
时间: 2024-11-05 19:01:49

Linux C 程序 (13)的相关文章

linux 统计 程序 运行时间

测试 代码运行时间 linux 中的 <sys/time.h> 中 有个函数可以获取当前时间,精确到 微秒 ---->  gettimeofday() 1 #include <sys/time.h>       // int gettimeofday(struct timeval *tv, struct timezone *tz); 2 /********************************************* 3 * struct timeval 4 *

嵌入式linux应用程序调试方法

嵌入式linux应用程序调试方法 四 内存工具 17 4.1 MEMWATCH 17 4.2 YAMD 22 4.3 Electric Fence 24 五 C/C++代码覆盖.性能profiling工具 24 5.1 用gcov来测试代码覆盖率 25 5.2 使用gprof来优化你的C/C++程序 35 四 内存工具 您肯定不想陷入类似在几千次调用之后发生分配溢出这样的情形. 许多小组花了许许多多时间来跟踪稀奇古怪的内存错误问题.应用程序在有的开发工作站上能运行,但在新的产品工作站上,这个应用

linux c程序中获取shell脚本输出的实现方法

linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作.比如实现一个ping程序来测试网络的连通性,实现ping函数需要写上200~300行代码,为什么不能直接调用系统的ping命令呢?通常在程序中通过 system函数来调用shell命令.但是,system函数仅返回命令是否执行成功,而我们可能需要获得shell命令在控制台上输出的结果.例如,执行外部

谈谈Linux应用程序 ABI兼容性

谈谈Linux应用程序ABI兼容性 背景 最近工作中遇到个问题,就是多个系统跑着不同版本的内核,不同架构的ARM芯片,上层的业务程序能否二进制归一(共镜像). 根据自己对Linux的了解,glibc是否可以在ABI层面做到向前兼容.那个整个系统能否做到呢?这勾起了我的分析和思考. ABI兼容依赖什么 试想一下,一个程序从源代码到最终的二进制,有哪些组件参与了编译和链接过程,大概如下: 内核导出用户态头文件 gcc编译器,gcc提供的静态.o/.a,以及它提供的动态库(如libgcc_s.so)

linux应用程序地址布局

Linux应用程序在内存中的布局,由高地址到低地址依次为:栈.堆.BSS段.数据段.代码段.代码段的起始地址固定为0x8048000,无论哪一个应用程序它的代码段起始地址一定是0x8048000,这里的地址虚拟地址,映射到不同的物理地址中去. 查看程序各段的地址 ps    aux     这个命令用于查看进程的ID,比如我运行一个可执行程序addr 可以看到addr的进程ID是24048.然后用cat命令查看进程在内部的布局 cat    /proc/进程ID/maps,这里我们是cat   

Linux 应用程序 之 IO编程(一)

我的linux 环境是windows8.1 + VMware6.5.1+  Fedora14,参考书籍:第六章 链接:Linux应用程序开发详解(1-11).pdf 我利用一个SSH软件SSH Secure File Transfer Client 来从Linux传输文件 来张虚拟机运行Fedora的图: 下面步入正题: IO最基本操作: 1 //hello.c 2 #include <unistd.h> 3 #include <sys/types.h> 4 #include &l

Linux C++程序进行性能分析工具gprof使用入门

性能分析工具 软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键.这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是要重点测试版本的性能表现和稳定性的.对于软件测试过程中发现的性能问题,如何定位有很多的方法.基本的方法可能是开发者对代码进行review,或者是使用一些工具对代码进行性能分析.常见的性能分析tuning工具有哪些呢?下面两篇文章做了详细的总结: https://computing.llnl.gov/

《Linux高性能服务器编程》学习总结(七)——Linux服务器程序规范

第七章      Linux服务器程序规范 服务器程序除了需要网络通信外,还应该考虑很多其他的细节,而这些细节很多很杂,但又基本是模板式的.1)服务器程序基本都是以后台形式运行的,没有控制终端,不能接受用户输入,其父进程通常是init.2)服务器程序有一套日志系统.3)服务器程序以某个专门的非root身份运行.4)服务器通常是可配置的.5)服务器进程启动时通常会生成一个PID文件以记录后台进程的PID.6)服务器程序同城需要考虑系统资源和限制. 服务器一般使用syslog函数与rsyslogd守

Linux网络服务13——PXE高效能批量网络装机

Linux网络服务13--PXE高效能批量网络装机 一.PXE简介 PXE:Pre-boot Excution Environment,预启动执行环境 PXE是由Intel公司开发的网络引导技术,工作在Client/Server模式,允许客户机通过网络从远程服务器下载引导镜像,并加载安装文件或者整个操作系统. 若要搭建PXE网络体系,必须要满足以下条件: ·客户机的网卡支持PXE协议(集成BOOTROM芯片),且主板支持网络引导. ·网络中有一台DHCP服务器,以便为客户机分配地址.指定引导文件