1、宏定义

1.1、不带参数的宏定义

#define 标识符 字符串           例如:#define PI 3.1415926

说明:

(1)宏名一般习惯用大写字母表示,但并非规定,也可以用小写

(2)使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量

(3)宏定义是用宏名代替一个字符串,也就是做简单的置换,并不做正确性检查。 比如如果写成 :

#define PI 3.l4l5926(把1错写成了l),

在预编译时并不会做任何语法检查,只有在编译已经把宏展开后的源程序时才会发现语法错误并报告

(4)宏定义不是C语句,不必在行末加分号,如果加了分号将会连同分号一起进行置换。 比如如果写成:

#define PI 3.1415926;                    area=PI*r*r;

则宏展开后该语句为:area=3.1415926;*r*r

(5)#define命令出息在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束,通常宏定义写在文件开头,在此文件范围内有效

(6)可以用#undef命令来终止宏定义的作用域,这样可以灵活控制宏定义的作用范围

(7)在进行宏定义时,可以应用已经定义的宏名,可以层层置换

(8)对程序中用引号括起来的字符串内的字符,即使与宏名相同,也不进行置换

(9)宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只做支付替换,不分配内存空间

1.2、带参数的宏定义

#define 宏名(参数表) 字符串         例如:#define S(a,b) a*b                   ·                   ·                   ·

area=S(3,2);

说明:

(1)对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的形参

(2)在宏定义时,在宏名与带参数的括号之间不应加空格,否则将空格以后的字符都作为代替字符串的一部分。

#define S (r)    PI*r*r       ---------  加红色部分不能有空格

1.3、对于带参数的宏定义与函数的区别

(1)函数调用时,先求出实参表达式的值,然后代入形参,而使用带参数的宏只是进行简单的字符替换

(2)函数调用是在程序运行时处理的,为形参分配临时的内存空间,宏展开是在编译前进行的,在展开时并不分配内存单元,不进行值的传递,也没有“返回值”的概念

(3)对函数中的市场和形参都要定义类型,二者的类型要求一致,如不一致则要进行类型转换,而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符合代替,展开时代入指定的字符串即可,宏定义时,字符串可以是任何类型的数据

(4)调用函数只可得到一个返回值,而用宏可以设法得到几个结果.

得到几个结果,怎么理解呢?

#define PI 3.1415926

#define CIRCLE(R,L,S,V)    L=2*PI*R; S=PI*R*R; V=4.0/3.0*PI*R*R*R

void main()

{

float r,l,s,v;

scanf("%f",&r);

CLE(r,l,s,v);

printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v );

}

---------------------------

真正意义上的返回值, 应该是可以直接等于的.

Variable = fun();

如果宏能实现一个"="号赋给多个, 这才叫做多个返回值.但是实际上,这里并不能严格意义上进行多个结果的返回值,展开后可以发现其等价形式多个变量进行赋值操作,而不是严格意义上的通过返回值赋值"Variable = fun()".

(5)宏使用次数多是,宏展开后源程序变长,因为每次展开都使程序增长,而函数调用不会

(6)宏替换不占用运行时间,只占编译时间,而函数调用则占用运行时间用于分配单元、保存现场、值传递、返回等


注:

  • 多层#define   TURE 或 FALSE 或 其他 一定要明确,不然可能会被优化掉

  • 宏定义出现在结构体内

预编译与编译两者的区别:宏定义是在预编译时就会去找到相应的常量去替换,就是在编译成目标文件之前已经进行了替换,所以这里在结构体中有宏定义不会被重复编译,也就不可能为结构体中的宏定义分配内存。

作用域还是开始于#define,结束于#undef,不会存在只作用于结构体之内的可能。把宏定义放在结构体中,主要是为了代码更加直观,让人一看就知道改结构体中的个标志位是什么,被定义在哪一位 ,以便于理解运算。




2、结构体

struct  结构体标识名

{

类型名1  结构成员表1;

类型名2  结构成员表2;

类型名n  结构成员表n;

}

注意:struct是关键字,是结构体类型的标志。“结构体标识名”和“结构体成员名”都是用户定义的标识符,“结构体标识名”是可选项,在说明中可以不出现。每个“结构成员表”中都可以含有多个同类型的成员名,它们之间用逗号隔开。结构体中的成员名可以和程序中的其他变量名相同,不同结构体中的成员也可以同名。要记住:结构体说明要以分号结尾

定义结构体类型的变量、数组、和指针变量可用4种方式:

a:紧跟在结构体类型说明之后进行定义;

b:在说明一个无名结构体类型的同时直接进行定义;

