初识C语言:从入门到精通(完结)

简介: 最后一篇对于C语言基础知识的总结,适合新手入门。

上篇内容分享了两种语句(选择语句、循环语句)、函数、数组、各种操作符,本篇文章我们再来了解关于初识C语言的内容,同样,涉及到的知识不会太复杂,废话不多说,正文开始:

紫蓝色几何渐变科技互联网微信公众号封面 (1).gif

1.常见关键字

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

C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创建关键字的。

关键字我们在本篇先介绍几个,后面遇到了再进行细致的讲解。

1.1关键字 typedef:

typedef顾名思义就是类型定义,在这里就是类型重命名。

比如:

typedefunsignedintuint_32;  //使用typedef重新定义一个类型:将unsigned int 重命名为uint_32//但不会取消unsigned int 的含义intmain()
{
unsignedintnum1=0;    //unsigned 表示无符号,unsigned int表示无符号整数//也就是处负数以外的整数uint_32num2=0;        //经过重命名,这里的num2的类型与num1的类型一致return0;
}

1.2关键字static:

在C语言中:

static是用来修饰变量函数

  • 修饰局部变量--称为静态局部变量
  • 修饰全局变量--称为静态全局变量
  • 修饰函数--称为静态函数

1.2.1修饰局部变量:

intmain()
{
inta=10;//局部变量,自动创建,自动销毁的return0;
}

局部变量是自动创建,在使用完之后便会自动销毁

当我们用static修饰局部变量之后会有怎样的效果呢?、

首先不用static修饰:

#include<stdio.h>voidadd()
{
inti=0;          //局部变量自动创建,自动销毁并且,他只是作用于这个add函数i++;
printf("%d ", i);
}
intmain()
{
inti=0;
while (i<10)
    {
add();    //设置一个函数i++;
    }
return0;
}

可以很直观的看到,i每一次打印都是1,因为i在add函数中刚刚创建好是0,i++变成了1,然后打印,但是当再次进去add函数时,上次的i已经销毁,所以i又是从0开始,所以我们就得到了10个1

当我们用static修饰这个局部变量i的时候会有什么效果呢?

#include<stdio.h>voidadd()
{
staticinti=0;    //用static来修饰一下局部变量ii++;
printf("%d ", i);
}
intmain()
{
inti=0;
while (i<10)
    {
add();
i++;
    }
return0;
}

当我们用static来修饰局部变量之后,可以看到,每次i++之后的值都被保留了下来,不再销毁,哎呀呀,这可不得了呀,所以呀,老铁们,static在修饰局部变量时的作用是:改变了局部变量的生命周期,让静态局部变量出了它自己的作用域仍然可以继续存在,直到整个程序结束,它才的生命周期才跟着结束,但是,并不影响它的作用域。

1.2.2修饰全局变量:

全局变量它的生命周期是整个程序的生命周期,只有程序结束,它的生命周期才跟着结束。当我们有两个.c文件时,在一个.c文件中创建一个全局变量,在另外一个.c文件中就可以使用这个变量,在使用时要用extern来声明外部符号

//extern  变量类型   变量名称;   //用来声明外部符号

源文件:add.c:

intg_val=2023;

源文件:test.c:

#include<stdio.h>externintg_val; //声明外部符号intmain()
{
printf("%d\n",g_val);
return0;
}

当在一个源文件中创建一个全局变量,那么如果我们需要在另外一个源文件中使用这个全局变量,我们只需要用extern来声明一下,就可以使用了,那我们用static来修饰一下这个全局变量之后又会是什么样的效果呢?

源文件:add.c:

staticintg_val=2023;

源文件:test.c:

#include<stdio.h>externintg_val;
intmain()
{
printf("%d\n",g_val);
return0;
}

