【初识C语言】一篇文章带你快速入手C语言(适合新手)

本文介绍了C语言的基本概念,包括C语言的起源、第一个程序、数据类型如char、int、float等的使用,以及变量的声明、定义、作用域和生命周期。文章还讨论了常量、字符串、转义字符、注释、选择语句if、循环语句while、函数、数组、操作符和关键字如typedef、static的用法。特别强调了指针的概念,包括指针变量的大小和使用方法。

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在回炉重造C语言(2023暑假)
✈️专栏:【C语言航路】
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

前言

本篇文章是基本了解C语言的基础知识,对C语言有一个大概的认识,目前不做详解。篇幅很长,建议大家配合目录食用~

一、什么是C语言

  • C语言是一门计算机语言,是人和计算机交流的语言,它广泛用于底层开发(Linux就是用C语言写的)。当然,计算机语言还包括C++JavaPythonGo等等。
  • 其常用的编辑器有Clang(苹果公司编写)GCC(Linux环境)MSVC(visual studio - 集成开发环境IDE)等(本人用的是VS2019)

二、第一个C语言程序

每学习一门新的语言,当然是要打印hello world!

// 第一个C语言代码
#include <stdio.h>
int main()
{
	printf("hello world!");

	return 0;
}

【输出结果】

在这里插入图片描述

  1. C语言代码中,不管是括号、分号、大括号等符号必须是 英文模式 下敲出来的。
  2. main主函数,在C语言必须要有主函数
  3. printfc语言标准函数库提供的一个格式化输出函数。因此使用printf函数就要包含头文件#include <stdio.h>scanf - 输入函数,也要包含此头文件)。 其中stdio.h ---standard input output header – 标准输入输出头文件
  4. '\n' – 换行(相当于回车)

2.1 什么是main函数

  1. 主函数是程序的入口
  2. C语言必须要有主函数
  3. 但需要注意的是:一个工程(项目)可以有多个源文件(.c后缀文件),main只能有一个

验证第3点main函数只有一个:
例如在一个项目中再创建一个源文件(Test2.c),内容如下:

在这里插入图片描述

三、数据类型

我们为什么要写代码?因为代码能够解决未来生活中的问题,C语言必须有能力描述我们的生活。假如设计在线商城,我们得用计算机的语言把它描述出来,比如商品陈列、详情、定价、编号等,所以C语言就引入了数据类型

3.1 C语言中的数据类型

char     //字符数据类型
short    //短整型
int      //整型
long     //长整型
long long   //更长的整型(C99引入)
float    //单精度浮点数
double  //双精度浮点数

现在我们利用以上类型来打印不同的数据到屏幕上:

在这里插入图片描述

  • %d是打印十进制的整数,所以第20行代码的意思是:把100以十进制的方式打印在屏幕上。
  • 当然还有一些常见的输出格式如下:
    在这里插入图片描述

3.2 数据类型的大小

在这里插入图片描述

【程序结果】

// 以下单位是字节
char类型大小:1
short类型大小:2
int类型大小:4
long类型大小:4
long long类型大小:8
float类型大小:4
double类型大小:8
  1. 小伙伴们有没有发现,为什么长整型(long)不比整型(int)大呢?

原因是:C语言标准规定:sizeof(long) >= sizeof(int)

  1. sizeof是一个操作符,是计算变量的大小。(单位:字节)

因此这里就要说说计算机常见的单位:

bit   比特位   1 byte = 8 bit
byte   字节
KB            1KB = 1024 byte
MB            1MB = 1024 KB
GB            1GB = 1024 MB
TB            1TB = 1024 GB
PB            1PB = 1024 TB

记住int类型的数据范围:[-21亿+,21亿+]

3.3 类型的使用

有了类型就是为了创建变量

在这里插入图片描述

在数据后加f后,就是float类型了

在这里插入图片描述

这里提一个好的编程习惯:在创建变量的同时给一个初始值。

四、变量的命名

  1. 只能由字母、数字和下划线(_)组成。
  2. 不能以数字开头
  3. 变量名是区分大小写
  4. 变量名不能使用关键字。

五、变量的分类

变量分为局部变量和全局变量

  1. 局部变量:定义在{}里的变量
  2. 全局变量:定义在{}外的变量

在这里插入图片描述

5.1 全局变量和局部变量的变量名冲突的情况

在这里插入图片描述

通过以上代码我们发现,当局部变量和全局变量的变量名冲突时,局部优先。但是建议大家在平时尽量不要冲突。

