初识C语言(下篇)

如果这世界上真有奇迹,那只是努力的另一个名字。

大家好,这里是anduin.今天将给大家带来初识C语言的最后一部分,和之前一样点到为止,适当补充,今天的内容是#define 定义常量和宏、指针和结构体三部分内容,事不宜迟,我们这就开始。

目录

12. #define 定义常量和宏

定义标识符常量

 定义宏

13. 指针

内存

指针的分析

&操作符

指针和指针变量

*操作符与指针的关系

指针变量的大小

计算及其结果

解释

14. 结构体

概念

使用方法

第一种访问方式

 第二种访问方法

结构体数据输入方法

结语


12. #define 定义常量和宏

定义标识符常量

我们在之前常量那一部分就认识到#define可以定义常量,凡是用到常量的地方都可以用define定义的宏来替换。

#include<stdio.h>
//#define 定义标识符常量
#define MAX 1000//定义整形
#define STR "abcdef"//定义字符串
int main()
{
     printf("%dn",MAX);
     int a = MAX;
     int arr[MAX] = {0}; 
     printf("%dn",a);
     printf("%sn",STR); 
     return 0; 
}

分析:如代码所示,#define用来定义常量MAX,当对变量a进行赋值时,可以打印出1000,同样的对于数组arr的数组元素为MAX,也就是1000个,由于MAX为常量,所对应arr中的元素也就是1000个(如下图),对于字符串常量STR也是相同的原理。

 定义宏

如果我们平时实现两个数相加的程序,我们可以直接在main函数中实现,或者是封装一个函数,代码如下:

#include<stdio.h>
//函数实现
int Add(int x,int y)
{
    return x+y;
}
int main()
{
    int a = 10;
    int b = 20;
    int c = Add(a,b);
    printf("%dn",c);
}

 那么除了函数,可不可以用其他方法实现呢?有,就是我们所说的宏:

#include<stdio.h>
#define ADD(x,y) ((x)+(y))
int main()
{
    int a = 10;
    int b = 20;
    int c = ADD(a,b);
    printf("%dn",c);
    return 0;
}

  对比:我们可以看到对于这两种实现方式,他们俩是很像的,就如函数有函数体,宏也有宏体(((x)+(y))),虽然他们比较相似,但是他们也有着许多差别!!!(仅目前所学知识归纳,不全)

宏和函数的差别:

  • 实现时有差异,定义时有差异(实现:函数实现时是调用函数,而宏是预处理指令;定义:函数有返回值类型,函数返回值,函数体,函数名,形参等等而宏则十分简单)
  • 宏的参数没有类型,函数的参数类型(代码可以看到形参的类型,和宏的无类型)
  • 函数体宏体
  • 函数传实际参数,宏直接起替换作用(如代码中就是a,b就是直接替换宏中的x,y)

13. 指针

内存

众所周知,内存是电脑上特别重要的存储器,它是外存与CPU进行沟通的桥梁,计算机所有程序的运行都在内存中进行,当计算机没有出现寄存器和高速缓存区之前,计算机都是要从内存中调取数据到CPU中进行运算,内存的重要性可见一斑。

所以内存的使用效率也是要被有效划分的,我们把内存单元划分成一个个小小的内存单位,每个内存单位单位大小是一个字节,如下图所示:

但是访问内存单元又成了一个问题,我们在查找货物时需要给货物编号,在拜访别人家时需要借助地址,在C语言中也一样,为了能有有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号就被称为该内存单元的地址。但是地址在平时说起来比较拗口,所以我们把给他起了个好听的名字 - 指针。

指针的分析

&操作符

#include<stdio.h>
int main()
{
    int a = 10;
    int *pa = &a;//指针变量pa
}

 分析:我们知道,int类型a变量的大小是4个字节,我们启动调试,点击内存窗口&a,并将其内存显示一列,观察它的地址发现,因为a占用4个字节,每个字节都有一个地址,在内存中它们地址是逐次增大的,与之对应的a的地址与a中第一个字节所存放的地址是相同的,也就是说&a取出的是第一个字节的地址

指针和指针变量

地址取出来了,那么用什么保存呢?指针变量。

 分析:pa是创建出来存放地址的,这个变量就是指针变量,他们通常写成int *p,char *p等形式,而int *整体是一个类型,叫做整形指针类型*说明pa是指针变量,而int说明pa指向的对象是int类型我们口头语上说的指针一般指的是指针变量!)

*操作符与指针的关系

那么问题来了,生活中我们拿到一户人家的地址时,可以找到他家并去拜访他,那么指针是否也可以起到这种效果呢?

当然可以!这时候就要用到我们上次没讲的*解引用操作符

#include<stdio.h>
int main()
{
    int a = 10;
    int *pa = &a;
    *pa = 20;
    printf("%dn",a);
    //*&a;//也就是找到地址在拿数据,相当于就是a
}

