初始C语言3

发布于:2024-12-23 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

9. 操作符

9.1 算术操作符

9.2 移位操作符

9.3 位操作符

9.4 赋值操作符

9.5 单目操作符

9.6 关系操作符

9.7 逻辑操作符

9.8 条件操作符

9.9 逗号表达式

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

10. 常见关键字

10.1 typedef

10.2 static

10.2.1 修饰局部变量

10.2.2 修饰全局变量

10.2.3 修饰函数

10.3 register-寄存器

11. #define 定义常量和宏

12. 指针

12.1 内存

12.2 指针变量的大小

13. 结构体


9. 操作符

C语言非常灵活:因为它提供了丰富的操作符。

9.1 算术操作符

+  -  *  /  %
//除和取模的区别
#include <stdio.h>
int main()
{
    int a = 7 / 2; 
    int c = 7 / 2.0; //除号的两边都是整数时,执行整数除法;若两边其中有一个浮点数,则执行浮点数的除法
    int b = 7 % 2; //取模操作符的两边只能是整数
    printf("%d\n",a); //3
    printf("%.1f\n",a); //2.5,%.1f:打印浮点型且小数点后保留一位
    printf("%d\n",b); //1
    return 0;
}

9.2 移位操作符

>>右移操作符   <<左移操作符
涉及二进制的运算,后面讲解

9.3 位操作符

&与   ^异或   |或
后面讲解    

9.4 赋值操作符

=  +=  -=  *=  /=  &=  ^=  |=  >>=  <<=
int main()
{
    int a = 0; //初始化
    a = 20; //赋值
    
    a = a + 3; //23
    //简化上面操作
    a += 3; //23
    
    return 0;
}

9.5 单目操作符

a + b  //+属于双目操作符,+两边分别有一个操作数
单目操作符:只有一个操作数
!           逻辑反操作
-            负值
+            正值
sizeof       操作数的类型长度(以字节为单位)
--           前置、后置--
++           前置、后置++
(类型)        强制类型转换
&            取地址,涉及指针后面讲解
*            间接访问操作符(解引用操作符),后面讲解
~            对一个数的二进制按位取反,涉及二进制后面讲解
//C语言中规定:0表示假,非0表示真
#include <stdio.h>
int main()
{
    int flag = 0;
    if (!flag)
    {
        printf("hehe\n"); //hehe
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int a = -10;
    int b = -a;
    printf("%d\n",b); //10
    return 0;
}
//sizeof是单目操作符,非函数
#include <stdio.h>
int main()
{
    int a = 10;
    printf("%d\n",sizeof(a)); //4字节
    printf("%d\n",sizeof(int)); //4字节
    printf("%d\n",sizeof a);  //4字节
    return 0;
}
//求数组的元素个数
#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%d\n",sizeof(arr)); //40字节,计算的是整个数组的大小,单位是字节
    printf("%d\n",sizeof(arr[0]));  //4字节
    printf("%d\n",sizeof(arr) / sizeof(arr[0])); //10,数组的元素个数
    return 0;
}
//后置++
#include <stdio.h>
int main()
{
    int a = 10;
    int b = a++; //后置++,先使用,后++。所以b=a;a=a+1
    printf("%d\n",a); //10
    printf("%d\n",b); //11
    return 0;
}
//前置++
#include <stdio.h>
int main()
{
    int a = 10;
    int b = ++a; //前置++,先++,后使用。所以a=a+1;b=a
    printf("%d\n",a); //11
    printf("%d\n",b); //11
    return 0;
}
//(类型)
#include <stdio.h>
int main()
{
    int a = (int)3.14; //3.14字面浮点数,编译器默认理解为double类型
    printf("%d\n",a); //3
    return 0;
}

9.6 关系操作符

>
>=
<
<=
!=       用于测试“不相等”
==       用于测试“相等”
#include <stdio.h>
int main()
{
    int a = 10;
    if (a = 3)  //将3赋值给a,则a=3,3为非零,为真则执行打印
    {
        printf("hehe\n"); //hehe
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int a = 10;  //初始化a=10
    if (a == 3)  //10不等于3为假,为假则不打印
    {
        printf("hehe\n"); //hehe
    }
    return 0;
}

9.7 逻辑操作符

&&  逻辑与,并且
||  逻辑或,或者
#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    if (a && b)  //a=10,非0为真;b=20,非0为真。两边均为真则执行打印
    {
        printf("hehe\n"); //hehe
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int a = 10;
    int b = 0;
    if (a || b)  //a=10,非0为真;b=0为假。其中一边为真则执行打印
    {
        printf("hehe\n"); //hehe
    }
    return 0;
}

9.8 条件操作符

三目操作符:有3个操作数
exp1 ? exp2 : exp3
真      √       ×
假      ×       √
#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    int r = (a > b ? a : b);
    printf("%d\n",r); //20
    return 0;
}

9.9 逗号表达式