5.2 变量的使用

哪里要使用变量,就在哪里创建

例如:编写代码,计算两个数的和

在这里插入图片描述

scanf是一个库函数,可以从键盘接收数据,要引用头文件#include <stdio.h>,同时 需要在变量前加上&(取地址)

5.3 scanf函数报错问题

注意:如果没有第一行代码,若使用scanf时会报错。

在这里插入图片描述

原因是:scanf是C语言提供的,当然也可以使用scanf_s(visual studio提供的),但是建议大家使用scanf函数。最后如何解决请看这篇文章:【点我跳转】

5.4 变量的声明和定义

  1. 变量的定义
// 当创建变量并给它赋值叫做定义
int a = 1; 
int main()
{
	printf("%d\n", a);

	return 0;
}
  1. 变量的声明
int a; //变量的声明
int main()
{
	printf("%d\n", a);

	return 0;
}
int a = 1;

如果变量的使用在变量的定义之前,使用前需要加上声明。原因是:代码在编译阶段是从上到下开始扫描的,当来到printf时,如果没有声明,编译器就不知道有a这个变量,所以会导致报错。

六、变量的作用域和生命周期

6.1 作用域

什么是作用域呢?直白来说,哪里可以使用变量,哪里就是它的作用域。

  1. 首先先来讨论局部变量的作用域
#include <stdio.h>

int main()
{
	int a = 100;
	printf("%d\n", a);

	return 0;
}

在上述代码中,变量a的作用域就是代码块{}的内部

总的来说,局部变量的作用域:就是变量所在的局部范围。

  1. 接下来看看全局变量的作用域

在这里插入图片描述

代码解析:因为main是程序的入口,代码先从第119行开始执行,接下来开始打印main:211在屏幕上,接着又调用test函数,最后打印test:211在屏幕上。(这里使用了函数部分知识,先凑合看,后面会讲)

有没有发现,全局变量既可以在主函数中使用,也能在其他函数中使用,这意味着在任意地方都能使用。由此可以得出结果,全局变量的作用域是整个工程

6.2 补充:extern

全局变量还能怎么用呢?假如我把变量a放在同一工程不同源文件Test1.c),程序是否能运行起来呢?

在这里插入图片描述

程序报错了,让我们应该如何解决呢?声明外部符号extern

在这里插入图片描述

6.3 变量的生命周期

变量的生命周期是指:变量的创建到变量的销毁之间的一个时间段

  1. 局部范围的生命周期

在这里插入图片描述
以上代码是编译不过的,这是为什么呢?原因是:变量a是个局部变量,它的作用域是中间的代码块。进入作用域生命周期开始,出作用域生命周期结束,所以变量a出了中间部分的代码块作用域,它就被销毁(还给了操作系统),所以当打印第二个a时,程序就报错了。这就是局部变量的生命周期。

  1. 全局变量的作用域就是整个程序的生命周期,直到整个程序结束,变量才会被销毁

七、常量

7.1 常量的分类

  • 字面常量
  • const修饰的常变量
  • #define定义的标识符常量
  • 枚举常量

【举例】

#include <stdio.h>

// 3. #define定义的标识符常量(也能放在main函数里)
#define M 100; //定义了一个M,它的值是100

// 4. 枚举 --- 一一列举
//假设列举三原色
enum Color
{
	// 编译器默认red,green,blue分别是0,1,2(常量)
	red, 
	green,
	blue
};

int main()
{
	// 1. 字面常量
	3;
	100;
	'a';
	"abcdef";
	
	// 2. const修饰的常变量
	const int N = 100010;
	N = 1; // 这是错误的,const修饰的变量具有常属性,不可修改
	// const从语法层面上限制了变量不能被修改,但其本质上还是变量。

	return 0;
}

7.2 常变量const的补充

常变量,是常量为什么会有一个“变“呢?让我们再举一个例子,加深对const的理解

我们可以使用数组来验证,因为数组[]操作符里必须是常量

在这里插入图片描述

显然报错了。这说明编辑器依然认为**a的属性是变量**。

总结:const从语法层面上限制了变量不能被修改,但其本质上还是变量。

八、字符串和转义字符

8.1 字符串

“hello world!\n”

这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串

注意:字符串的结束标志是'\0'的转义字符。在计算字符串长度时,'\0'是结束标志,不是字符串内容。

一般存多个字符或者字符串都是用数组存储的

#include <stdio.h>
int main()
{
	char ch1[] = { 'a','b','c' };
	char ch2[] = "abcdef";

	return 0;
}

