前言
- 本篇是对C语言(上)的补充,涉及C语言中较多的难点,请入门者好好观看哟!
- 不够也不要太担心,这只是简单的了解C的难点,并不会深度介绍,以后会为大家详细介绍.
阅读本文之前你是否还记得C语言上的部分?如果不记得尽快回顾一遍吧! 点击这里哦!!!
本文开始
文章重点
- 初识数组
- 初识操作符
- 初识关键字
- 初识标识符常量
- 初识指针
- 初识结构体
1.初识数组
1.1什么是数组?
数组:一组 相同元素 的集合
1.2 什么时候我们会用到数组呢?数组如何使用呢?我们来看看.
当我们需要存放一组数据的元素,单一的变量显然已经满足不了我们了,数组的出现就解决了这种问题
- 数组创建:一组数的数据类型+数组名+存放数据的个数
int arr[10]; char ch[5]; int count[26];
#include<stdio.h>
int main()
{
int arr1[10]={0,1,2,3,4,5,6,7,8,9};
int arr2[10]={1,2,3};
int arr3[]={1,2,3};
int arr[];
int n=10;
int arr[n];
return 0;
}
1.3数组下标
- 数组存放元素,我们如何来找到数组中的元素呢?这里就考虑到了,C语言中规定的下标了,C规定数组每个元素都有一个下标,下标规定从0开始.
数组下标:
1.4数组的使用
说了怎么多,不如我们来实践这么一回,让我们用之前学的while循环来实现数组使用吧!
#include<stdio.h>
int main()
{
int arr[10] = {0,2,4,6,8,1,3,5,7,9};
int i = 0;
while (i < 10)
{
printf("%d ", arr[i]);
i++;
}
return 0;
}
2.操作符
2.1算术操作符
算数:+ - * / %
在计算机操作中使用 /号 和 %号,可能和你想的不同哦,我们来看一下.
-
/: double a = 5 / 2;结果是2.000000(先不要管为什么这么多0),和你想的是否差距太多呢?我们以常规数学思维想得到2.5,,但计算机并不这么认为,想得到2.5就得以他的规则,把分子分母至少一个该为浮点数就可以算出想要的结果2.5了.如:double a = 5.0 / 2; double a = 5 / 2.0; double a = 5.0 / 2.0; -
%:取模(求余),该操作符只能用于整数,浮点数不可以切记.
2.2移位操作符
移位操作符:<< >>
何为移位呢?其实移动的是二进制位(这里不过多介绍)只知道数据都是以二进制位存储在内存中的就可以了.
2.3位操作符
位操作符:& ^ | 使用在二进制中
- &按位与:AB两个数在内存中换算成二进制,对应的二进制位为0就为0,两个全1才为1;
- |按位或:AB两个数在内存中换算成二进制 ,对应的二进制位有1就为1,两个全0才是0;
- ^按位异或:AB两个数在内存中换算成二进制,对应的二进制位相同位0,相异为1;
2.4赋值操作符
赋值操作符:= += -= *= /= &= ^= |= >>= <<=
类似+=这样称为复合运算符
2.5单目操作符
- ! :逻辑反操作符
- -:负值
- +:正值
- &:取地址
- sizeof :计算类型或变量长度(以字节为单位)
- ~:对一个数的二进制位按位取反
- - -:前置、后置–
- ++:前置、后置++
- *:间接访问操作符(解引用)
- (类型):强制类型转换
int main()
{
int a = 1;
int b = 2;
printf("%d\n", a<b);
printf("%d\n", !(a<b));
int c = 0;
printf("%zu\n", sizeof(c));
int d = 5;
printf("%d %d\n", d--, --d);
int e = 5;
printf("%d %d\n", e++, ++e);
int g = (int)3.14;
printf("%d\n", g);
return 0;
}
结果样例:
2.6关系操作符
关系操作符:> >= < <= != ==
- !=:不等于,这里与数学中的不一样,需要记住哦!
- ==:计算机中的等于是两个 ==,重点记住!!!
2.7逻辑操作符
逻辑操作符(只关注真假):&& | |
- &&:并且(全真才为真)
- ||:或者(两个有1个为真就为真)
int main()
{
int a = 2;
int b = 3;
int c = 0;
if (a && b)
{
printf("都真");
}
if (a || c)
{
printf("hehe");
}
return 0;
}
2.8条件操作符
条件操作符:a ?b : c
强调这里的a b c指的是表达式
条件操作符又称三目运算符
- 如果表达式1为真,跳过表达式2,输出表达式3的值;
- 如果表达式1为假,就判断表达式2,表达式2为真,就输出表达式2的结果;
学会条件表达式你就可用一行代码比较两个数的较大值与较小值了哦,样例如下
int main()
{
int a = 2;
int b = 3;
int c1 = 0;
int c2 = 0;
c1 = a < b ? a : b;
c2 = a > b ? a : b;
printf("%d %d\n", c1,c2);
return 0;
}
2.9逗号表达式
逗号表达式:exp1,exp2,exp3…
* 逗号表达式会从左向右依次计算,以最后一个表达式的值为最后结果.
int main()
{
int a = 2;
int b = 3;
int c = 0;
printf("%d\n", (a = a + 1, b = a - 2, c = b + 3));
return 0;
}
3.初识关键字
3.1C语言规定的关键字
auto break case char const continue default do double else enum extern float goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
C语言的关键字都是本身预先设定好的,初学者要注意,自己是不能创建关键字的
这里只是对部分关键字介绍,其他的,我会在以后的文章中在详细介绍.
3.2typedef
- typedef是类型定义,简单来说就是对类型重命名,
如何使用呢,简单的介绍一下,让小伙伴有一个大概的了解,请看如下代码.
typedef unsigned int unit;
int main()
{
unsigned int num1 = 10;
unit num2 = 20;
return 0;
}
3.3static
static静态的 c语言中 static 用来修饰变量和函数
3.3.1修饰局部变量
让我们先看一段代码吧!
void text1()
{
int i = 0;
i++;
printf("%d ", i);
}
void text2()
{
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
text1();
}
printf("\n");
for (i = 0; i < 10; i++)
{
text2();
}
return 0;
}
代码结果:
- text1与text2代码十分相似,但略有不同,text2有static修饰,实际上static修饰的i只初始化执行一次,再使用时i为上一次保存的值
- 这里补充一些知识点,在内存中数据存放分别在栈区,堆区,静态区,栈区存放的局部变量容易被销毁,而static修饰的局部变量改变了局部变量 的存储位置(相当于改变其生命周期),从栈区变成静态区,,静态区存储的变量不易被销毁,从而使改变存储的局部变量出来自己的使用范围也不会被销毁.
[注]:数据在内存存储的图
3.3.2修饰全局变量
[注]:一般来说,全局变量是具有外部链接数性 static修饰全局变量,这个全局变量的外部链接属性就变成了内部链接属性 这个全局变量只能在自己的.c文件中看到,其他源文件就看不到了
让我们通过代码分析去理解一下吧!
#include<stdio.h>
static int g_val = 2022;
-------------------------------------
extern int g_val;
int main()
{
printf("%d\n", g_val);
return 0;
}
上述程序是在add.文件中static全局变量g_val并在text.c文件中引用,显然上述代码会报错.static修饰全局变量,这个全局变量的外部链接属性 (外部连接属性:一个变量在.c文件中定义,在另一个.c文件中使用) 就变成了内部链接属性,这个全局变量只能在自己的.c文件中看到,其他源文件就看不到了,相当于这里的text.c文件不能使用g_val这个变量.
注意:局部变量的只具有内部链接属性,外部来接属性被改变时,它所使用的范围将会限制.
3.3.3修饰函数
注:函数本身是具有外部链接属性 如果static修饰函数,函数的外部链接属性就变成内部链接属性 修饰后与修饰全局变量效果一样,只能在自身源文件下使用,其他源文件不能使用.
代码正常编译
int Add(int x, int y)
{
return x + y;
}
-------------------------------
#include<stdio.h>
extern int Add(int x, int y);
int main()
{
int a = 2;
int b = 3;
int sum = Add(a, b);
printf("%d\n", sum);
return 0;
}
下面代码会出现编译错误,static修饰Add函数改变其链接属性,使其不能在别的.c文件使用
static int Add(int x, int y)
{
return x + y;
}
-------------------------------
#include<stdio.h>
extern int Add(int x, int y);
int main()
{
int a = 2;
int b = 3;
int sum = Add(a, b);
printf("%d\n", sum);
return 0;
}
4.#define 定义常量和宏
#define MAX 100
#define Add(x,y)((x)+(y)
5.初识指针
指针在C语言中占据着重要地位,小伙伴们要重视起来呀!但不用慌张,这里只是简单的了解一下指针,对它有一个初步的认识.
5.1指针是如何存储的?
这里我们要提到内存了,为了更好使用内存,就把内存划分成一个个小的单元,每个单元的大小为1个字节,我们把数据存储在内存中,那么如何访问内存?我们就给内存单元进行了编号,也称其为 内存单元的地址.
这里只是简单了解一下内存的大概存储,以后会为大家详细介绍.
我们来以代码认识一下指针.
int main()
{
int a = 10;
printf("%p\n", &a);
int* pa = &a;
char ch = 'w';
char* pc = &ch;
return 0;
}
这里说明 指针,本质是地址(地址 == 编号) 口语中,说的指针是指:指针变量
int main()
{
int a = 10;
int* pa = &a;
*pa = 20;
printf("%d\n", a);
return 0;
}
5.2指针变量有多大呢?
我们来看一下指针变量的存储–地址, 所以说 地址所需存储空间是多大,指针变量的大小就是多大,这是根据 编译器决定的.
- 32位机器(x86):一个地址是32个二进制位,存储需要32个bit位空间,所以在32位机器上,指针变量的大小是4个字节
- 64位机器(x64):一个地址是64个二进制位,存储需要64个bit位空间,所以在64位机器上,指针变量的大小是8个字节
那么指针变量的大小是多少呢?我们通过代码来看看吧!
int main()
{
printf("%zu\n", sizeof(char *));
printf("%zu\n", sizeof(short *));
printf("%zu\n", sizeof(int *));
printf("%zu\n", sizeof(double *));
return 0;
}
x86环境下编译的
意不意外,结果和你想的一样吗? 不论那个类型的指针变量,在x86平台下指针大小都是4,在x64平台下都是8,小伙伴们下去可以试一下,看结果是不是一样.
由此可以得出结论:指针变量的大小关键是平台的不同,在相同平台下指针大小一样,在32位平台(x86)是4个字节,在64位平台(x64)是8个字节.
6.初识结构体
生活中有很多复杂的类型,比如说一个学生,学生具有:名字,年龄,性别,学号等信息,面对复杂信息我们又怎么来描述呢?
结构体 的出现为我们带来解决方法,他使得C语言有能力描述复杂类型.给我们带来了很大方便.
struct Stu
{
char name[15];
int age;
char sex[5];
};
int main()
{
struct Stu s = { "zhangsan",18,"nan"};
printf("name=%s age= %d sex=%s\n", s.name, s.age, s.sex);
struct Stu* ps = &s;
printf("name=%s age=%d sex=%s\n", ps->name, ps->age, ps->sex);
return 0;
}```
也可以指定输入结构体成员的值,代码如下:
```c
struct Stu
{
char name[15];
int age;
char sex[5];
};
int main()
{
struct Stu s = { 0 };
scanf("%s %d %s", s.name, &s.age, s.sex);
printf("name=%s age=%d sex=%s\n", s.name, s.age, s.sex);
return 0;
}
[注]一个文字算两个字节
总结
c语言初识,到这里就结束了,通过本篇相信你一定对C语言的整体知识有了进一步了解,如果感觉有帮助就👍一个吧!!!十分谢谢.
|