exp1, exp2, exp3, ···expN
逗号表达式:逗号隔开的一串表达式。
特点:从左向右依次计算,整个表达式的结果是最后一个表达式的结果。
#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    int c = 0;
    int d = (c=a-2 , a=b+c , c-3);
    //  c=10-2=8    a=20+8=28    8-3=5
    printf("%d\n",d); //5
}

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

[]   ()   .   ->
//下标引用操作符
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9 };
    int n = 3;
    arr[n] = 20;  //[]是下标引用操作符,arr和3是[]的操作数
    return 0;
}
//函数调用操作符
int Add(int x,int y)
{
    return x+y;
}
int main()
{
    int sum = Add(2,3); //():函数调用操作符 Add,2,3都是()的操作数,且函数调用操作符不可省略
    return 0;
}

10. 常见关键字

//C语言本身内置的,关键字不是自己创建出来的,也不能自己创建
auto    //局部变量默认auto,通常省略,进入作用域创建,离开作用域销毁
break   //for,while,do while循环中使用,退出循环 
case    //switch与case搭配使用
char
short
int
long
float
double
const   //常属性,修饰变量
continue  //与循环一起使用  
default
do
else
enum    //枚举
struct   //结构体
union   //联合体或共用体
extern  //声明外部符号
for
goto  //实现跳转语句
if
register  //寄存器
return   //函数返回值
signed    //有符号的
unsigned   //无符号的
sizeof  //计算类型大小
static  //静态的,修饰函数和变量
switch  
typedef  //类型重命名
void   //无,用于函数的返回类型,函数的参数
volatile
while
int main()
{
    auto int a = 10;  //自动变量,通常省略,局部变量都是auto类型
    return 0;
}
//未全,暂时分类
for while do break continue
if switch case default goto
char short int long float double signed unsigned enum struct union void sizeof typedef
const
extern 
register static 
return
变量的命名:
1、有意义
int age;
int salary;

2、变量名必须是字母、数字、下划线组成,不能有特殊字符,同时不能以数字开头
int 2b; //error
int _2b; //ok

3、变量名不能是关键字

10.1 typedef

类型定义(类型重命名)

typedef unsigned int unit;
typedef struct Node
{
    int data;
    struct Node* next;
}Node;
int main()
{
    unsigned int num = 0;
    unit num = 1;
    
    struct Node n;
    Node n2;
    return 0;
}

10.2 static

static用来修饰变量和函数:
1、修饰局部变量---静态局部变量
2、修饰全局变量---静态全局变量
3、修饰函数---静态函数

10.2.1 修饰局部变量

#include <stdio.h>
void test()
{
    int a = 1;
    a++;
    printf("%d ",a);  //打印10个2,因为a是局部变量,进入作用域创建,离开作用域销毁
}
int main()
{
    int i = 0;
    while (i < 10)
    {
        test();
        i++;
    }
    return 0;
}
#include <stdio.h>
void test()  //void类型表示函数不需要返回(return)
{
    static int a = 1;
    a++;
    printf("%d ",a);  //2 3 4 5 6 7 8 9 10 11
}
int main()
{
    int i = 0;
    while (i < 10)
    {
        test();
        i++;
    }
    return 0;
}

static修饰局部变量时,局部变量出了作用域,不销毁。本质上static修饰局部变量时,改变了变量的存储位置。影响了变量的生命周期,生命周期变长,和程序的生命周期一样。

10.2.2 修饰全局变量

全局变量是具有外部链接属性的。

源文件通过编译+链接--->生成可执行程序

//add.c文件:
int g_val = 2022; //全局变量   

//test.c文件:
#include <stdio.h>
extern int g_val; //声明外部符号
int main()
{
    printf("%d\n",g_val); //2022
    return 0;
}
//add.c文件:
static int g_val = 2022; //静态变量   

//test.c文件:
#include <stdio.h>
extern int g_val; //声明外部符号
int main()
{
    printf("%d\n",g_val); //error
    return 0;
}

static修饰全局变量时,全局变量的外部链接属性变为了内部链接属性。

其它源文件(.c文件)就不能再使用到这个全局变量了。

我们在使用的时候,感觉作用域变小了。

10.2.3 修饰函数

函数是具有外部链接属性的。

//add.c文件:
int Add(int x,int y)
{
    return x + y;
}

//test.c文件:
#include <stdio.h>
extern int Add(int x,int y);
int main()
{
    int a = 10;
    int b = 20;
    int r = Add(a,b);
    printf("%d\n",r); //30
    return 0;
}

//add.c文件:
static int Add(int x,int y)
{
    return x + y;
}

//test.c文件:
#include <stdio.h>    
extern int Add(int x,int y);
int main()
{
    int a = 10;
    int b = 20;
    int r = Add(a,b);
    printf("%d\n",r); //warning
    return 0;
}

一个函数本来是具有外部链接属性的,但被static修饰时,外部链接属性就变为了内部链接属性。

其它源文件(.c文件)就不能使用了。

10.3 register-寄存器

电脑上的存储设备有哪些?

  • 寄存器(集成到CPU上)
  • 高速缓存(cache)
  • 内存
  • 硬盘

