目录

#define 定义常量和宏

#define 定义常量

#define 定义宏

指针

内存

指针变量的大小

结构体


#define 定义常量和宏

#define 定义常量

在变量和常量2,#define 定义的标识符常量中,就了解到#define可以定义常量。

定义一个符号叫做NUM,这里我们可以给它赋值,可以直接打印它的值,也可以创建一个数组,数组的大小用NUM(此时NUM是一个常量)。

#define NUM 100int main()
{printf("%d\n", NUM);int n = NUM;printf("%d\n", n);int arr[NUM] = { 0 };return 0;
}

运行证明,无论是直接打印,还是用NUM 创建一个数组都是没有问题的。

#define 定义宏

宏是有参数的

之前求两个数之和的时候,我们写了一个函数来求,这里我们写个宏来求两数之和。

#define ADD(x,y)  ((x)+(y))        定义一个宏叫做ADD,

ADD是宏名,(x,y)是宏的参数,参数是无类型的,((x)+(y)) 是宏体。

int Add(int x,int y) 这是函数的写法

{

return x + y;

}

#define ADD(x,y)  ((x)+(y))int main()
{int a = 10;int b = 20;int c = ADD(a, b);printf("%d\n", c);return 0;
}

运行得到结果30,成功完成两数加和的任务。

宏和函数非常相似,但宏是宏,函数是函数,这里还是见识一下就可以了。

指针

内存

在说指针之前,不得不先说一下内存.

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。

这个我们在register-寄存器中就提到过。

control+alt+delete打开任务管理器,就能看到内存的使用情况,每一个程序都占有内存,都在使用内存,那这些程序是怎么使用的呢?首先要加载到内存里面去。

当我们买电脑时说8G/16G,那这8G/16G不可能直接使用吧,所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节

这一个个小的内存单元就像生活中一个个房间一样,每个房间都有一个地址。

此比如说有五层楼,每层十个房间,共五十个房间,这时如果我说我在某一个房间里,你是不是要一层一层转,一间一间的去找,但要这时给这五十个房间编号了,101,102,103……,我说我在305时305是门牌号,同时更是一个地址。

生活中是这样,内存同样如此,只要给内存每一个小的内存单元编号,这样我去找这些内存空间的时候就非常的方便。

内存会划分为一个个小的内存单元(一个内存单元的大小:1byte)每个内存单元都有一个编号。这时一个32位的电脑,地址是通过地址线通电生成的,通电就会产生电信号,电信号就是1/0(正脉冲或者负脉冲);32位的电脑上有32根地址线,这时32跟地址线,每根地址线都有电信号,那32根地址线同时产生电信号地址的可能是:

00000000000000000000000000000000——>0

00000000000000000000000000000001——>1

……

1111111111111111111111111111111111111

所有产生电信号的组合是有2的32次方

2的32次方个地址序列就是2的32次方个字节的空间

那到底是多大呢?我们打开电脑的计算器调到程序员,点击BIN也就是二进制,输入100000000000000000000000000000000

然后点击DEC也就是十进制,得到的数字也就代表4,294,967,296byte

然后除以1024就能得到KB,再除以1024就能得到MB,再除以1024得到GB

最后我们算出,如果一个内存单位是一个字节,那么在32位的电脑上,管理的就是4GB的内存

当前我们都是64位的电脑,所以电脑内存是8G/16G/32G都是很常见的。

这里有人要问一个内存单位为什么不用一个bit比特位呢?

因为1bit不太合理,比如我创建一个变量c,char c; c就得1byte,1byte就是8bit

想象一下1bit一个内存单元,光一个c就占8bit,八个地址,char已经是C语言中最小的类型,那int呢,那不32个地址就没了,就跟生活中寄快递一样,我给你放到宿舍第五个平方米上,是不是没有必要,寄到房间是不是就可以了。

所以出于各种综合考虑,最后规定一个内存单位是1byte。

为什么要说内存呢,因为创建变量就是像内存申请空间

int a = 10;这个代码的含义就是向内存申请4个字节,储存10。

&a;取a的地址,&是取地址符号

按F10调试,并打开窗口监视,输入a,值是10,输入&a,就能查看a的地址

名称 类型
&a 0x0116fd60 {10} int *

同时还可以查看内存,也是点击调试——窗口——内存(注意:只有先调试才能看到)

因为不知道地址是什么,在地址窗口输入&a,回车,看到0x0116fd60,就是a的地址,然后把列调成4,一行就是4个字节——0a 00 00 00。

十进制是由0~9的数字组成的,八进制是由0~7的数字组成的,十六进制本来应该是0~15的数字组成,但后面的10~15是不是就会重复,所以这里用a~f分别对应10~15,所以10就用a表示