8.2 计算字符和字符串的长度

C语言提供了一个库函数:strlen,可以计算字符串的长度。但使用strlen需要包含头文件:#include <string.h>

在这里插入图片描述

这里注意一下:

  1. 其实ch1字符串长度其实不止15,它是个随机值,因为它没有结束字符'\0'
  2. 字符串ch2在计算长度时没有算上末尾的'\0'它统计的是'\0'之前字符的个数

8.3 转义字符

顾名思义就说转变原来的意义

在这里插入图片描述

【例如】

在这里插入图片描述

【经典笔试题】

以下代码输出的结果是多少?

#include <stdio.h>

int main()
{
	printf("%d\n", strlen("c:\test\628\test.c"));

	return 0;
}

【答案】

在这里插入图片描述

解析:从左往右,\t\62\t是转移字符。分别都只算一个字符。

九、注释

当代码中有些代码比较难懂,可以添加文字注释。当然也可以注释掉不需要的代码

注释风格:

// 这是一个注释,只能注释一行

/*
这是一个多行注释
这是一个多行注释
这是一个多行注释
注意:这种注释风格不能嵌套
*/

十、选择语句if

//以下是伪代码

if(判断条件)
{
	// 逻辑实现
}
else if(条件判断)
{
	// 逻辑实现
}
else
{
	// 逻辑选择
}

【例子】

编写代码,输入一个人的智商值,如果智商大于等于140,输出“Genius”。否则输出“fool”

#include <stdio.h>
int main()
{
	int score = 0;
	scanf("%d", &score);
	if (score >= 140)
	{
		printf("Genius");
	}
	else
	{
		printf("fool");
	}
	return 0;
}

十一、循环语句while

意思是循环做,直到满足条件停止。当然还有fordo while,这些循环会在后面讲到

【例子】

输出1~10

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		printf("%d ", i);
		i = i + 1;
	}

	return 0;
}

十二、函数

在数学中,我们经常把函数定义成:f(x);在C语言中,把函数定义为:函数名(类型 x,...),其特点是:简化代码,代码重复使用。

在变量的使用中,写过有关加法的代码,那么能否把加法的过程封装成一个函数呢?

#include <stdint.h>

int add(int x, int y)
{
	// 1. 第一种写法
	//return x + y;

	// 2. 第二种写法
	int res = x + y;
	return res;
}

int  main() 
{
	int num1 = 0;
	int num2 = 0;
	scanf("%d%d", &num1, &num2);
	
	// 封装一个add函数
	int ans = add(num1, num2);

	printf("num1 + num2 = %d\n", ans);
	return 0;
}

建立一个add函数,把num1传到int x,再把num2传到int y中,经过函数内部的逻辑运算,最后把res的结果作为返回值给到ans,因为res的结果一定是整型,所以add函数的返回值是int。但注意,函数名要根据实际的意义来命名

我们还能这样理解:可以把add看作一个工厂,把num1num2相当材料输入到int xint y中,工厂里再进行加工(x+y),最后通过return返回到ans中。

十三、数组

13.1 数组的定义

如果我们要存1-10的数字,怎么储存?难道是一直定义变量直到10吗?这样会不会显得麻烦?所以在C语言中给了数组的定义:一组相同类型元素的集合

int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

// 定义整型数组,最多只能存放10个整型元素
// 注意:
// 在C99之前,[]内不能使用变量
// 在C99中引入变长数组的概念,这时候
// 这时候数组的大小是可以使用变量的,但数组不能初始化!!!

假如数组不放满指定数组元素个数是否可以呢?其内容又是什么?

#include <stdint.h>
int main()
{
	int arr1[10] = { 0, 1, 2,3,4,5,6,7,8,9 };
	int arr2[10] = { 0,1,2,3,4 };

	return 0;
}

可以在监视中看看效果,首先在编译器中先按F10,然后在调试中找到窗口,最后在窗口中找到监视:

在这里插入图片描述

随后在名称中输入arr1arr2,就能看到他们的内容:

在这里插入图片描述

有没有发现未放满10个元素的整型数组arr2后面补了5个0,这个叫:不完全初始化,剩余的默认初始化为0

如果我再创建字符数组arr3,数组中也不放满对应元素,结果又会是如何呢?

在这里插入图片描述

结果很明显了,对于字符数组,它的剩余默认初始化为'\0'

13.2 数组的下标及其使用