c:先说明结构体类型,再单独进行变量定义;

d:使用typedef说明一个结构体类型名,再用新类型名来定义变量。

如果已经定义了一个结构体变量和基类型为同一结构体类型的指针变量,并使该指针指向同类型的变量,则引用结构体变量中的成员可以用以下三种形式:

形式1:结构体变量名.成员名        形式2:指针变量名->成员名    形式3:(*指针变量名).成员名

注意:结构体变量名也可以是已经定义的结构体数组中的数组元素。

说明:点号(.)称为成员运算符;箭头(->)称为结构指向运算符,它由减号和大于号两部分组成,它们之间不能有空格;在形式三中,一对圆括号不可少。这两个运算符与圆括号、下标运算符的优先级相同,在c语言的运算符中优先级最高。

..............................................................................

初始化成员:

顺序初始化

顺序初始化struct必须要按照成员的顺序进行,缺一不可,如果结构体比较大,很容易出现错误,而且表现形式不直观,不能一眼看出各个struct各个数据成员的值。

乱序初始化

  乱序初始化是C99标准新加的,比较直观的一种初始化方式。相比顺序初始化而言,乱序初始化就如其名,成员可以不按照顺序初始化,而且可以只初始化部分成员,扩展性较好。linux内核中采用这种方式初始化struct。

 乱序初始化有两种方式,一种是用点(.)符号;一种是用冒号(:)。方式一是C99标准,方式二是GCC的扩展,强烈建议使用第一种方式。

未被初始化的成员默认为0(指针类型的成员默认为NULL)。两种乱序初始化方法,即可以用在C代码中,也可以用在C++代码

..............................................................................


3、枚举

在程序中,可能需要为某些有限的整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,更普遍采用的是枚举类型。

enum  枚举类型名 {常量1,常量2,常量3,.......};

enum DAY

{MON=1, TUE, WED, THU, FRI, SAT, SUN};

(1) 枚举型是一个集合,枚举成员是一些命名的整型常量,元素之间用逗号“,”隔开。