所以内存中的0a 00 00 00,存的就是10(至于为什么是倒着存,我们后面说,现在只要知道现在看内存倒着往回看就是你存的数字就可以了)

a的地址也可以打印出来,打印整型用%d,打印地址用%p,printf("%p\n", &a);

这时a的地址就是002CFF1C,因为每一次运行程序,a变量都会重新创建,所以地址变化了,和上一次不一样,因为二进制打印起来太长,看起来不够方便,所以用十六进制打印出来。

那地址能不能存起来?当然可以,那怎么写呢

int* p = &a; 把a的地址放到一个变量p里面,p的类型叫做int*

这里的p就叫做指针变量

为什么叫指针变量呢?

前面我们说到了内存单元,内存单元有编号,编号就是地址,地址也被称为指针

所以指针就是地址,就是内存单元的编号,而p是用来存这个地址,这个编号的,那也意味着用来存指针的,所以把用来存放指针(地址)的变量叫做指着变量

注意:变量的名字叫p,而不是*p,而p的类型是int*

依此类推,那这时创建char ch = 'w'

pc =&ch; 那这时pc的类型是什么,是char*

int* p = &a;        p里存放了a的地址,那p就有机会能找到a,那怎么找呢

*p = 20; *是解引用操作符,意思就是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象。

打印出了20,证明我们通过指针里的地址,然后解引用找到了a,并成功改掉了a的值。

这里就说了,在操作符中单目操作符漏掉的两个操作符——&*。

注意:辨析指针和指针变量,指针就是地址,指着变量是用来存放地址的,像我们口头语说的p是个指针,这个指针其实指的是一个指针变量,注意口头语的表达

指针变量的大小

int* p;char* p2;指针的创建有不同的类型,那不同类型的大小是什么样的呢

运行结果我们发现都是4,那为什么都是4呢?

因为不管是什么类型的指针,都是在创建指针变量,指针变量是用来存放地址的,指针变量的大小取决于一个地址存放的时候需要大多空间。32位机器上的地址:32bit位 - 4byte,所以指针变量的大小是4个字节,64位机器上的地址:64bit位 - 8byte,所以指针变量的大小是8个字节。

上面得到4,是在X86下运行的的结果(X86的意思就是32位平台),这时将其改成X64(就是64位平台),结果就成8了。

最后说一下创建指针变量的写法:char* pc;char *pc;

vs编译器喜欢char* pc;这样写,当你写完加上分号时,会自动跳成这样,这样写char*合在一起是一个类型,但连续定义多个指针时,int* p1, p2, p3; 你认为int*定义的p1, p2, p3都是指针吧,其实并不是,*只是给p1用了,p2, p3都只是拿到了int类型,你要想p1, p2, p3都是指针,就要int *p1, *p2, *p3;这样写,这时*跟着更能让你理解,p2,p3并不是指针。

这两种写法没有绝对的好,主要看个人习惯

结构体

前面我们说了数据类型(char,short,int,long,float,double),你用这些类型表示一个数完全没有问题,但现在要用这些类型表示一个人,人是一个复杂对象,要想表示一个人得有名字,年龄,地址,电话……,那再表示一本书,书得有书名,作者,出版社,定价,书号……

我们就发现这些复杂对象,不能简单用这种内置类型来描述了,这时C语言就给了自定义的能力,

自定义的类型中有一种叫结构体,而结构体的关键字叫做struct。

结构体是吧一些单一类型组合在一起的做法。

这时我们描述一个学生

先定义struct用{}把需要描述的变量括起来(注意{}后的不能掉),然后创建一个主函数

结构体访问它的对象用的是.操作符(结构体对象.成员名),这种用法的前提条件是得到一个结构体对象。

struct Stu
{//成员char name[20];int age;char sex[10];char tele[12];
};
int main()
{struct Stu s = {"zhangsan", 20, "nan", "15596668862"};//结构体对象.成员名printf("%s %d %s %s\n", s.name, s.age, s.sex, s.tele);return 0;
}

不想直接打印,取出s的地址,传给print函数。

void print(struct Stu* ps)
{printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).tele);}
int main()
{struct Stu s = {"zhangsan", 20, "nan", "15596668862"};print(&s);return 0;
}

觉得这样写太麻烦,改成

void print(struct Stu* ps)
{//结构体指针变量->成员名printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->tele);
}
int main()
{struct Stu s = {"zhangsan", 20, "nan", "15596668862"};print(&s);return 0;
}

这里又学了一个操作符->,用法:结构体指针变量->成员名(这种用法的前提条件是得到了一个指针)

 到这里,C语言基础语法概览就说完了,相信大家对C语言有哪些知识应该有一个轮廓了,只是这些知识没那么深入,没关系,后面再逐步抽丝剥茧,一点点去说。