C语言规定:数组的每个元素都有一个下标,且下标都是从0开始的。

假如打印数组中的3,就可以用到[]这个操作符:

在这里插入图片描述

对于数组4个元素,从语法上规定:第一个元素0的下标就是0,第二个元素1的下标是1,后面以此类推…

十四、操作符

14.1 算术操作符:+ 、-、*、/

  1. 如果算术操作符至少有一个运算对象是浮点型,其表达式的类型为浮点型。

在这里插入图片描述

  1. 取模(取余)操作符(%)的两个运算对象必须都是整数,结果的正负号由被除数决定。

在这里插入图片描述

  1. 注意不要把*和/写成数学中的×和÷。

14.2 位移操作符: >> <<

如果想深入了解建议看看这篇博客:点击跳转

14.3 位操作符:&、^、|

如果想深入了解建议看看这篇博客:点击跳转

14.4 赋值操作符:=、+=、-=-、*=、%=、/=、&=、^=、|=、>>=、<<=

如果想深入了解建议看看这篇博客:点击跳转

14.5 单目操作符

在这里插入图片描述

14.5.1 !
!   逻辑反操作

在C语言中,非零表示真,零表示假,操作符!即可以把真变成假,假变成真

在这里插入图片描述

flag初始值为0,其本质为假;在if条件判断加了!,假变成了真,所以在屏幕上打印了hello world!

14.5.2 &

负值和正值操作符比较简单,这里就不过多赘述了

感兴趣请参考这篇文章:点击跳转

14.5.3 sizeof

sizeofstrlen的区别

  • sizeof是操作符,是计算变量所占内存空间的大小,单位是字节。
  • strlen是库函数,是计算字符串的长度,统计的是字符串中‘\0’之前出现的字符个数

感兴趣请参考这篇文章:点击跳转

14.5.4 ~

感兴趣请参考这篇文章: 点击跳转

14.5.5 - -和++

感兴趣请参考这篇文章: 点击跳转

14.5.6 *

感兴趣请参考这篇文章:点击跳转

14.5.7 (类型)

在这里插入图片描述

3.14原先是浮点数类型,但在3.14前加上(int)就变成了整型(只取整数部分)。

14.6 关系操作符

>
>=
<
<=
!=  用于测试“不相等”
==  用于测试“相等”

关系操作符比较简单,这里要重点区分“=”和“==”。在C语言中,“=”是赋值操作符;两个等于才表示相等。

14.7 逻辑操作符

&&  逻辑与:两真为真,一假全假
||  逻辑或:一真全真,两假全假

14.8 条件操作符

在这里插入图片描述

  • expl的值为真,则结果就是exp2的值。
  • exp1的值为假,则结果就是exp3的值 。

14.9 逗号表达式

exp1,exp2,exp3...

从左向右依次执行,最后的答案是最右边的表达式

14.10 下标引用、函数调用和结构成员

请参考这篇博客:点击跳转

十五、关键字

注意:以下关键字不能当变量名来使用!

auto break case char const continue default do double else enum extern
float for goto if int long register return short signed sizeof static struct
switch typedef union unsigned void volatile while

注意:sizeof既是关键字,也是操作符。

另外,操作符是C语言本身预先设定好的,用户是不能创造关键字的。

最后,我对这些关键字做了分类:

在这里插入图片描述

15.1 关键字typedef

typedef的作用是:类型重命名。

我们应该怎么用呢? 比如我们要定义一个无符号的整型,我们可以这么写:unsigned int num = 0,大家有没有发现这个名字很长。因此我们可以用typedef来进行类型重命名:

#include <stdio.h>
typedef unsigned int ui;
int main()
{
	ui num = 0;
	return 0;
}

我们可以把unsigned int(类型)重命名为ui(开头首字母缩写),ui就是unsigned int的别名,这样写把代码复杂类型简单化。

15.2 关键字static

在C语言中:
static是用来修饰变量和函数的
①修饰局部变量 - 称为静态局部变量
②修饰全局变量 - 称为静态全局变量
③修饰函数 - 称为静态函数

15.2.1 修饰局部变量

以下代码会输出什么呢?

#include <stdio.h>