分析:*操作符其实就是起到一个间接访问的作用,*pa的意思其实就是通过pa中存放的地址,找到pa指向的空间,拿到空间里的数据,也就相当于a = 20,使用*操作符也就起到了"拜访"数据的作用。

与&操作符结合理解就是&操作符是你找到地址*则是找到数据,一个是来,一个是去。

Tips:可能大家有些疑惑,解引用操作符会不会和乘号混淆?我可以明确地告诉你:不会!

因为解引用操作符*是单目操作符的缘故,并不会和双目操作符乘*所混淆的。

指针变量的大小

计算及其结果

那么指针变量的大小又是多少呢?让我们用sizeof来计算一下。

由于pc是指针变量,而它是char*字符指针类型的,所以用计算大小时用pc和用它的类型本质上是一样的,通过类型来计算大小还是计算它的变量大小是一样的。

#include<stdio.h>
int main()
{
    char ch = 'a';
    char* pc = &ch;
    printf("%dn", sizeof(char *));
    printf("%dn", sizeof(short *));
    printf("%dn", sizeof(int *));
    printf("%dn", sizeof(long *));
    printf("%dn", sizeof(long long *));
    printf("%dn", sizeof(float *));
    printf("%dn", sizeof(double *));

    return 0;
}

解释

指针变量是用来存放地址的,其大小取决于一个地址需要多大的空间,我们的电脑是硬件,在电脑中有一层地址线(32/64位)。

电线上通电后,转化为1/0组成的数字信号(如图),这些地址组合有2的32次方个,而在这些地址也就是32位的由01组成的地址序列,每个1/0就占一个bit位,每8个bit位构成一个字节,所以地址存放起来的大小总共就是4个字节,而指针变量就是存放地址的,那么它的大小也就是4个字节!!!当然在64位平台上地址序列就是64个1/0组成的二进制序列,存起来就需要八个字节。


14. 结构体

概念

在C语言中存在着许多类型,但是他们所表示的往往是部分数据,并不能通过一个类型来描述生活中的一个事物,例如一本书:他们要有书名+定价+作者等组成,这些复杂对象不能简单地使用单一类型进行描述的,在C语言中可以用结构体来描述这种复杂对象

使用方法

第一种访问方式

#include<stdio.h>
//结构体类型
struct Book
{
     char bookname[30];
     float price;
     char writer[20];  
};
int main()
{
     struct Book s = {"chushiclanguage",1.01,"anduin"};//创建变量并初始化
     //结构体变量.结构体成员
     printf("%s %f %sn",s.bookname,s.price,s.writer);   
}

对创建结构体类型及其变量初始化的分析:

如代码,首先创建结构体类型Book,在其内部创建bookname,price,writer等类型选项,再在main函数中定义结构体变量s,通过大括号的方式对其内容进行初始化。

.访问操作符就是通过结构体变量.结构体成员的形式,对结构体内容进行访问,运行代码输出结果为:

 第二种访问方法

#include<stdio.h>
struct Book
{
    char bookname[30];
    float price;
    char writer[20];
};
void Print(struct Book* ps)
{
    printf("%s %.2f %sn", ps->bookname, ps->price, ps->writer);
    //结构体指针->结构体成员
    //printf("%s %.2f %sn", (*ps).bookname, (*ps).price, (*ps).writer);
}
int main()
{
    struct Book s = { "chushiclanguage",1.01,"anduin" };//创建变量并初始化
    Print(&s);
}

分析:从上面那段代码可以知道.操作符可以访问,那么可不可以用另外一种方式来访问呢?

1.(.)指针方式访问

如代码所示,定义Print函数,参数为s的地址,在函数中我们仍然是通过.操作符的方式来进行访问,传参传的是地址,有结构体指针ps进行保存,再通过*符号来找到结构体变量s,并通过.操作符进行访问。

2.->方式访问

由于参数是结构体指针,便可以通过->来进行访问,格式为结构体指针->结构体成员,这样也可以进行访问。

结构体数据输入方法

我们平常想要输入数据时,经常要用到scanf函数,那么对于结构体我们如何输入数据呢?

#include<stdio.h>
struct Book
{
    char bookname[30];
    float price;
    char writer[20];
};
int main()
{
    struct Book s;
    scanf("%s %f %s",s.bookname,&(s.price),s.writer);
    printf("%s %.2f %sn",s.bookname,s.price,s.writer);
}

Tips:这里的bookname,writer是数组名,数组名本来就是地址,所以不需要&,而price是浮点型,那就需要取地址了!!!

结语

好了,以上就是初识C语言的全部内容,对于C语言中的知识点,我们也都有了一个初步的了解,对于其深度理解,我会在之后的博文中一一剖析。

如果大家觉得anduin写的还可以的话,请点赞+收藏哦!你们的肯定就是对我最大的鼓励!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>