🦔🦔一场遇见C语言的归途🦔🦔
🐺C语言没有风花雪月没有所谓的思想高于一切,这是一场修行,是在孤独中前行的理性之旅:
在指针中学会寻找,在内存中苦苦争渡
C语言编程冒险之旅——开篇(二)
前言
上篇文章我们了解了分支循环语句的一些知识,以及c语言中关于函数的一些基本概念,和用法,在本篇文章我将对剩下的一些基本知识进行讲解,让我们可以看懂一些基本的代码,使我们能对一些代码能够有比较深的了解
一、数组
1.基本概念
数组是由一系列类型相同的元素所构成的集合。
2.定义方法
e.g:
//示例代码
int arr[3] = {1,2,3};/*注意方括号里的数组元素个数必须是常量。这里指的常量
不包括由const修饰的常变量,因为即使是常变量其本质还是
变量*/
3.访问调用
一般来讲我们调用数组是通过访问下标来实现的(请注意在数组内部数组对元素的下标是这样规定的:从左向右下标从0依次增大。所以我们用下列方式进行调用即可
//定义数组
int arr[4] = {0};//定义完数组数组一般要进行初始化,这样可以避免非法访问
arr[2] = 1; //一般来讲无论是创建变量还是数组,一般都要进行初始
//如若不然一些检查严格的编译器,会报错。
二、操作符
操作符,顾名思义对数据进行一定操作的符号,当然这里的操作并不仅限于算数操作,还包含多种多样的操作方式,下面即即区分种类进行讲解
1.算数操作符
+ - * / %
这些算数操作符看字面意思大概就能猜出来大体的意思,但值得注意的是%它的意思是取余,也被称作取模,使用这个操作符会得到两个操作数相除的余数,而且两个操作数必须是整形类型。
//比如:
int c = 4;
int a = 3;
int b = a % c
得到的结果 b = 1。
2.移位操作符
<< >>
这两个操作符较为复杂,在后边操作符详解的时候会讲到。
3.位操作符
^ 按位异或操作符
~ 按位取反(将这个数据的二进制位全部取反)
& 按位与
| 按位或
因为这些操作符的难度较高后边一块讲解。
4.单目操作符
– 将一个数值改为负值
! 逻辑反操作(即表示不是什么的意思)
~ 针对二进制位进行取反
& 取地址
+ 让数值变成正值
sizeof 计算操作数的所占字节数大小
– – 自减和-=1差不多
++ 自加和+=1差不多
* 解引用操作符
(类型) 将一定类型的数据强制转换为另一种类型
5.条件操作符
>=
<=
== 等于
!= 表示不相等关系
=== 恒等于
6.逻辑操作符
|| 逻辑或
&& 逻辑与
7.赋值操作符
= //它可以跟很多操作符组合使用e.g:+= -= *=……
8.一些特殊的表达式和操作符
逗号表达式
(表达式1,表达式2) 这个表达式输出的结果只会是最后一个表达式的结果。
问号表达式
(表达式)?表达式:表达式
这个表达式会根据括号内表达式真假情况进行返回若为真则会返回第一个表达式的值,反之则返回第二个表达式的值。
特殊的操作符
[ ] 常见于数组下标引用
-> 结构体成员操作符
. 结构体操作符
( ) 函数调用
三、关键字
所谓关键字,就是被编译器征用的字符,用户在编写代码的时候不能使用,详情请见下图:
下面我们对一些关键字进行解析:
1.typedef(相当于python中的as)
这个关键字是针对一个类型重命名为一个新的类型
//示例
int b = 0;
typedef int new;
new a = 0;
//虽说是新建类型,但是,从某种方面来讲他们还是相同的。
2.static(静态类型关键字)
用法:
- 用于修饰局部变量
- 用于修饰全局变量
- 用于修饰函数。
下面我们将对这几个功能进行实验:
首先我们来看这样一段代码:
修饰局部变量
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void my_test()//注意当所定义函数没有返回值的时候可以用void来当作函数返回类型
{
int a = 0;/*因为是局部变量所以生命周期仅限于my_test函数内部所以每次调用此函数都会重新创建a变量使其数值归为0*/
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while (i < 10)
{
my_test();
i++;
}
return 0;
}
所以这段代码的结果如下:
但倘若在a变量前加上静态类型关键字结果就会使另一副样子。
那为什么会产生这样的结果呢?因为static在修饰局部变量时只会使得这个变量被定义一次,使得他的生命周期延长,每次运行到static int a的时候并不会在对a进行重新创建,和定义,会保留原有的值下面让我们深入内存来刨析:
修饰全局变量
首先我们要知道全局变量有一定的外链性,在一个文件中定义可以在同一个项目的另一个文件中使用。只需要在在调用的文件,用extern来声明就能使用。
但是如果在test1.c的全局变量用static进行修饰,则会出现编译出错:
所以可以得出当static对全局变量进行修饰则会让全局变量失去外链性。
修饰自定义函数
这与修饰全局变量类似,可以使得无法在外部文件使用。
四、#define 定义常量和宏
1.常量定义使用
具体规则:
使用可以用于数组的定义
2.定义宏(类似于函数的定义)
语法举例:
#define add(x,y) x + y #include<stdio.h> int main() { printf("%d",add(2,3));//与函数不同的是宏定义的原理是在编译后将式子赋值并加以替换 //但如果是4*add(2,3)则与常规认知不同不是4*(2 +3)而是4*2+3 return 0; } //优化可以改为add(x,y) ((x) + (y))
五、指针
❤️指针,是c语言针对内存操作指向的特殊机制。所以在对指针进行了解的时候,我们要对内存编号有一定的了解。
从计算机组成来理解,现在主流系统分为32位和64位这里的32和64指的是地址线,所以在内存基础上就分为32bit和64bit。但为了更加有效的使用内存,就会将8bit划分为一个内存单元,称作一个字节。并同时给这些字节打上属于自己的符号->地址,便于访问。
注意:一个字节对应着一个地址
同时我们前边学的&就用了用武之地了,对变量使用这个操作符能够将变量的地址取出来,同时定义指针变量来存放地址。
int a = 0;
int * p = &a;
原理分析:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int a = 0; int* p = &a; printf("%p\n",p ); printf("%d", *p); return 0; }
补充:指针变量是存放地址的变量,定义形式为
数据类型 + * +变量名 =
指针变量大小
在32位环境下换算得到4个字节,在64位则位8个字节
sizeof(char*);
sizeof(int*);
sizeof(float*);
sizeof(double*);//因为不同类型的指针都是地址所以都相等。
六、结构体
结构体的定义是为了应对具有不同特征数据的描述的数据类型,构造的模型。用不同数据变量等来描摹新的个体,给编译器看的具体形式,就比如:书的特点包括书名,书价等……
1.定义
struct book
{
int book_price;
char book_name[10];
};
观察结构体的定义,可以发现结构体最后有一个分号,这里是定义符合这个book类型的变量即,具体的形象。并且在此定义的变量具有全局属性。,当然定义的方法也不只有这个方法;
struct book s1;
基本定义类型:
struct + 结构体名 + 变量名
2.调用方式
变量.成员名便可得到这个成员的值
结构指针变量->要访问的成员s1.id//结构变量用 . 访问 struct book * p = &s1; p -> id;//结构指针用->访问。->左边一定要是结构指针右边是成员名
总结
人生南北多歧路,君向潇湘我向秦
若您觉得有趣,请一键三连,支持一下。