void test()
{
	int a = 0;
	a++;
	printf("%d\n", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	return 0;
}

【程序结果】

在这里插入图片描述

为什么是10个1呢?原因是:a是个局部变量,进入作用域生命周期开始,出作用域生命周期结束。当每次调用test函数,创建局部变量a,出了作用域,变量a被销毁(还给了操作系统),因此每次调用test函数都只会打印1。

那如果我在变量a前加static结果还会是一样吗?那我们来看一下。

#include <stdio.h>

void test()
{
	static int a = 0;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	printf("\n");
	return 0;
}

【程序结果】

在这里插入图片描述

答案是1~10。为什么能输出这个结果呢?static修饰局部变量的作用是什么呢?

分析:第一个结果为1很好理解,可是第二个结果为2有没有发现第一次的结果并没有销毁。以此类推…

那么static的本质是什么呢?我们来看看下面这幅图:

在这里插入图片描述

栈区是进入作用域创建,出了作用域就会释放,放在静态区的数据创建后,直到程序结束才会释放。被static修饰都是在静态区里。 堆区目前不做了解。

总结:普通的局部变量是放在栈区上的,这种局部变量进入作用域创建,出了作用域释放,但是局部变量被static修饰后,这种局部变量就放在了静态区,放在静态区的变量,创建好后,直到程序结束才释放。

本质:static的修饰改变了局部变量的存储位置,因为存储位置的差异,使得执行效果不一样。

注意:被static修饰是不影响作用域的!!!但是生命周期变长了。

15.2.2 修饰全局变量

假设我在另一个源文件创建一个全局变量:

在这里插入图片描述

若全局变量astatic修饰,结果又会是如何呢?

在这里插入图片描述

程序发生报错了(无法解析的外部符号),所以为什么会出现这种现象呢?

原因是:全局变量本身是具有外部链接属性的,在一个文件中定义的变量,在另一个文件可以通过链接使用(extern),但是如果全局变量被static修饰,这个外部链接属性就变成了内部链接属性了,这个全局变量只能在自己所在的源文件内部使用。最终使得全局变量的作用域变小了。

15.2.3 修饰函数

其实static修饰函数和修饰全局变量非常类似。让我们看看下面的代码:

在这里插入图片描述

现在,我们在函数前加个static会怎么样呢?

在这里插入图片描述

结果是程序报错了(未定义外部符号)

原因是:函数本身是具有外部链接属性的,被static修饰后,外部链接属性就变成内部链接属性,使得这个函数只能在自己所在源文件内部使用,其他源文件无法使用。和全局变量其实是一个道理。限制了作用域。

十六、#define定义常量和宏

16.1 #define定义常量

这个在前面已经讲过了,来看看简单的代码样例吧

在这里插入图片描述

16.2 #define定义宏

比如:写一个函数求两个数的最大值,不难可以写出以下代码:

#include <stdio.h>

int Max(int x, int y)
{
	if (x >= y)
		return x;
	else
		return y;
	// 或者还可以用三目操作符
	//return x > y ? x : y;
}

int main()
{
	int a = 10;
	int b = 20;
	int c = Max(a, b);

	printf("最大值是:%d\n", c);

	return 0;
}

除此之外,我们还可以用宏来求出两个数之间的最大值

#include <stdio.h>
#define Max(x, y) (x > y ? x : y)

int main()
{
	int a = 10;
	int b = 20;
	int c = Max(a, b);

	printf("最大值是:%d\n", c);

	return 0;
}

解析一下代码:我这定义了一个宏叫Max后面跟着圆括号,xy参数,后面的三目运算符叫宏体 。其中a传给了的xb也传给了y,因此宏体其实就被替换成(a>b?a:b)。可能有人会想,这不就和函数差不多么?注意:宏一般是解决逻辑比较简单的问题,而函数通常用于解决复杂的问题。

如果我们要求两个数的和该怎么写呢?

#define  ADD(x,y)   ((x)+(y))

十七、指针

17.1 内存

想要理解什么是指针,必须先了解什么是内存。内存是电脑上的存储设备,一般都是4G/8G/16G等,程序运行的时候会加载到内存中,也会使用内存空间,例如任务管理器:

在这里插入图片描述

17.2 内存的管理与使用

我们将内存划分为一个个小格子,每一个格子是一个内存单元,大小为一个字节,对每一个内存单元进行编号,假设未来要找一个内存单元,就可以通过编号很快的找到,我们把这些编号叫做地址而地址在c语言中又叫做指针。

在这里插入图片描述

举一个例子,在下图中,假设定义一个变量 int a=10,一个int类型的变量,需要占4个字节的空间,而每个空间都有地址,&a取出的是哪一个的地址呢?其实取出的是第一个字节的地址(也就是较小的地址),也就是说,&a最终取出来的地址是0x0012ff40,当然,可以把这个地址存到一个变量中,int* pa=&a*表示pa是一个指针,int代表pa所指向的类型是int类型,这个pa也叫做指针变量(它是专门用来存放地址的)。

在这里插入图片描述

17.3 指针变量的大小

在这里插入图片描述

在这里插入图片描述

指针变量,就是用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
那么问题来了:一个内存单元到底是多大? — 刚刚讲过,就是一个字节
那它又是如何编址的呢?
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。 对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0)
那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001