(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项

(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。

(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。

(5) 枚举型是预处理指令 #define 的替代。

(6) 类型定义以分号“;”结束。

声明变量

enum DAY yesterday;

enum DAY today;

enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days; // 变量days的类型为枚举型enum week

typedef enum { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} WEEK;

typedef enum WEEK { Mon=1, Tue, Wed, Thu, Fri Sat, Sun};

WEEK Monday;

WEEK Tuesday;

  • 同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。
  • 定义声明赋初值可以同时进行。

#include <stdio.h>

/* 定义枚举类型,同时声明该类型的三个变量,并赋初值。它们都为全局变量 */

enum DAY

{

MON=1,

TUE,

WED,

THU,

FRI,

SAT,

SUN

} yesterday = MON, today = TUE, tomorrow = WED;

  • 对枚举型的变量赋整数值时,需要进行类型转换

#include <stdio.h>

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

void main()

{

enum DAY yesterday, today, tomorrow;

yesterday = TUE;

today = (enum DAY) (yesterday + 1); //类型转换

tomorrow = (enum DAY) 30; //类型转换

//tomorrow = 3; //错误

printf("%d %d %d \n", yesterday, today, tomorrow); //输出:2 3 30

}

  • 枚举类型与sizeof运算符(可以量enum当做一个类似的 int 变量类型)

enum escapes

{

BELL      = '\a',

BACKSPACE = '\b',

HTAB      = '\t',

RETURN    = '\r',

NEWLINE   = '\n',

VTAB      = '\v',

SPACE     = ' '

};

enum BOOLEAN { FALSE = 0, TRUE } match_flag;

void main()

{

printf("%d bytes \n", sizeof(enum escapes)); //4 bytes

printf("%d bytes \n", sizeof(escapes)); //4 bytes

printf("%d bytes \n", sizeof(enum BOOLEAN)); //4 bytes

printf("%d bytes \n", sizeof(BOOLEAN)); //4 bytes

printf("%d bytes \n", sizeof(match_flag)); //4 bytes

printf("%d bytes \n", sizeof(SPACE)); //4 bytes

printf("%d bytes \n", sizeof(NEWLINE)); //4 bytes

printf("%d bytes \n", sizeof(FALSE)); //4 bytes

printf("%d bytes \n", sizeof(0)); //4 bytes

}

  • 枚举类型作为函数的参数

#include "stdio.h"

typedef enum { e0 = 0, e1, e2, e3, e4, eMax }testEnum;

void fun(testEnum te)

{

printf("%d\r\n", te);

}

int main(void)

{

fun(e3);

fun((testEnum)8);

//fun(8); // ERROR:invalid conversion from 'int' to 'testEnum '

return 0;

}

输出: 3 8

枚举(enum)、宏定义(#define)、结构体(struct)的拾遗相关推荐

  1. 枚举,联合,宏定义,结构体

    一,枚举 (1)枚举也可以用来创建新的数据类型,枚举类型存储区就是一个整数类型存储区,只不过这个存储区里只能记录有限的几个整数(2)声明枚举类型时需要提供一组名称,每个名称代表一个整数,这些整数都可以 ...

  2. C/C++结构体struct 与结构体数组和枚举型enum的结合使用

    C/C++结构体struct 与结构体数组和枚举型enum的结合使用 #include "stdafx.h" #include <string> #include &l ...

  3. 枚举、宏定义enum /defint/typedef

    #pragma mark 分类,可快速搜索 #pragma mark 1 枚举创建 int enumOne() {     enum Season {spring=1,summer,autumn,wi ...

  4. 结构体struct timeval 和 struct timespec的定义

    结构体struct timeval 和 struct timespec的定义均在头文件<sys/time.h>中,具体定义如下: struct timeval {long tv_sec; ...

  5. 结构体struct声明、定义

    结构体是一种构造类型(结构体.数组.联合类型),结构体弥补了数组不能存储多种类型的缺陷(即结构体是由于相同类型或不同类的成员组成) 一般声明形式如: struct 结构体名称 { 成员列表 }; st ...

  6. golang 结构体struct、数组、结构体数组 定义与赋值 、json string转struct

    文章目录 1.结构体struct 1.1 声明结构体 1.2 初始化结构体 以及 传参 2. 结构体数组.append 3. 接口返回 含数组的结构体 常用写法 json string转struct ...

  7. c语言结构体定义蚂蚁,C语言结构体(struct)常见使用方法

    C语言结构体(struct)常见使用方法 C语言结构体(struct)常见使用方法 基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合) ...

  8. 关于C语言结构体(struct)介绍

    转自:微点阅读  https://www.weidianyuedu.com 导读:       C语言结构体,怎么理解? 你可以把它想象成一个桌面上的文件夹,这个文件夹里面可以有各种各样的文件,当然也 ...

  9. C语言 结构体struct总结

    文章目录 一.前言 二.结构体的引入 三.结构体声明 四.结构体变量的定义 五.结构体变量的初始化 六.结构体变量成员的访问 七.结构体存储原理 八.结构体数组 8.1结构体数组的定义 8.2结构体数 ...

最新文章

  1. Istio Pilot源码浅析
  2. 【ubuntu perf安装】The program 'perf' is currently not installed.
  3. 元计算:IT巨头的金钱收割机,核武器
  4. 【Spring MVC学习】详解spring mvc 3.0常用注解
  5. Repeater在无数据记录时显示“无相关记录...”
  6. bzoj2435: [Noi2011]道路修建 树上dp
  7. Vue中过滤器的使用
  8. 2.权限管理准备工作:你应该知道的ASP.NET网站最基本的安全措施!
  9. linux svn客户端通过 https访问windows VisualSVN Server Manager
  10. 如何对matlab .m代码文件进行加密
  11. 条码软件如何制作SCC-14条形码
  12. erewrwerwer
  13. 【杂烩】Tesla M40 训练机组装与散热改造
  14. ARM体系结构2:处理器内核和汇编指令集
  15. 关于原型法,以及敏捷的需求 2010-9-13
  16. 中秋节的广西甘蔗——智蔗见智·向新而生
  17. Python 生成总和一定的随机数
  18. Push failed Unable to access ‘https://github.com/‘: Failed to connect to github.com port 443: Timed
  19. 轮廓中对踵点/旋转卡壳
  20. 接线 科思模块怎么和plc_plc控制系统输出模块与输出设备的连接方法图解

热门文章

  1. 2019年下半年教师资格小学《综合素质》真题与参考答案
  2. Springboot是怎么实现将数据库的数据展示到html的
  3. 博士论文的开题报告写作
  4. 关于Keil5编译器报错:ARMLMD_LICENSE_FILE: unset - 解决
  5. this iPhone7 Plus is running IOS11.3(15E216),which may not be supported by this verson of Xcode.
  6. DWZ(JUI) 教程 普通表单提交
  7. “秦农直供”农产品垂直电商平台UML
  8. Cannot find class com.test.domain.User for bean with nain file[applicationContext.xml]
  9. 面试官问我List接口,我
  10. 【SDCC讲师专访】京东数据库系统研发部负责人田琪的架构之路