01初识C语言

这篇博客将带大家初步认识C语言,由于仅仅是初步认识,因此具体内容并没有进行深度的说明讲解,具体更详细的内容将在之后的博客中单独讲解。


文章目录

  • 什么是C语言
    • 什么是计算机编程语言
    • 什么是底层开发
    • 计算机语言的发展过程
    • 什么是编译器
    • ASCII码表
  • 第一个C语言程序
    • 创建工程 以VS2019为例
    • 主函数
  • 数据类型
    • 不同数据类型的大小
    • 数据类型的输出格式
  • 变量、常量
    • 定义变量的方法
    • 局部变量和全局变量
      • 变量的作用域和生命周期
        • 作用域
        • 生命周期
    • 常量
  • 字符串+转义字符+注释
    • 字符串
    • 转义字符
      • 补齐字符
    • 注释
  • 选择语句
  • 循环语句
  • 函数
  • 数组
    • 数组的定义
    • 数组的使用
  • 操作符
    • 算数操作符
    • 移位操作符
    • 位操作符
    • 赋值操作符
    • 单目操作符
    • 关系操作符
    • 逻辑操作符
    • 条件操作符(三目运算符)
    • 逗号表达式
    • 下标引用、函数调用和结构成员
  • 常见关键字
  • define定义常量和宏
  • 指针
    • 指针的大小
  • 结构体
  • 总结:

什么是C语言

C语言的定义百度不难获取。C语言是一门通用计算机编程语言,广泛应用于底层开发。那什么是计算机编程语言和底层开发呢?

什么是计算机编程语言

计算机语言顾名思义就是人和计算机交流的语言,即人给计算机发送指令,计算机读懂以后按照指令执行我们想要计算机执行的工作。常用的计算机语言有C/C++/JAVA等等。

什么是底层开发

我们常用的电脑(硬件),要让电脑工作就必须要给电脑装一个操作系统,比如win10,linux等,来进行对硬件的操作。操作系统和硬件由驱动层相关联。因此,硬件、驱动和操作系统就叫做底层,所以我们写一个操作系统、驱动软件等这些操作就叫做底层开发

在底层往上就是应用层,即我们能直观感受到的东西,比如应用软件(QQ、微信等)。C语言也可以用于应用软件开发,但是相比其他语言就显得很劣势。
01初识C语言_第1张图片

计算机语言的发展过程

最初的编程语言我们称为机器语言,即二进制的语言,要想实现某一个功能就要写好多二进制的序列。
由于太难理解后来出现了汇编语言,汇编语言用助记符代替机器指令的操作码,我们用助记符就可以更加容易写代码。
后来发展出了更加容易的B语言和C语言,更加贴近我们人的逻辑。但后来由于C语言的标准不统一,这就导致A公司的代码在B公司上就无法运行,因此制定了ANSI C,即C语言国际标准。这些标准约束了C语言的语法规则

什么是编译器

主要的编译器有GCC,MSVC等,编译器就是编译代码的工具,用来将我们写的C代码转换成电脑能读懂的二进制
值得一提的是,我们常用的VS2019,Dev C++严格来讲并不能称为编译器,它们是由编译器组成的集成式开发环境。

ASCII码表