11111111 11111111 11111111 11111111
这里就有2的32次方个地址。 一个地址管理一个内存单元,那么2的32次方个地址就能管理2的32次方个内存单元,也就是2的32次方个字节,那2的32次方个字节又是多大空间呢?
根据进制转化:
2^32Byte = 2^32÷1024KB÷1024MB÷1024GB = 4GB
同样的方法,64位机器,也可以计算出来。

这里我们就明白:

  • 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以 一个指针变量的大小就应该是4个字节。
  • 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

总结:

  • 指针变量是用来存放地址的,地址是唯一标示一个内存单元的。
  • 指针的大小在32位平台是4个字节,在64位平台是8个字节。

17.4 指针变量的使用

在这里插入图片描述

通过以上代码就验证了,指针变量p存放的就是a的地址。

接下来,我们可以使用*解引用操作符来对其使用

在这里插入图片描述

十八、自定义类型 – 结构体

18.1 定义

结构体使得C语言有能力描述复杂信息。

假如我们要描述一个学生(名字+性别+年龄)

// 定义一个学生的类型
struct Stu // 这个是类型
{
	char name[10]; // 姓名
	char sex[5]; // 性别
	int age; //年龄
	// 以上三个变量叫做结构体成员
};
// 分号不能省略

int main()
{
	// 类型(struct) + 变量(s) 
	struct Stu s = {"张三", "男", 20};
	
	return 0; 
}

代码解析:首先我们要先定义一个学生的类型,其中{}里的是结构体里的成员,注意最后要有分号 。接下来,在主函数中创建一个struct Stu的类型,其中s是变量。

那么问题来了,我们应该怎样打印出学生的信息呢?让我们接着往下看。

18.2 结构体的访问 — 点操作符

我们需要利用点.操作符来访问结构体里的成员

模板:结构体变量.成员名

// 定义一个学生的类型
struct Stu // 这个是类型
{
	char name[10]; // 姓名
	char sex[5]; // 性别
	int age; //年龄
	// 以上三个变量叫做结构体成员
};

int main()
{
	struct Stu s = { "张三", "男", 20 };
	printf("姓名:%s\n性别:%s\n年龄:%d\n", s.name, s.sex, s.age);

	return 0;
}

【程序结果】

在这里插入图片描述

当然还能使用指针解引用的方法

struct Stu // 这个是类型
{
	char name[10]; // 姓名
	char sex[5]; // 性别
	int age; //年龄
	// 以上三个变量叫做结构体成员
};

int main()
{
	struct Stu s = { "张三", "男", 20 };
	//printf("姓名:%s\n性别:%s\n年龄:%d\n", s.name, s.sex, s.age);

	struct Stu* p = &s;

	printf("姓名:%s\n性别:%s\n年龄:%d\n", (*p).name, (*p).sex, (*p).age);
	return 0;
}

【程序结果】

在这里插入图片描述

取出结构体变量s的地址存放到指针变量p中,再对其解引用,因此*p本质上就是s

18.3 结构体的访问 — ->箭头操作符

大家有没有发现解引用再去访问成员变量写的怪长怪累的,因此这里引用了箭头操作符:

// 定义一个学生的类型
struct Stu // 这个是类型
{
	char name[10]; // 姓名
	char sex[5]; // 性别
	int age; //年龄
	// 以上三个变量叫做结构体成员
};

int main()
{
	struct Stu s = { "张三", "男", 20 };
	//printf("姓名:%s\n性别:%s\n年龄:%d\n", s.name, s.sex, s.age);

	struct Stu* p = &s;

	//printf("姓名:%s\n性别:%s\n年龄:%d\n", (*p).name, (*p).sex, (*p).age);

	printf("姓名:%s\n性别:%s\n年龄:%d\n", p->name, p->sex, p->age);
	return 0;
}

【程序结果】

在这里插入图片描述

这里运用到了->箭头操作符,因为p指向了s,所以ps->name(sex/age)就是ps指向了sname(sex/age)

模板:结构体指针->成员变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值