可以看到哇,这个static在修饰全局变量时居然不能使用了,所以呀,static在修饰全局变量时起的作用是:改变了全局变量的作用域,使得这个全局变量只能在自己所在的源文件内部进行使用。我们要知道全局变量是具有外部链接属性,而在用static修饰之后,使得它的外部链接属性变成了内部链接属性,使其只能在自己的源文件内部使用,从而给我们直观的感受就是改变了它的作用域。

1.2.3修饰函数:

函数也具有外部链接属性,所以我们同样使用两个源文件,在一个源文件中创建函数Add,在另外一个源文件使用Add函数:

源文件:add.c:

intAdd(intx, inty)
{
returnx+y;
}

源文件:test.c:

#include<stdio.h>externintAdd(int,int);  //这里注意,在使用extern声明外部函数时,需要加上参数类型,参数可加可不加//int是参数类型intmain()
{
intx=0;
inty=0;
intadd=0;
printf("请输入两个数:>");
scanf("%d %d", &x, &y);
add=Add(x, y);
printf("add = %d", add);
return0;
}

在用static修饰函数时效果和修饰全局变量是一样的,都是改变链接属性,我们来验证一下:

源文件:add.c:

staticintAdd(intx, inty)
{
returnx+y;
}

源文件:test.c:

#include<stdio.h>externintAdd(int,int);
intmain()
{
intx=0;
inty=0;
intadd=0;
printf("请输入两个数:>");
scanf("%d %d", &x, &y);
add=Add(x, y);
printf("add = %d", add);
return0;
}

效果很明显,也是不能使用了,所以static在修饰函数时改变了这个函数的链接属性,使其只能在本源文件中使用。

📚static总结:

  1. static在修饰局部变量时改变了变量的存储类型,而恰恰是因为存储类型的改变,从而导致了局部变量的生命周期的延长,但是并不影响它的作用域,该在哪里起作用就在哪里起作用。
  2. static在修饰全局变量时改变了全局变量的外部连接属性,使其变为内部连接属性,导致该全局变量只能在自己所在的源文件中起作用,其他的源文件无法链接使用,带给我们的感受是改变了它的作用域。
  3. static在修饰函数时也是改变了函数的链接属性,使其改变为内部链接属性,从而使这个函数只能在自己所在的源文件内部进行使用,其他源文件无法链接使用。(这里的函数指的不是同一个源文件中的函数,而是其他源文件内部的函数)

2.#define 定义常量和宏

2.1#define定义标识符常量:

#include<stdio.h>#define M 2023  //#define定义的标识符常量通常都是用的是大写字母intmain()      
{
//M = 2022   //定义的是常量那很明显是不能修改的printf("M= %d", M);   
return0;
}

2.2#define定义宏:

在用#define定义宏时要带上参数

#include<stdio.h>#define ADD(x,y)  ((x)+(y))  //定义宏intmain()
{
intadd=0;
add=ADD(20, 10);        
printf("add= %d\n",add);   //add=30add=3*ADD(5, 10);     //add=45printf("add= %d", add);
return0;
}

可以看到:#define定义的宏不仅可以实现单独运算,也可以实现混合运算,也是非常方便的。

3.指针

指针是C语言中比较抽象的一部分知识,有很多的老铁看到指针就头疼,但是我们这里只是对指针做一个简单的认识和了解,然后学习一些关于指针的基础、简单的知识。

要想学好指针,就先得了解内存:

3.1内存:

在我们电脑上有许许多多的软件,这些软件在运行起来都需要内存,我们可以按住键盘上的Ctrl+Alt+Delete打开我们的任务管理器,就可以看到我们使用电脑时都有哪些软件在运行以及这些软件所占用的内存。

我们在买电脑时电脑的内存有很多选择:4G、8G、16G,那这些内存在电脑中是怎样的呢?