#define 定义常量和宏,指针和结构体相关推荐

  1. C语言——关键字,define定义宏,指针,结构体

    常见关键字 auto break case char continue const default do double else enum extern float for goto if int l ...

  2. [C语言]static关键字--#define 定义常量和宏--初识指针--初识C语言(四)

    文章目录 前言 一,static关键字 二,#define 定义常量和宏 三,初识指针 总结 前言 本节主要记录初识C语言第四节内容. 内容包括:static关键字------#define 定义常量 ...

  3. C语言——初识C语言(define定义常量和宏,指针,结构体)

    1.1define定义常量和宏 define    定义符号(定义常量) //define 定义标识符常量 #define MAX 1000 define    定义宏(宏是有参数的,参数用来替换) ...

  4. define定义常量和宏 以及 寄存器关键字register

    在C语言中,# 指的是预处理指令.像#define就是在main函数之前预先进行定义. define定义常量 这里定义了常量NUM,我们知道数组固定下标值必须是常量,这也进一步说明了这里define定 ...

  5. C语言中的#define定义常量和宏

    C语言中的define是一个预处理指令. 1.define定义常量        格式为:#define  标识符  常量  , 注意:语句末尾没有":". 2.define定义宏 ...

  6. C语言基础1:初识C语言(转义、注释;数组、操作符、反码、补码、static、define、指针、结构体常变量;局部变量;作用域、生命周期)

    文章目录 C语言基础1:初识C语言 1.C语言简介 1.1什么是C语言 1.2C语言的发展 2.第一个C语言程序 2.1创建项目 2.2添加源文件 2.3写代码 3.数据类型 4.变量.常量 4.1定 ...

  7. 初识C语言#define、指针、结构体

    #define 定义常量和宏 define是一个预处理指令. 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为"宏".被定义为"宏"的标识符称为& ...

  8. 初识C语言系列-5-完结篇-#define,指针,结构体

    目录 1.前言 2.#define定义常量和宏 #define定义常量 #define定义的宏 3.指针 内存 指针变量的大小  4.结构体 1.前言 终于到了初识C语言的完结篇了,这里再次祝大家五一 ...

  9. 初识C语言(1)(2)(3)(4) C语言入门 保姆级教程 变量 常量 字符串 转义字符 操作符 关键字 字符串 指针 函数 结构体 数组 选择语句 循环语句

    一.如何写C语言代码 1.编译器 2.创建项目 3.创建源文件 4.写代码 5.编译+链接+运行 项目名字不要汉语,不要特殊字符,不要加空格,项目路径一般为你想要的路径 C语言中,一般创建.c源文件, ...

最新文章

  1. 怎样用matlab打开mw文,C# matlab混合编程 MWArray使用笔记
  2. Linux内核设计与实现读书笔记
  3. The Elements of C# Style -Naming
  4. tflearn anaconda 安装过程记录
  5. 好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题...
  6. 我在SAP这么多年使用过的IDE
  7. 使用string.Format需要注意的一个性能问题
  8. 【洛谷3768】简单的数学题【莫比乌斯反演】【杜教筛】【小学奥数】
  9. 编写一个脚本判断某个用户是否处在活动模式_大数据技术之Spark内核解析(二)Spark 部署模式...
  10. 读书笔记三——你的灯亮着吗
  11. LabView学习笔记——简易入门AND初级实战项目(计算器)
  12. 四级信息安全工程师基础知识
  13. python playsound 音量_Win32 PlaySound:如何控制音量?
  14. BIM+3DGIS的行业应用探讨
  15. 隔段时间网络就会变差,重启路由器恢复,这是为什么
  16. 棋牌游戏开发制做花费,您知多少呢?
  17. cesium加载entity图片缩放_Vue中使用vuecroper插件实现图片上传裁剪并传到SpringBoot后台接口...
  18. H5拍照、选择图片上传组件核心
  19. AS 编写 Xposed 插件需要修改的地方
  20. 华硕主板Z97-A无法识别intel M.2 NVME固态硬盘的解决方案

热门文章

  1. 数据库删除字段指定字符前面或者后面的字符串
  2. 12Cr2Mo1R(H)化学成分
  3. python使用cer证书进行https访问接口
  4. python 返回绝对值
  5. 第六章 Cesium学习入门之添加Geojson数据(dataSource)
  6. mysql如何加索引的时候不锁表
  7. ads1258_ADS1258 pdf,ADS1258中文资料,ADS1258应用电路-华秋商城
  8. ~ 按位取反运算解析
  9. 科学论文写作工具TEX/LaTEX/CTEX
  10. 数据库设计:需求分析