C语言中typedef,条件编译,结构体的说明
typedef (类型别名)
typedef关键字,可以给类型取别名(alias),语法:
typedef 原类型名 新类型名
使用typedef去给函数指针类型取别名,语法略有不同。
typedef void(*PFNTYPE1)(int sig);
typedef void(*PFNTYPE2)(int sig);
PFNTYPE2 mysignal(int sig, PFNTYPE1 func);
善于使用typdef,可以增强代码可读性。
也可以减少重构中修改代码的量。
条件编译
条件编译属于一种预处理命令,它可以根据宏是否定义,来决定某段代码是否要编译。
假设一个场景,我们写的程序,可能在windows和Linux上编译,在Linux上,因为种种原因,不能得到全面的支持。
我们希望按照条件编译,只要一份源码,可以自动的编译出windows和linux对应的版本。
#ifdef ARCH_WIN
/*代码段1*/
int main(int argc, char* argv[])
{
printf("windows, OK");
return 0;
}
#else
int main(int argc, char* argv[])
{
printf("Linux, OK");
return 0;
}
#endif
以上代码:如果定义了ARCH_WIN这个宏,那么编译代码段1,否则,编译代码段2.
条件编译在工程中的应用非常多。比如我们所谓的Debug版本,和Release版本其实就是条件编译控制的。
我们不仅可以通过define指令去设置宏,还可以通过VS设置宏:
vs设置宏的原理,是直接通过编译器的编译选项设置。所以对于所有的cpp文件全部生效。
条件编译在头文件包含中的应用
赤裸裸的头文件包含,容易产生重复包含的问题。
有些头文件被重复包含了。轻则降低效率,重则编译出错。
我们可以使用条件编译,解决这个问题。
解决方案,是按照以下模板去写头文件:
#ifndef 非常特殊的宏
#define 非常特殊的宏
你的头文件的内容……
#endif
这种套路,被更新的指令
#pragma once
所取代。
结构体
现在,我们开始学习非基本数据类型。非基本数据类型,顾名思义,不是编译器天生
直到的类型。是程序员发明的类型:
- 程序员先发明新类型(非基本数据类型)
- 然后再用新类型,去定义新变量
我们即将学习的结构体(struct),是C语言中最重要的非基本数据类型。
它的发明目的,是为了复合信息。
举例,如果我们要写一个学生管理系统,那么当然要保存学生的信息,比如: - 姓名, char[12]
- 性别, int
- 学号, int
如果没有到结构体语句的话
记录一,两个学生的信息还好,当需要记录的学生越来越多时,容易出错。因为姓名、ID、学号没有被很好
的封装起来。
结构体,就是为了解决封装问题而诞生的语法。
定义结构体类型
struct tagStudent
{
char szname[8];
int nGender;
int nStuId;
};
使用结构体定义新的结构体变量
纯正c89语法:
struct tagstudent stu1;
之后的C++以及较新的C编译器,都允许省略struct来定义结构体变量
tagstudent stu1;
结构体成员的引用与赋值
从结构体类型的定义就可以看出,结构体中封装了多种变量。
我们可以通过"."运算符,去引用到结构体内部的变量(结构体成员)。
struct tagStudent
{
char szName[8];
int nGender;
int nStuId;
};
int main(int argc, char* argv[])
{
struct tagStudent stu1;
strcpy(stu1.szName, "刘x");
stu1.nGender = 1;
stu1.nStuId = 20172519;
return 0;
}
结构体指针及其引用
如果需要将结构体作为参数传递
强烈不推荐使用值传递的方法传递结构体。
而强烈推荐使用指针传递结构体。
因为以值传递的方式传递结构体,结构体会整体被拷贝到栈帧并随函数返回释放。这常常意味着较大的消耗资源。
甚至可能造成栈帧的崩溃
struct tagStudent
{
char szName[2000000];
int nGender;
int nStuId;
};
void ShowStu(tagStudent stu)
{
printf("姓名:%s, 性别:%d, 学号:%d",
stu.szName,
stu.nGender,
stu.nStuId);
}
struct tagStudent g_stu1;
int main(int argc, char* argv[])
{
strcpy(g_stu1.szName, "刘x");
g_stu1.nGender = 1;
g_stu1.nStuId = 20172519;
ShowStu(g_stu1);
return 0;
}
综上所述,我们推荐使用地址的方式(结构体指针)传递结构体。
- 结构体指针的定义:
struct tagStudent
{
char szName[200000];
int nGender;
int nStuId;
};
void ShowStu(tagStudent* pstu)
{
printf("姓名:%s, 性别:%d, 学号:%d",
pstu->szName,
pstu->nGender,
pstu->nStuId);
pstu->nGender = 0;
}
struct tagStudent g_stu1;
int main(int argc, char* argv[])
{
strcpy(g_stu1.szName, "XX");
g_stu1.nGender = 1;
g_stu1.nStuId = 1233456;
ShowStu(&g_stu1);
return 0;
}
C语言中typedef,条件编译,结构体的说明的更多相关文章
- C语言中,隐藏结构体的细节
我们都知道,在C语言中,结构体中的字段都是可以访问的.或者说,在C++ 中,类和结构体的主要区别就是类中成员变量默认为private,而结构体中默认为public.结构体的这一个特性,导致结构体中封装 ...
- C语言中FILE是结构体,文件类型的指针
c语言文件类型指针 我们在定义文件类型指针变量后,称作该指针指向该文件,但本质上,它不是指向一个存储文件信息的结构型变量么?那么我们在用各个函数对所谓的“文件指针”进行操作时,本质上是不是函数通过获取 ...
- c语言中,在结构体中如何将void *转存为具体需要的数据类型
1. 只需要将该void *类型成员,强制转换为具体的数据类型指针即可.需要注意的是,该强制转换是有风险的,转换时,必须确定void*指向内存实际数据为目标结构体格式,否则可能会出现内存越界访问,从而 ...
- C语言中typedef用法
C语言中typedef用法 1. 基本解释 typedef为C语言的关键字,作用是为一种数据类型定义一个新名字.这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等) ...
- typedef 定义结构体数组或其他数组
typedef 定义结构体数组或其他数组 C\C++语言下 typedef其实是对一个变量类型的名字进行重新定义,例如下面中: typedef struct { int num[10]; char n ...
- C语言中typedef的解释_2
typedef工具是一个高级数据特性.利用typedef可以为某一类型自定义一个新的名称.这样可以提高程序的可读性,可移植性,向用户表明特定用途. typedef没有创建任何新的类型,它只是为某个已存 ...
- typedef struct 结构体
typedef struct _TTTT_ { int i; }TT_TT; 定义变量如下: struct _TTTT_ NewTT;方法1 TT_TT NewTT;方法2 是声明和定义 ...
- C语言中typedef
一.基本概念剖析 ])(int, char*); //#1 ]) (void (*)()); //#2 ]; //#3 .C语言中函数声明和数组声明.函数声明一般是这样: int fun(int, d ...
- C语言中typedef的解释_1
typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异. 它本身是一种存储类的关键字,与auto.extern.mutable.static.register等关键字不能 ...
随机推荐
- 【leetcode】1278. Palindrome Partitioning III
题目如下: You are given a string s containing lowercase letters and an integer k. You need to : First, c ...
- selenium 与appium的关系
selenium是web端的自动化,appium是app端的自动化,它继承了webdriver(也就是selenium 2) 关系如下:
- codevs 2804 最大最小数质因数 x
题目描述 Description 先输入n,n<=20;再依次输入n个不同的数,每个数<=1000000;找出最大数和最小数,并输出最大最小数的质 ...
- 记一次protobuf和hbase自带protobuf版本冲突的解决
使用protobuf生产模板代码,使用的版本是: <dependency> <groupId>com.google.protobuf</groupId> <a ...
- hadoop+zookeeper+hbase分布式安装
前期服务器配置 修改/etc/hosts文件,添加以下信息(如果正常IP) 119.23.163.113 master 120.79.116.198 slave1 120.79.116.23 slav ...
- Centos-Redhat下远程桌面的方法 & Redhat改Centos源
折腾了好几天才搞定,Redhat下远程桌面的方法,首先保证本身已经装了桌面,并且可以ssh访问 由于系统中自带python2环境,装了anaconda以及它带的python3环境,这个必须存在(前提) ...
- 关于Array.reduce的理解与拓展
2018年1月6日 首先我要感谢我的同事徒步上山看日出在我第一份实习的时候对我的指导,现在我也开始跟他一样开始养成写博客的习惯 现在开始讨论我遇到的第一个问题,这是我在看javascript高级程序设 ...
- TCP被动打开 之 第三次握手-接收ACK
假定客户端主动打开,发送syn包到服务器,服务器创建连接请求控制块加入到队列,进入TCP_NEW_SYN_RECV 状态,发送syn+ack给客户端,并启动定时器,等待客户端回复最后一个握手ack: ...
- python3笔记二十:时间操作time
一:学习内容 time时间戳 time元组 time字符串 time时间转换图解 二:time 需要引入:import time 1.概念 UTC(世界协调时间):格林尼治天文时间,世界标准时间,在中 ...
- CI集成Smarty的实现方式
给新伙伴的忠告:不要去想着有多复杂,看一遍绝对就会弄了! 这样集成的目的是什么? 因为我使用过CI和smarty,所以我就按自己的理解讲一下:CI框架在控制器.models方面做的很好,但在多变的视图 ...