为了有效地使用内存,首先内存被划分为一个一个的内存单元,然后依次给这些内存进行编号,这些编号被称为该内存单元的地址。那么这一个个的内存单元是多大呢?其实一个内存单元的大小是一个字节(byte)(1byte = 8bit),如果我们在后期要找到存放在内存单元中的东西,我们就需要知道它的地址,知道地址就可以使用指针来找到它。所以呀,地址就是指针,指针就是地址。其实现实中也有类似的,就比如我们住在大学宿舍,然后我们的同学来找我们,那那么多的宿舍楼总不可能一个一个楼层、一个个房间的找吧,首先得知道地址吧,比如:男生宿舍6号楼519,这就是我们的地址,我们的同学只需要知道这个地址就可以很方便的找到我们,那么指针也类似于这样的作用。

变量也是创建在内存中的(在内存中分配空间),每一个内存单元都有地址,所以变量也是有地址的。假设我们创建了一个int整形的变量,一个整形变量的大小是4个字节,所以创建的一个整形在内存中要占4个内存单元,那么再分配这个整形变量的地址时是怎么分配的呢?

我们创建了一个整形变量a,在内存中占4个内存单元,假设a的地址是上图中的地址,那当我们取出a的地址的时候,是不是把这四个内存单元的地址都取出呢?我们来试一下:

在验证之前我们来了解一个新的操作符:&  ,取地址操作符,这个我们在之前都见过

打印地址使用的是: %p

#include<stdio.h>intmain()
{
inta=10;
&a;       //取出a的地址printf("&a= %p\n", &a);  //打印地址使用%preturn0;
}

我们可以看到,取出的地址只有一个,其实呀,a这个整形变量在创建时确实占用了4个内存单元,但是在采用取地址操作后,取出的地址是a所占内存单元中较小的那个地址,所以只打印一个地址。在编译器里面打印的时候,可以发现每次打印的地址都不一样,这是因为编译器在每一次编译的时候,会分配不同的地址。

那需要怎么储存这个变量的地址呢?

这时候需要定义指针变量:

inta=10;
int*pa=&a;     //创建指针变量*pa=20;       //解引用找到aprintf("%d\n",a);

我们来解读一下这段代码:

首先创建一个整形变量 a 赋值为10,然后创建一个指针变量,这里要注意int * 是指针变量的类型,pa是指针变量的名称,接下来使用操作符: * ,该操作符是解引用操作符,前面都见过,主要作用是将原本的指针变量解引用找到它并操作它,在这个代码里面就是通过pa找到pa指向的a,所以*pa就是a,然后给*pa赋值为20,所以最后打印出的结果就是20.

由于地址就是指针,pa是存放指针的,所以在C语言中把pa叫:指针变量。

注:地址的形式是16进制的。

知道了指针变量我们也可以使用指针来改变字符

#include<stdio.h>intmain()
{
charch='w';
char*pch=&ch;
*pch='d';
printf("ch = %c\n", ch); //打印字符用%creturn0;
}

要注意指针变量的类型

3.2指针变量的大小:

在我们的电脑中有许多的电线,其中就包括地址线,有的电脑32根地址线,有的电脑呢是64根地址线,由于地址线的不同,他们管理地址的大小也就不同,由于数据存储在电脑中是以二进制的方法存储的,所以在32根地址线的机器上它的管理的空间是2^32个字节(2的32次方),那在64跟地址线的机器上呢,它所管理的是2^64个字节。那么我们在32位机器上指针变量的大小和在64位机器上的一样吗?我们来验证一下:

32位平台(32根地址线):

在打印计算出指针变量的大小时使用的是%zd

#include<stdio.h>intmain()
{
printf("%zd\n", sizeof(char*)); 
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(float*));
printf("%zd\n", sizeof(double*));
return0;
}

64位平台(64根地址线):

#include<stdio.h>intmain()
{
printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(float*));
printf("%zd\n", sizeof(double*));
return0;
}

可以看到,在不同的平台下,指针变量的大小是不一样的,在32位平台下,一个指针变量的大小是4个字节,一个字节又等于八个比特位,所以所占32个比特位的大小,在64位平台下,一个指针变量又是8个字节,所以占64个比特位,因此只有平台的不同,指针变量的大小才会改变。