CPU---中央处理器

将数据从内存送到CPU进行处理,计算,由于技术发展,CPU处理速度加快,而内存跟不上,所以出现如图所示的金字塔。

int main()
{
    //寄存器变量
    register int num = 3; //建议将3存放在寄存器中,最终由编译器决定存放位置
    return 0;
}

11. #define 定义常量和宏

//#define 定义标识符常量

#define NUM 100
#include <stdio.h>
int main()
{
    printf("%d\n",NUM); //100
    int n = NUM;
    printf("%d\n",n); //100
    int arr[NUM] = { 0 }; //数组中有100个元素
    return 0;
}
//#define 定义宏,宏是有参数的
#define ADD(x,y) ((x)+(y)) //ADD:宏名;x和y是宏的参数,参数是无类型;后面括号内的是宏体
#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("%d\n",c); //30,处理过程类似替换,int c = ((a)+(b))
    return 0;
}

.h:头文件(函数的声明、类型的声明、头文件的包含)
.c:源文件(函数实现)

浮点数的四舍五入,不能用你肉眼看到的数值来计算!因为浮点数在内存中有可能不能精确保存。如12.455,可能内存中存储的是12.454988888888828282···
数据存储中会详解。

12. 指针

12.1 内存

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

所以为了有效的使用内存,就把内存划分为一个个小的内存单元,每个内存单元的大小是1个字节

为了能够有效地访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址

综上所述:

内存会划分为一个个的内存单元(一个内存单元的大小:1Byte)。

每个内存单元都有一个编号(地址/指针)。

8进制:0-7
10进制:0-9
16进制:0-9,a, b, c, d, e, f
           10,11,12,13,14,15

内存中存储10:
0000 0000 0000 0000 0000 0000 0000 1010 //2进制
0    0    0    0    0     0    0    a
0x 00 00 00 0a  //16进制
#include <stdio.h>     
int main()
{
    int a = 10; //向内存申请4个字节(32bit),来存储10
    &a; //&:取地址操作符
    printf("%p\n",&a); //00000000005FFE9C,%p打印地址
    return 0;
}

调试可看监控窗口和内存窗口,后续出调试哇。也可自己上网查查资料。此处先不说。

#include <stdio.h> 
int main()
{
    int a = 10;
    int* p = &a; //p:指针变量
    //int说明p指向的对象a是int类型
    //*说明p是指针变量
    *p = 20; //*表示解引用操作符,*p就是p指向的对象。意思就是通过p中存放的地址,找到p所指向的对象a
    printf("%d\n",a); //20
    return 0;
}

内存单元

编号--->地址--->指针(地址也被称为指针)

存放指针(地址)的变量就是指针变量。

12.2 指针变量的大小

不管是什么类型的指针,都是在创建指针变量。

指针变量是用来存放地址的。

指针变量的大小取决于一个地址存放时需要多大空间。

  • 32位机器上的地址:32bit位---4Byte,所以指针变量的大小是4个字节(x86)
  • 64位机器上的地址:64bit位---8Byte,,所以指针变量的大小是8个字节(x64)

VS默认是x86平台,可调节嗷。

#include <stdio.h>
int main()
{
    printf("%zu\n",sizeof(char*)); //8字节
    printf("%zu\n",sizeof(short*)); //8字节
    printf("%zu\n",sizeof(int*)); //8字节
    printf("%zu\n",sizeof(float*)); //8字节
    printf("%zu\n",sizeof(double*)); //8字节
    return 0;
}

13. 结构体

描述人:名字+年龄+性别···

描述书:书名+作者+出版社···

人和书均为复杂对象,C语言就给了自定义类型的能力。自定义类型中有一种叫做:结构体。

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

#include <stdio.h>
struct Stu  //类型
{
    //成员
    char name[20];
    int age;
    char sex[10];
    char tele[12];
};
int main()
{
    struct Stu s = {"zhangsan", 20, "nan", "15590001234"}; //创建struct Stu类型的对象s并进行初始化
    printf("%s %d %s %s\n",
           s.name, s.age, s.sex, s.tele); //zhangsan 20 nan 15590001234
    //结构体对象.成员名:访问结构体对象s里面的成员
    return 0;
}
#include <stdio.h>
struct Stu  //类型
{
    //成员
    char name[20];
    int age;
    char sex[10];
    char tele[12];
};
void print(struct Stu* ps)
{
    printf("%s %d %s %s\n",(*ps).name, (*ps).age, (*ps).sex, (*ps).tele); //zhangsan 20 nan 15590001234 
    //解引用指针,找到ps指针变量指向的结构体对象s。略显啰嗦
    printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->tele); //zhangsan 20 nan 15590001234
    //结构体指针变量->成员名
    
}
int main()
{
    struct Stu s = {"zhangsan", 20, "nan", "15590001234"}; //创建struct Stu类型的对象s并进行初始化
    print(&s); //将结构体对象s的地址(指针)传给print函数
    return 0;
}

 本周就暂且更新至此吧,期待下周再会。如有错误还请不吝赐教。