由于计算机中只有二进制数字,一些符号没法表示,例如,像a、b、c、d这样的52个字母(包括大写)以及一些常用的符号(例如*、#、@等),因此约定一套编码来表示这些符号,这就是ASCII表。
01初识C语言_第2张图片

第一个C语言程序

创建工程 以VS2019为例

首先创建项目,然后创建源文件。
01初识C语言_第3张图片01初识C语言_第4张图片01初识C语言_第5张图片这样我们便创建了一个新的C语言文件,接下来就可以写代码了。


主函数

主函数是C语言的程序入口,程序开始执行的位置。一个源文件当中只能有一个主函数,要不然编译器就不知道从哪个入口开始执行了。
主函数代码为

int main()
{
     

   return 0;
}

int是函数返回值的类型,最常用的是整型
main是主函数的函数名
()是函数的参数,由于主函数一般情况下为无参,因此()里面的内容可以为空,
{}里面是主函数的内容
return 0;表示的是函数的返回值

函数的内容以后再做进一步讲解,在此只需要简单认识即可。

比如我们要在屏幕上输出打印“hello world”这一行语句,我们就可以运用打印函数printf,它的具体用法是printf(“要输出的内容”)。
但是printf是C语言提供的库函数,我们在使用之前得先打声招呼,即要引用库函数的头文件,即,#include,stido翻译为标准输入输出。我们的输入和输出函数都在这个头文件里面,每次要使用这些函数都要引用这个头文件。
因此我们的代码就是下面这样的:

#include
int main()
{
     
   printf("hello world");
   return 0;
}

运行的结果是这样的:
01初识C语言_第6张图片如此一来,我们的第一个C语言程序就写好了。


数据类型

我们在对一件事物的描述需要各种各样的数据,比如价格、体重等描述就要用到整数、小数等数据类型。因此C语言中引入了这些类型

char      //字符数据类型,比如a、b、c、!等字符 
short      //短整型                用来描述范围更小的整数
int         //整形                用来描述整数      
long        //长整型               用来描述范围更大的整数     
long long   //更长的整形            用来描述范围更大的整数    
float       //单精度浮点数        用来描述小数
double      //双精度浮点数       比float精度更高

不同数据类型的大小

在计算不同数据类型大小之前首先要清楚计算机中的单位:

计算机中最小的单位为bit(比特),即存放一个1或者0的空间。计算机是一个硬件,通电后,可以识别电信号,0和1代表两种逻辑状态,1代表电路连通状态,0代表电路断开状态;存放一个0或者1的空间大小为1个比特位。

计算机在存储数据和执行指令的时候是以8个"比特"为单位的,通常又叫做"字节"。

一字节等于8比特。也就是说一个字节可以存储8个二进制(0或1)的数据

拿整型(整数)举例,通常整型的大小是4个字节,也就是32个比特位,因此如果要存储一个整型数据数字5,那么它的内存状态是这样的:
在这里插入图片描述

从右向左,每个1依次代表2^0, 2^1, 2^2,… …2^31,而5用二进制表示为 2^2 + 2^0

如果给5加上1变为6,由于二进制逢二进一,因此最末位变为0,倒数第二位变为1
在这里插入图片描述以上就是比特和字节的概念。


另外,字节往上还有更大的存储单位,具体如下:

1字节(Byte)=8位(bit)
1KB( Kilobyte,千字节)=1024B
1MB( Megabyte,兆字节)=1024KB
1GB( Gigabyte,吉字节,千兆)=1024MB
1TB( Trillionbyte,万亿字节,太字节)=1024GB
1PB( Petabyte,千万亿字节,拍字节)=1024TB
1EB( Exabyte,百亿亿字节,艾字节)=1024PB
1ZB(Zettabyte,十万亿亿字节,泽字节)=1024EB
1YB( Yottabyte,一亿亿亿字节,尧字节)=1024ZB
1BB( Brontobyte,千亿亿亿字节)=1024YB


我们可以用sizeof这一求大小的操作符来计算不同数据类型在内存中所占空间的大小,单位是字节
01初识C语言_第7张图片

可以看出,不同的整形和浮点型所占空间大小是不同的。我们可以使用不同整形和浮点型,防止空间浪费。比如short型的二进制换算成十进制,可以表示的范围是-32768~32767,int范围是-2147483648 ~2147483647,因此在描述年龄等较小的数据时,选择short型可以很好地节约空间。单精度浮点数在机内占4个字节,双精度浮点数在机内占8个字节。单精度浮点数有效数字8位,双精度浮点数有效数字16位。在使用浮点型时也可以使用不同的类型来节约内存。

数据类型的输出格式

不同的数据类型有不同的输出格式

    %d-打印整形
    %c-打印字符
    %f-打印浮点型-小数
    %p-以地址形式打印
    %x-打印16进制数字
    %s-打印字符串

不同的类型可以用多种格式打印
比如

int main()
{
     
   int a=32;
   printf("%x",a);//结果为20
   return 0; 
}

%x是16进制输出,因此在打印输出时,会将a转换为16进制再进行输出。

变量、常量

顾名思义,常量就是不能改变的量,在生活中常量有很多,比如圆周率、身份号码等。
变量就是值可以改变的量,比如体重、年龄等。

定义变量的方法

在C语言中,我们一般用数据类型+变量名+赋值操作符(=)+变量的值这种形式来定义一个变量。比如我们要定义一个整形变量age,它的值为10,我们就可以用以下方法:

int age=10;//age值为10,但由于age是变量,因此age的值可以被重新赋值
age=11;//此时age的值变为11

同理要定义一个浮点型变量weight和字符型变量ch,也是如此:

float weight=45.5;
char ch='w';

特别说明一下:

在C语言中,=并不是我们数学中的等号,而是一个赋值操作符,int age=10意为,定义一个整形变量age,将10赋值给age,此时age的值就是10。这个过程我们称为给age赋初值,如果不给age赋初值,age将无法使用,因为编译器也不知道age的值是多少。

当然也可以先定义一个变量age,然后再给age赋初值,不用一步进行

int age=10;

int age;
age=10

以上两个操作是等价的。

而在C语言中,等号为‘==’,即两个赋值操作符。
另外,对于单个字符,一般用单引号‘ ’,比如‘a’,‘b’,对于字符串,一般使用双引号“ ”,比如“hello world”。

局部变量和全局变量

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

全局变量:定义在代码块 ({})之外的变量
局部变量:定义在代码块 ({})之内的变量

int g=100;//全局变量

void test()//定义一个函数,以后会具体说明
{
     
  int b=100;//局部变量
}

int main()
{
     
   int a=10;//局部变量
   
   return 0;
} 

特别说明:

全局变量与局部变量名相同,局部变量优先。
虽然全局变量与局部变量名字可以相同,但是在写代码过程中不建议相同,因为会造成不必要的错误

int a=100;//全局变量
int main()
{
     
   int a=10;//局部变量
   printf("%d",a);// 局部变量优先,结果为10
   return 0;
} 

变量的作用域和生命周期

作用域

作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用
的。限定这个名字的可用性的代码范围就是这个名字的作用域。
一句话来讲就是一个变量的可用的范围。

局部变量的作用域是变量所在的局部范围
全局变量的作用域是整个工程

举一个例子:

int b=20;
int main()
{
     
  int c=30;
  
   {
     
    int a=10;
   }
   printf("a=%d",a);//打印会报错 无法打印输出
   printf("b=%d",b);//可以打印输出

  {
     
         printf("c=%d",c);//可以打印输出
  }
   return 0;
}

a是局部变量,a的定义范围是a所在的那个{},它的作用域就是它所在的{},出了{}以后a就不能使用了。
b是全局变量,作用域是整个工程,因此b的作用域并不受{}的限制。
c的是局部变量,c的作用域是整个main函数所在的范围,由于 printf(“c=%d”,c);所在的{}也属于main函数所在的范围,因此可以打印输出。

生命周期

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。如果变量不销毁,那么每次我们运行都要开辟一块空间来存放我们的变量,那么我们的内存早就用完了,因此变量存在生命周期也是合情合理。

  1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  2. 全局变量的生命周期是:整个程序的生命周期,即从程序开始到程序结束。

特别说明一点:

全局变量能够在不同源文件中使用,但要用extern声明其为外部变量

比如我们在要test中使用test1中的变量a
01初识C语言_第8张图片
如果未使用extern声明则会报错
01初识C语言_第9张图片
如果声明后则不会报错
01初识C语言_第10张图片

常量

C语言中常量分为以下几种:

  • 字面常量
    程序中出现的数字,字符等。
#include
int main()
{
     
	int a = 10;
	char b = 'w';

	return 0;
}

10和w就是字面常量。

  • const 修饰的常变量(无法修改的变量称为常变量)
int main()
{
     
	const int a = 10;

	return 0;
}

const修饰的常变量无法修改,比如下面的程序

#include
int main()
{
     
	const int a = 10;
	a = 20;

	return 0;
}

01初识C语言_第11张图片

虽然const修饰的变量无法修改,但它本身还是一个变量,具有变量的属性。我们可以通过a是否可以作为数组的大小来验证这一问题。

01初识C语言_第12张图片
可以看出a此时还是一个变量。

  • #define 定义的标识符常量

这种定义方式相当于给字面常量起别名,它的别名具有字面常量的属性,在使用时别名直接替换为字面常量,比如下面的代码。

#include
#define a 10
int main()
{
     
	int arr[a] = {
      0 };//相当于int arr[10] = { 0 };
	a=20;//无法修改,因为a具有字面常量的属性;
	return 0;
}

01初识C语言_第13张图片

  • 枚举常量

通过枚举关键字enum定义的常量;

在此不作过多介绍

字符串+转义字符+注释

字符串

C语言中由双引号引起的一串字符叫做字符串。
注:字符串相当于多个字符连续存放在内存中,但是字符串的结尾是一个隐藏的 \0 转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
\0对于字符串非常重要,比如下面的代码:

int main()
{
     
    char arr1[] = "abc";
    char arr2[] = {
     'a', 'b', 'c'};
    char arr3[] = {
     'a', 'b', 'c''\0'};
    printf("%s\n", arr1);//abc
    printf("%s\n", arr2);//abc和乱码
    printf("%s\n", arr3);//abc
    return 0;
 }

01初识C语言_第14张图片

从监视中不难看出arr1在结尾处比arr2多了一个\0,而arr1和arr3是一样的。
arr1字符串后面有一个隐藏的\0 ,因此在打印输出时,遇到\0后,打印停止。
arr2字符串后面没有\0,因此在打印完abc以后还会继续打印,直到遇到\0才会停止。
arr3字符串有\0,遇到\0后,打印停止。

转义字符

转义字符顾名思义就是转变原来含义的意思。比如每次我们在printf打印时加入一个换行符\n,程序输出完以后就会自动换行,而不是输出\n。

转义字符 释义
\? 在书写连续多个问号时使用,防止他们被解析成三字母词
\ ’ 用于表示字符常量’
\“ 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a 警告字符,蜂鸣
\b 退格符
\f 进纸符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd ddd表示1~3个八进制的数字
\xdd dd表示2个十六进制数字

比如下面的程序:

#include 
#include
int main()
{
     
    // \32被解析成一个转义字符
    //\32  32是2个8进制数字
    //32作为8进制代表的十进制数字的ASCII码值对应的字符
    //100先转化为10进制为64,然后将64转化为ASCII码值代表的字符
    printf("%d\n", strlen("c:\test\100\test.c"));//结果为13
    return 0; 
    }

strlen这个函数可以求字符串的长度,在这里\t和\100都是一个字符,因此一共有13个字符,输出结果为13。\t是水平制表符算作一个字符可以理解,那为什么\100也是一个字符呢?
实际上\100属于上述转移字符中的 \ddd类型,100是一个八进制的数字,编译器先将100转化成十进制也就是64,在找到64从ASCII码表中代表的字符,\100就相当于那个字符。
01初识C语言_第15张图片

补齐字符

int main()
{
     
	int a = 123;
	int b = 1;
	printf("%3d\n%3d\n", a, b);//%3d是右对齐,如果输出的位数不够三位,就会补空格
    printf("%3d\n%-3d\n", a, b);//%-3d是左对齐
}

结果是这样:
01初识C语言_第16张图片

注释

  1. 代码中有不需要的代码可以直接删除,也可以注释掉
  2. 代码中有些代码比较难懂,可以加一下注释文字
    比如:
#include 
int Add(int x, int y) 
{
     
    return x+y; }
/*
int Sub(int x, int y)
{
    return x-y;
}
*/
int main()
{
     
    //int a = 10;
    //调用Add函数,完成加法
    printf("%d\n", Add(1, 2));
    return 0;
 }

注释有两种风格:

  • C语言风格的注释 /xxxxxx/
    • 缺陷:不能嵌套注释
  • C++风格的注释 //xxxxxxxx
    • 可以注释一行也可以注释多行

选择语句

顾名思义,就是根据不同的条件选择性地执行不同的语句。比如下面的程序;

#include 
int main()
{
     
    int coding = 0;
    printf("1+1=?>");
    scanf("%d", &coding);
    if(coding == 2)
   {
     
       prinf("回答正确\n");
   }
    else
   {
     
       printf("回答错误\n");
   }
    return 0;
  }

如果if里面的条件成立,就会执行if语句里面的代码,如果不成立,则执行else里面的代码。

循环语句

当条件成立,就会不断执行循环语句中的内容,直到条件不成立,跳出循环。

C语言中实现循环的方式:

  • while语句
  • for语句
  • do … while语句

由于只是初识C语言,因此在这里只挑while循环来说明:

//while循环的实例
#include 
int main()
{
     
    int line = 0;
    while(line<20000)
   {
     
        line++;
        printf("hello world\n");
   }
    return 0;
 }

当line等于20000时,会跳出循环,因此屏幕上会打印20000行hello world。

函数

当一个动作(比如两个数相加,相减)不断执行的时候,我们就可以将这个动作写成一个函数,在需要执行这个动作的时候,只需调用函数就可以,以此来简化代码。比如一个加法的函数:

#include 
int Add(int x, int y)
{
     
  int z = x+y;
  return z;
 }
int main()
{
     
   int num1 = 0;
  int num2 = 0;
   int sum = 0;
   printf("输入两个操作数:>");
   scanf("%d %d", &num1, &num2);
   sum = Add(num1, num2);//将num1,num2的值传给函数中的x,y
   printf("sum = %d\n", sum);
   return 0; 
 }

由于是初识C语言,因此只需对函数进行简单的了解即可。

数组

数组就是一组相同类型元素的集合,用来存放多个相同类型的元素

数组的定义

int arr[10] = {
     1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个整形元素

int 是数组的类型;arr是数组的名字;[10]是数组的大小,数组的大小也可以不写,编译器会自动识别数组的大小;{ }内是数组的每个元素。

数组的使用

#include 
int main()
{
     
 int i = 0;
 int arr[10] = {
     1,2,3,4,5,6,7,8,9,10};
 for(i=0; i<10; i++)
 {
     
       printf("%d ", arr[i]);//用循环的方式打印数组中的每个元素
 }
 printf("\n");
    return 0;
 }

强调一点:要访问数组的元素,就要用到数组的下标,比如arr[i]中,i就是数组的下标。数组下标是从0开始的整数,因此数组的第一个元素的下标元素为0而不是1。以此类推,第二个元素的下标为1,第三个元素下标为2 … …

操作符

顾名思义就是对变量进行操作的符号,比如加减乘除等,在此仅做简单的介绍。

算数操作符

+ - * / %   加 减 乘 除 取模(即求一个数除以另一个所得到的余数)

移位操作符

>> <<    左移和右移
  • 位移操作符移动的是变量的二进制位而不是十进制位

左移操作符<<将二进制位的位数向左移动,移动以后移出位丢弃,右边补0,比如将数字1进行左移一位。

int main()
{
     
    int a = 1;
    int b = a << 1;
    printf("%d", b);

    return 0;
}

01初识C语言_第17张图片
01初识C语言_第18张图片

右移运算是将一个数的二进制位的位数向右移动,移出位被丢弃,左边移出的空位或者一律补0,或者补符号位,这由不同的机器而定。

左移和右移并不会改变变量本身的大小。

01初识C语言_第19张图片
a还是原来的a,本身的值并没有改变

位操作符

&  |  ^   与运算  或运算  异或运算

对二进制位进行运算;& 两个位都为1时,结果才为1,其余情况全为0;| 两个位都为0时,结果才为0,其余情况全为1;^ 两个位相同为0,相异为1

比如将5和3进行与运算:
01初识C语言_第20张图片
01初识C语言_第21张图片

赋值操作符

=   +=   -=    *=   /=    &=    ^=    |=      >>=      <<=

= 将右边的值赋值给左边
+=对原本的操作进行了简化, a+=1 等价于 a=a+1 只是a+=1更简便一些, 其他操作符也是同理

单目操作符

!           逻辑反操作(将真变为假,假变为真,非0的数都是真,0为假)
-           负值
+           正值
&           取地址(与指针配合使用)
sizeof      操作数的类型长度(求数组的大小,单位是字节)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
 (类型)       强制类型转换,将一个类型强制转换成另一个类型

这里单独说一下前置++和后置++,前置- -和后置- -也是同样的道理

++在前,先自加1,再使用
++在后,先使用,再自加1

01初识C语言_第22张图片
a先自加1,再将自己的值赋值给b
01初识C语言_第23张图片
a先将自己的值赋值给b,再自加1

关系操作符

>    //大于
>=    //大于等于
<     //小于
<=     //小于等于
!=    // “不相等”
==    //“相等”

逻辑操作符

&&        逻辑与   所有表达式都为真(非0),那整体就为真(1),否则为假(0||        逻辑或   所有表达式有一个为真(非0),那么整体就为真(1),只有所有表达式都为假时整体才为假(0

01初识C语言_第24张图片

条件操作符(三目运算符)

exp1 ? exp2 : exp3    如果表达式1的值为真,整体的值就是表达式2,如果表达式1的值为假,整体的值就是表达式3

01初识C语言_第25张图片

逗号表达式

exp1, exp2, exp3, …expN  每个表达式从左向右依次进行计算,
整个表达式的结果是最后一个表达式计算结束的结果
#include
int main()
{
     
	int a = 1;
	int b = 3;
	a = (b = a + 1, a = b + 1,b= a + b);
	//先计算a+1的值然后将其赋值给b,此时b的值为2,a的值为1;
	//再计算b+1的值然后将其赋值给a,此时a的值为3,b的值为2;
	//最后计算a+b的值并将结果赋值给b,此时b的值为5
	//整体表达式的结果就是最后一个表达式的结果,最后一个表达式的结果为5,因此整体表达式结果为5
	printf("%d", a);
	return 0;
}

01初识C语言_第26张图片

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

[]    用来访问数组中的成员,如arr[1]就是访问数组的第二个成员(数组的下标从0开始)
()    用来调用函数时给函数传参
.     用来访问结构体成员
 ->   用来通过指针访问结构体成员

常见关键字

C语言内置的关键字。只需初步了解即可。另外记住,变量名不能和关键字相同,要不然编译器无法区分关键字和变量名。

auto--自动  局部变量都是自动变量 但在编译器auto省略
break--循环中停止循环 switch选择语句中结束语句
case--switch语句中进行选择
char
const--常变量   
continue--继续,运用在循环中 
default--默认,用在switch选择中使用 
do   
double 
else  --条件语句中使用
enum --枚举 
extern--引入外部负号
float--单精度浮点数
for   
goto  
if --条件语句中使用  
int   
long  
register--寄存器关键字,建议将变量定义为寄存器变量
return   
short  
signed--有符号数,
signed intint 等价
sizeof   
static--静态的 1.修饰局部变量,生命周期变长-静态局部变量 2.修饰全局变量,改变变量的作用域,使变量只能作用在自己所在的源文件使用,出了源文件将无法使用-静态全局变量 3.修饰函数,改变函数的链接属性,普通函数具有外部链接属性(外部文件想使用该函数只需声明即可),被static修饰后变成内部链接属性-静态函数
struct--结构体关键字  
switch  
typedef--类型定义--类型重定义(起别名)
unsigned int u_int
union--联合体(共用体)  
unsigned--无符号数
void  volatile  while
  • auto
    auto意为自动的,局部变量又叫自动变量,自动创建和销毁,局部变量前都有auto修饰,但省略不写;
  • signed
    意为有符号数,int 和 signed int 是等价的,int本身就是有符号整形
  • unsigned
    意为无符号数 ,unsigned int没有符号,也就意味着没有负数
  • typedef
    类型重定义
    给类型重新起名字,用于简化代码,具体用法为

typedef 原来的名字 新的名字

比如:

int main()
{
     
     typedef unsigned int u_int;
     unsigned int num1=20;
     u_int num2=20;//num1和num2等价
}
  • static关键字
    1.用来修饰局部变量,使其成为静态局部变量

static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,
生命周期才结束。

比如下面的代码

#include 
void test()
{
     
    //static修饰局部变量
    static int i = 0;
    i++;
    printf("%d ", i);
}
int main()
{
     
 int i = 0;
    for(i=0; i<10; i++)
   {
     
        test();
   }
    return 0; }

结果为:
01初识C语言_第27张图片

test函数中的局部变量i在test函数运行结束后并没有被销毁,每次调用test函数都会使i自增。

为了更清晰地对比,我们可以观察把static去掉以后程序的运行结果

#include 
void test()
{
     
	//static修饰局部变量
	int i = 0;
	i++;
	printf("%d ", i);
}
int main()
{
     
	int i = 0;
	for (i = 0; i < 10; i++)
	{
     
		test();
	}
	return 0;
}

01初识C语言_第28张图片

  • static 修饰全局变量

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

我们在变量的作用域和生命周期那里已经了解到了,全局变量可以使用关键字extern从而使其能够在其他文件中被使用,但一旦被static修饰,则无法被使用

01初识C语言_第29张图片
01初识C语言_第30张图片

  • static修饰函数

一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。

效果与static修饰全局变量类似

define定义常量和宏

具体方式

#defne 宏名(被替换的内容)(要替换的内容)

//define定义标识符常量
#define MAX 1000//在程序中,只要遇到MAX,都会被替换为1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include 
int main()
{
     
    printf("%d\n", MAX);
    int sum = ADD(2, 3);//会将2,3与宏中的x,y进行替换,因此ADD(2,3)就相当于((2)+(3))
    printf("sum = %d\n", sum);
    sum = 10*ADD(2, 3);//10*ADD(2,3)就相当于10*((2)+(3))
    printf("sum = %d\n", sum);
    return 0;
 }

01初识C语言_第31张图片

指针

要理解指针,首先要理解内存。我们电脑的内存都被划分为很小的内存单元,并给每个内存单元都进行编号,这个编号就是内存的地址。那内存地址是如何产生的呢?

以32位举例,32位有32根地址线/数据线,地址线一旦通电就会有正电(1)和负电(0);通电后电信号转化为数字信号,因此有2^32 个二进制序列,将这些序列作为每个内存单元的编号,就会产生2^32个内存单元,每个内存单元的大小为一个字节

01初识C语言_第32张图片
指针就是存储地址的一个变量,比如:

int num = 10;
int *p;//p为一个整形指针变量
p = &num;

&操作符可以将num的地址取出,然后赋值给指针p。
但我们知道num占四个字节,因此它有四个地址,&取出的是num的起始位置地址。

指针的使用实例:

#include 
int main()
{
     
 int num = 10;
 int *p = &num;
 *p = 20;//*是解引用操作符,*p是通过p找到p指向的对象,即num
    return 0;
}

*是解引用操作符,*p是通过p找到p指向的对象,即num

p也是一个指针变量,它也有地址。
01初识C语言_第33张图片

指针的大小

#include 
int main()
{
     
    printf("%d\n", sizeof(char *));//4
    printf("%d\n", sizeof(short *));//4
    printf("%d\n", sizeof(int *));//4
    printf("%d\n", sizeof(double *));//4
    return 0; 
}

可以得出结论:指针大小在32位平台是4个字节,64位平台是8个字节。

结构体

有的对象是非常复杂的,比如要表示一个人,他有名字、身高、体重等信息,想要描述这个人,仅仅使用单一的变量是很难做到的,因此结构体就是我们创造出来的一个类型,用来描述一个复杂的对象。比如要描述一个人:

struct Stu
{
     
    char name[20];//名字
    int age;      //年龄
    char sex[5];  //性别
    char id[15]//学号
};
int main()
{
     
struct Stu s = {
     "张三"20"男""20180101"};//创建一个学生s,并对其进行初始化赋值
//.为结构成员访问操作符,能够访问结构体的成员
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//创建一个结构体指针,用来存放s的地址
struct Stu *ps = &s;
//->操作符可以通过指针来访问到结构体的具体成员
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps- >id);
}

我们通过结构体创建一个学生s,并对其进行初始化操作,此时我们可以通过点操作符.来访问结构体具体的成员,具体语法为:结构体变量名.结构体具体内容,比如s.name
我们也可以创建结构体指针来指向s,并通过箭头操作符->来通过结构体指针来访问结构体成员,具体语法为结构体指针->结构体内容,比如ps->name


总结:

这篇博客带大家了解了C语言的基本语法内容,对于刚刚入门的萌新来讲,相信这些内容会让其更加了解C语言。另外,这只是C语言的一点基础内容,更深入的内容我会在后续博客中展开讲解。
当然,这篇博客肯定还有可以完善的地方,如果有错误的地方请在评论区指正,非常感谢!另外,如果有更好的建议,也欢迎在评论区提出。我会进行博客的完善和修改。

你可能感兴趣的:(C语言从入门到进阶,c语言)