结论:指针在32位平台大小就是4个字节,在64位平台上就是8个字节,与指针变量的类型无关。

4.结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型,结构体是自己创建的。

比如:一本书包含 书名+作者+定价+日期 这些信息.

先来了解一点新的东西:

struct:结构体关键字,用于创建结构体

操作符:‘ . ’:用于结构体变量,从而找到该成员。

操作符:‘ -> ’:  用于结构体指针,从而指向该成员。

#include<stdio.h>structBook//结构体关键字用来创建{
charname[20];   
charwriter[10];
intprice;
chartime[20];
};
intmain()
{
structBookx= { "C语言","张三",55,"2023_1_20"};
printf("书名:《%s》\n作者:%s\n价格:%d元\n时间:%s\n", x.name,x.writer ,x.price, x.time);
//这里使用的是操作符‘ . ’  //使用‘ . ’操作符来找到结构体中所对应的成员       return0;
}

我们也可以使用操作符‘ -> ’来找到结构体中的成员,但是要注意,‘ -> ’是用于结构体指针,所以我们得设置一个函数,将结构体的地址传给函数,然后使用  -> 来找到。

#include<stdio.h>structBook{
charname[20];
charwriter[10];
intprice;
chartime[20];
};
voidPrintf(structBook*px)   //这里要接收x,所以要创建指针变量{
printf("书名:《%s》\n作者: %s\n价格:% d元\n时间:% s\n", px->name, px->writer, px->price, px->time);
//这里使用的就是操作符‘ -> ’用来找到结构体中的成员//也可以使用解引用操作 ,从而找到结构体成员//printf("书名:《%s》\n作者: %s\n价格:% d元\n时间:% s\n",(*px).name,(*px).writer,(*px).price,(*px).time);}
intmain()
{
structBookx= { "C语言","张三",55,"2023_1_20" };
Printf(&x);  //设置一个Printf函数,将x的地址传给它return0;
}


我们初识C语言的内容就到此结束了,回过头来我们已经了解了许多许多关于C语言的知识,但这些知识只是皮毛,后面我们会对C语言知识进行庖丁解牛,会很清晰的将每一个知识点都分享给大家,感谢大家的支持!

目录
相关文章
|
1月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
52 2
|
1月前
|
C语言
【C语言的完结】:最后的测试题
【C语言的完结】:最后的测试题
19 3
|
1月前
|
存储 Java 编译器
初识C语言1——C语言入门介绍
初识C语言1——C语言入门介绍
30 1
|
1月前
|
C语言
回溯入门题,数据所有排列方式(c语言)
回溯入门题,数据所有排列方式(c语言)
|
3月前
|
C语言
C语言------程设设计入门
这篇文章是C语言程序设计的入门教程,涵盖了C程序的实现过程、VC集成开发环境的使用、基本数据类型的使用、格式控制字符的作用,以及通过示例代码演示了如何使用printf()函数输出不同类型的数据。
C语言------程设设计入门
|
4月前
|
存储 Java C语言
【C语言入门】初识C语言:掌握编程的基石
【C语言入门】初识C语言:掌握编程的基石
67 4
【C语言入门】初识C语言:掌握编程的基石
|
3月前
|
NoSQL Java 编译器
C语言从入门到精通该怎样学?
持续学习与实践:编程是一门需要不断学习和实践的技能,要保持对新技术和新知识的敏感性,并持续进行编程实践。
57 1
|
4月前
|
存储 Java 程序员
【C语言入门】C语言入门:探索编程世界的基础概念
【C语言入门】C语言入门:探索编程世界的基础概念
105 2
|
4月前
|
前端开发 C语言 C++
C语言入门02---环境搭建
C语言入门02---环境搭建
|
5月前
|
存储 Web App开发 算法
c语言的简单入门
熟悉c语言(简单入门)