快速上手c语言

快速上手c语言

  • 快速上手c语言
    • 关于学c语言的一些信息杂谈
    • 第一个C语言程序
      • 通过命令行运行c程序
      • Dev-c++5.11
      • Visual Studio系列产品
    • 数据类型
    • 变量、常量
      • 定义变量的方法
      • 变量的命名
      • 变量的分类
      • 变量的使用
      • 变量的作用域和生命周期
      • 常量
    • 操作符简单介绍
    • 语句
      • 选择语句
      • 循环语句
    • 数组
      • 数组定义
      • 数组的下标
      • 数组简单使用
      • 变长数组的概念
    • 字符串和转义字符
      • 字符串
      • 转义字符
    • 注释
    • 函数
      • 关于scanf的返回值
    • 常见关键字
    • #define 定义常量和宏
    • 指针
      • 内存
      • 地址的产生(可跳过)
      • 变量的地址
    • 结构体

快速上手c语言

在看懂c语言的基础上,再学会如何使用。

同理,在学会使用c语言的基础上,再进行语法和细节上的拓展。

因此本篇的目的是基本了解C语言的基础知识,对C语言有一个大概的认识。

每个知识点就是简单认识,不做详细讲解,后期会进行补充。

关于学c语言的一些信息杂谈

仅为个人平时听别人说话总结的东西,可跳过:

  1. 开始学c,都是先从简单概念介绍编译环境的搭建开始,会用就行,用熟后再学内部的东西。学其他编程语言(也可以是交流的语言)也是这样。
  2. 写博客是表示你愿意向其他人分享知识,同时也是知识点的总结,写其他博客也一样。在面试时可以加深面试官的印象。
  3. 写完的代码可以上传git。git可以是gitee(国内),也可以是githup(国外)。一般用gitee就够,也可以用githup。这个也是可以在面试时加印象分。
  4. 语言,我暂时理解为两个或多个对象之间的交流。比如人与人交流可以通过汉语、英语等。相对应的,人与计算机交流可以通过c语言、c++、Java等程序设计语言和开发环境。
  5. 学好编程不仅是学好c语言,这些都可以提升编程的能力,推荐去学:
    • 计算机语言,推荐学完c语言和一门面向对象的语言(比如c++)后再去学其他语言,会有全新的认识。
    • 算法和数据结构。
    • 操作系统。
    • 计算机网络。
    • 项目实战。
    • 数据库-MySQL。
  6. c语言广泛用于底层开发。比如,一个电脑刚买来的时候是一个硬件(称之为里面装有电路板的方块更恰当),这个硬件装了操作系统比如windows 10,Linux等。
    操作系统之上的称之为上层软件。这里用一张图大致描绘电脑的结构:
    请添加图片描述

c语言更擅长做底层软件开发,在嵌入式开发、单片机开发中应用广泛,但c语言也可以做上层软件。其中Linux内核就是用c语言写出来的(不懂没关系,以后会懂)。

  1. 计算机语言的发展:
    请添加图片描述

  2. 编程可以狭义的称之为写代码。写代码是为了利用计算机解决生活中的问题。

  3. c语言诞生的时候,c语言在不同人(公司)手上各自设有自己的标准。这就使得
    A公司写的代码无法在B公司用。于是C语言的国际标准统一,也就是出现统一的标准。
    ANSI C是最早的标准,当时称它为C89,后来不断根据需求增添和修改功能。目前的习惯是在C后面加年份的最后2位来指代这个标准。
    C11之前的标准都是在20世纪末发布,C11是2011发布的最新标准。

请添加图片描述

  1. c语言还需要通过编译器翻译成计算机看的懂的语言,计算机才能去做事。
    常见的c语言编译器:

    • Microsoft Visual Studio系列(简称vs),推荐使用vs2019,版本太旧会出现BUG或版本不兼容,太新的话微软公司做的封装太严实,不利于新人学习c语言。
      vs用的编译器是MSVC。
      vs集结编辑器、编译器、调试器和别的东西,集结写源代码文本、编译和运行为一体,称这种大成集合体为集成开发环境。英文缩写:IDE。
      类似的产品还有Visual Studio Code(简称vscode)只是用来写代码的编辑器,需要装很多插件才能用。
    • Linux平台下的gcc。windows也有gcc,主要是Dev-c++和vscode用。
    • 苹果维护的clang。
  2. c语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

  3. 尽管c语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的c语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。

  4. 二十世纪八十年代,为了避免各开发厂商用的c语言语法产生差异,由美国国家标准局为c语言制定了一套完整的美国国家标准语法,称为ANSI C,作为c语言最初的标准。 2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是c语言的第三个官方标准,也是c语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

  5. C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
    我的c语言和c++的学习主要的环境是GCC(为方便我会写成gcc)和MSVC(为方便我会写成vs或vs2019)。

  6. 推荐书籍:

    • 初学c语言和初学c++阶段:
      《C和指针》
      《高质量的C/C++编程指南》
      《C语言深度剖析》
      《数据结构》严蔚敏(c语言版)殷人昆(c++版)
      《程序员的自我修养》
      《C陷阱与缺陷》

    • 对c++有一定认识之后:
      《Effective C++》(中文版 第3版)
      《STL源码剖析》

    • 对操作系统,特别是Linux操作系统有一定了解之后:
      《现代操作系统》(第4版)
      《Unix环境高级编程》
      《图解HTTP》
      《图解TCP/IP》

    • 关于数据结构和算法:
      《数据结构》严蔚敏(c语言版)殷人昆(c++版)

      《漫画算法》

    • 其他:
      《知识大迁移》

    仅为个人理解,可能有安排不合理的地方,如何选择看自己。

  7. bug,英语的名词,翻译成虫子、飞蛾等。因为第一个计算机故障由虫子引起(指虫子死后损坏晶体管),它便成了故障的代言词。
    调试是debug,指排除程序的故障和不符合预期的地方。

第一个C语言程序

通过命令行运行c程序

新建一个拓展名为.txt的文件,在里面写上c语言的程序:

#include <stdio.h>
int main()
{printf("hello bit\n");printf("he he\n");return 0;
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个

之后将拓展名改为.c即可。.c是c语言的代码文本文件,.cpp是c++的代码文本文件。c++的代码文本文件可以运行c语言的,反过来却不行,因为c++是在c语言的基础上进行补充。

这个程序是打印hello bit\nhe he\n在什么地方。\n是换行的意思。

安装minGW-64,并配置环境变量。
请添加图片描述

之后只需在cmd中将目录切换到源码所在的目录,输入命令gcc name.c -o name.exe即可生成可执行程序(在>后输入)。运行可执行程序,输入程序的名称即可。

请添加图片描述

c语言的代码都是从main函数的第一行开始执行。一个c程序背后的源码有且只有一个main函数。

printf是一个库函数,即c语言的标准库中提供的一个线程的函数,可以直接用。它的功能是在终端控制台上打印信息。在使用printf之前一定要包含头文件stdio.h

stdio.h是标准输入输出头文件(standard,in,out三个部分组成)。关于头文件的本质,点击这里。

main函数还有其他的写法。

void main(){}

古老的写法,现在大家都不这么写。

int main(void){}

void 表示main不接受参数,可以这样写。

int main(int argc, char* argv[]){}

argc:保存命令行字符串个数
argv:指针数组,每个成员都是指针(argv[0] argv[1] argv[2] …),用于成员指向命令行各字符串的首地址。

例如下面的代码会将所有命令全部打印。

#include<stdio.h>int main(int argc,char* argv[]){int i=0;for(i=0;i<argc;i++){printf("%s\n",argv[i]);}return 0;
} 

但目前我用的编译器都是只打印一个调用最新生成的.exe的命令。

这些操作也可以在vscode界面使用。详细见vscode-CSDN博客。

Dev-c++5.11

Dev-c++5.11将命令行简化成了一个或两个按钮。只需点击这个按钮即可运行。
请添加图片描述

也可以按快捷键F11,Dev会自动帮我们完成输入命令的过程。
请添加图片描述

若出现某些语法不可用的情况,则可通过在编译选项中添加命令修改编译器的语言标准:
请添加图片描述

Visual Studio系列产品

vs系列产品我更推荐vs2019和vscode。

这两个软件最大的特色是调试方便。现在也有很多集成开发环境(IDE)也能做到,取决于个人需求。在初学阶段,社区版已经能满足绝大多数需求。

我不喜欢用vs2022这个新版本的IDE,是因为新版本做了更加严密的封装,在反汇编和特殊情况的编译下会做出多余的行动。当然我并不是否定vs2022的功能,vs2022也有自己的特色。

vs的编辑界面,解决方案资源管理器

请添加图片描述

在vs的安装路径中找到

Microsoft Visual Studio\2019\Community\Common7\IDE\VC\VCProjectItems

在其中有一个newc++file.cpp,这个是vs2019生成新的c++文件的模版。我们可以在外取一个同名的.cpp文件,之后在里面添加各种我们想要的初始语句,之后再拷贝到这个路径进行替换即可(这个路径可能无法修改)。

请添加图片描述

例如我们加上一句#define _CRT_SECURE_NO_WARNINGS 1,之后在使用vs时用这个模版生成的新文件中会带有这样一个语句。

请添加图片描述

生成的默认文件就会带有这样一句:

请添加图片描述

请添加图片描述

vs也可以更换

数据类型

c语言的使用方式是将现实问题转化为能用数据和数据之间的关系模拟的抽象模型。所以学习使用c语言(甚至是其他编程语言)都绕不开用于表示数据的变量和常量。

c语言的数据类型在c++又有另外的别称:内置类型。

char        //字符数据类型
short       //短整型
int         //整形
long        //长整型
long long   //更长的整形
float       //单精度浮点数
double      //双精度浮点数
//C语言没有字符串类型

案例:

#include <stdio.h>
int main()
{printf("%d\n", sizeof(char));printf("%d\n", sizeof(short));printf("%d\n", sizeof(int));printf("%d\n", sizeof(long));printf("%d\n", sizeof(long long));printf("%d\n", sizeof(float));printf("%d\n", sizeof(double));printf("%d\n", sizeof(long double));//类型的使用char ch='w';return 0;
}
  • sizeof()是一个操作符,可以返回括号内的数据占用的内存大小。

  • printf函数用于打印信息在控制台,%d是指定打印的格式,sizeof(type)是被打印的对象。

  • char ch='w';的意思是向内存申请大小为sizeof(char)的空间来存放字符w。字符用单引号''引起来。

关于计算机存储单位,我们知道计算机能完成这么庞大的运算,离不开底层大量的0和1的支持。

计算机只能看懂二进制,编译器的工作就是将人写的代码转变成二进制。

存放一个0或一个1所需的空间称之为1 bit(1位)。

单位转换:

1byte=8bit (1字节 = 8位)
1kB=2^10byte=1024byte
1MB=1024kB
1GB=1024MB
1TB=1024GB
1PB=1024TB

c语言的标准中,sizeof(long) ≥ \geq sizeof(int)long占用字节数的大小取决于编译器的版本。

变量、常量

生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)

有些值是可变的(比如:年龄,体重,薪资)。

不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。

定义变量的方法

//定义变量的格式:类型 变量名=初始值;
//例如
int age=18;
//声明变量的格式:类型 变量名;
//例如
float weight=45.10f;

对于这个语句float weight=45.10f;

若采用float weight=45.10;,系统默认45.10是double型,我们希望45.10只是float型的数据,于是在浮点数后面加后缀f

这里声明变量最好先给他赋一个值并养成习惯,直接用没赋值的变量,vs会出错,Dev早期版本会产生随机数。

变量的命名

变量的命名遵循以下规则:

  • 只能由字母(包括大写和小写)、数字和下划线( _ )组成。

  • 不能以数字开头。

  • 长度不能超过63个字符。

  • 变量名中区分大小写的。

  • 变量名不能使用关键字。

其中自己再加上一条:

变量名最好有它自己的意义。

这个只是总结的,其他资料有可能有更详细的,但遵守这个是最普适的。

变量的分类

变量按作用域分可分为全局变量局部变量。作用域暂时可以理解为离变量最近的{}

局部变量是在{}内定义的变量,全局变量是在{}之外定义的变量(狭义的理解),也可以理解为在函数外定义的变量。

#include <stdio.h>
int global = 2019;//全局变量
int main()
{int local = 2018;//局部变量//下面定义的global会不会有问题?int global = 2020;//局部变量printf("global = %d\n", global);return 0;
}

上面的局部变量global变量的定义其实没有什么问题的。

局部变量和全局变量同名的时候,局部变量优先使用。但不可以将两个同一作用域的变量设置为同一个名字,会产生重名的错误。

变量的使用

变量可以当成一个存储数据的容器使用。包括修改、利用变量存储的数据。

#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0;
}

变量的作用域和生命周期

作用域

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

总结以下就是:一个变量,哪里可以用,哪里就是它的作用域

  1. 局部变量的作用域是变量所在的局部范围。(即自己所在的{}内部)

  2. 全局变量的作用域是整个工程。

例如:

#include<stdio>int main(){int a=1;{int b=2;printf("%d\n",b);}printf("%d\n",b);//b不在作用域,不可用return 0;
}

生命周期

变量的生命周期指的是变量的创建到变量的销毁之间的时间段。(比如c程序的生命周期指的是程创建到销毁的时间段)

  1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。

  2. 全局变量的生命周期是:整个程序的生命周期。

一个程序的生命周期与main函数是一样的,而全局变量与main函数也是一样的。

常量

常量即不可修改的量。c语言中的常量和变量的定义的形式有所差异。

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

  • 字面常量。例如int a=10;中的10。

  • const 修饰的常变量。例如const int a=10;中的aa本质上是一个变量,但具有了常属性不可以被改变。)。

  • #define 定义的标识符常量

  • 枚举常量

    枚举,就是一一列举所有可能性,生活中很多东西如性别、血型等情况有限可能。

#include <stdio.h>
//举例
enum Sex
{MALE,FEMALE,SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{//字面常量演示3.14;//字面常量1000;//字面常量//const 修饰的常变量const float pai = 3.14f;   //这里的pai是const修饰的常变量pai = 5.14;//是不能直接修改的!//#define的标识符常量 演示
#define MAX 100printf("max = %d\n", MAX);//枚举常量演示printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);//注:枚举常量的默认是从0开始,依次向下递增1的return 0;
}

上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在c语言中只是在语法层面限制了变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的,所以叫常变量。

const int a=10;,a不可用于定义数组,即int arr[a];int arr[a]={0}不允许。

但总有特例。

在C99标准中引入变长数组的概念,可以使用变量来声明(但不能定义)。

典型的编译器如Dev-C++ 5.11的gcc支持。

大部分网站的OJ题支持c99。

最后,变长数组不能初始化。

操作符简单介绍

有了变量之后,还需要有某种操作来沟通部分或全部的变量,使得变量能真正用于解决问题。例如ab代表两个数字,想用它们解决四则运算,则需要有四则运算符。

因此c语言提供了操作符。在有的资料上,操作符又称为运算符。

算术操作符:用于数学计算的操作符。两边都要有变量、常量或表达式(变量和操作符组成的集合)。

  • +:加法。
  • - :减法。
  • * :乘法。
  • /:除法得到的是商,整型会自动舍弃小数部分,浮点型按精度返回。
  • %:取模(求余数),两个不能是整型,模正负与%前的正负相同。

样例解析:

void f(){float a = 10/3;//等式右边都是整数,a为3.000000float b = 10.0f/3;//或float b = 10/3.0f;
}

形如10.0f,这种是单精度浮点数表示法。我们希望用float存储10.010.0默认为double型。double型的值赋值给float型变量,在vs中会报警告。

赋值操作符,用于修改变量。

  • =:将右边的值赋值给左边的变量。例如int a; a=3;只要不是跟在类型后面用于初始化,都是用于给变量赋值。
  • +=:例如:a+=2;等价于a=a+2;。下同。
  • -=*=/=%=

单目操作符,只和一个操作数(可以是变量,也可以是变量和操作符组成的表示一个值的集合)组合的操作符。

  • &:取地址(详见指针)。
  • sizeof:返回操作数的类型长度(以字节为单位)。例如sizeof(int)就是返回int型变量在计算机中占用的空间的大小。
  • --:分前置和后置。本质是变量=变量-1的缩写,但因前置、后置有不同的执行顺序,前置是优先执行操作数再执行其他部分,后置则是优先执行其他部分再执行操作数。
  • ++:和--同理。本质是变量=变量+1的缩写。
  • *:间接访问操作符(解引用操作符,和指针有关)。
  • (类型):强制类型转换。例如:(char)65=='A')

关系操作符:用于数学意义上的比较操作符。靠返回真和假来判断。

>
>=
<
<=
!=   用于测试“不相等”
==      用于测试“相等”

逻辑操作符:用于组合

&&     逻辑与
||     逻辑或

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

exp1 ? exp2 : exp3
/*
等价于
if(exp1)exp2;
elseexp3;
*/

逗号表达式:从左到右依次计算,返回最后一个表达式expn的值。

exp1, exp2, ...,expn;

下标引用函数调用结构成员访问

  • []:用于表示数组的索引(或下标)。
  • ():有两个含义:1、(表达式)表示这个表达式(暂时理解为语句的一部分)最先执行。2、子程序名(参数清单)表示执行某个子程序(总的程序的一部分。见函数)。
  • .:用于结构体的成员调用(见下方结构体)。
  • ->:用于结构体指针的结构体的成员的调用。

其他的操作符有的都是涉及二进制,放在另一篇详细解释。

语句

变量和操作符进行组合,便完成了一个功能,需要用;结尾,这个用;结尾的代码就是语句。

c语言的代码由语句函数(子程序)组成,而函数的主干部分是语句。这些语句分成普通语句选择语句循环语句。普通语句就是以;结尾的语句。

选择语句

if后面的括号内的表达式如果判断为,则执行if后面的{}内的语句(或{}以及内部语句的代码块),为假则不执行

if没有{},则if会自动匹配离它最近的语句

而且if还能和else if以及else组成多分支。

#include <stdio.h>
int main() {int coding = 0;printf("你会去敲代码吗?(选择0 or 1 or 2):>");scanf("%d", &coding);//单分支if (coding == 2) {//匹配后面的{}printf("三天打鱼两天晒网,啥也不能做,只能\n");}//2个分支if (coding == 1)//匹配最近的语句printf("坚持,你会有好offer\n");else{printf("放弃,回家卖红薯\n");}//3个及以上的分支printf("如果再来一次,你会去敲代码吗?(选择0 or 1 or 2):>");scanf("%d", &coding);if (coding == 2) {//匹配后面的{}printf("三天打鱼两天晒网,啥也不能做\n");}else if (coding == 1)//匹配最近的语句printf("坚持,你会有好offer\n");else {printf("放弃,回家卖红薯\n");}return 0;
}

循环语句

有一部分功能,需要执行很多次,同样地拷贝粘贴会增加代码长度。因此就有了循环语句:通过满足某种条件执行特定的语句或代码块

c语言实现循环的方式有4种:

  • while
  • for
  • do {} while
  • goto

这里只介绍while,详见循环。

while只要满足后面括号内的语句的返回值为真,后面的语句块会一直执行。

#include <stdio.h>
int main()
{int line = 0;while(line<=20000){line++;printf("我要继续努力敲代码\n");}if(line>20000)printf("好offer\n");return 0;
}

数组

既然有了变量,又会有新的问题:有的问题需要大量的变量,这时重复的拷贝粘贴会使代码变得特别长。

c语言中给了数组的定义:一组相同类型元素(变量)的集合。

数组定义

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

数组的下标

C语言规定:数组的每个元素都有一个下标,下标是从0开始的。

数组可以通过下标来访问的。

比如:

int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9

请添加图片描述

数组简单使用

#include <stdio.h>
int main()
{int i = 0;int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };while (i < 10){printf("%d ", arr[i]);i++;}printf("\n");return 0;
}

printf("%d ", arr[i]);的解释:

arr[i]是用于访问下标为i的元素(下标访问操作符[]),将arri结合在一起,让我们访问arr[i]存放的元素。

所以arr和数组中的内容4[]这个操作符的操作数。

变长数组的概念

C99标准之前,数组的大小只能是常量指定。例如:

int a[10];

即使用#define定义符号,在编译阶段也会全部替换回来,本质还是只能常量指定。

在C99标准中,引入一个变长数组的概念。变长数组允许数组的大小使用变量来指定,例如:

void f(){int n = 10;int a[n];
}

大部分网站的OJ题都支持C99。

此外,变长数组不能初始化。也就是说不允许这种写法:

int a[n]={0};

字符串和转义字符

字符串

"Hello, world!\n"这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。c语言表示字符用单引号。例如:'a''2'

字符串是最后一个元素为\0char型数组。

注:字符串的结束标志是一个\0的转义字符,ASCII值为0。在计算字符串长度的时候\0是结束标志,不算作字符串内容。

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{char arr1[] = "bit";//字符串里隐藏一个'\0'char arr2[] = {'b', 'i', 't'};//无'\0',只是将三个字符放进去char arr3[] = {'b', 'i', 't''\0'};printf("%s\n", arr1);printf("%s\n", arr2);printf("%s\n", arr3);return 0;
}

打印结果(不同的设备情况可能不同):

bit
bit烫烫烫烫蘠it
bit

分析:

char arr1[] = "bit";内部结构:

请添加图片描述

char arr2[] = {'b', 'i', 't'};的结尾并不是\0,也就不是字符串。

printf("%s\n", arr1);%s的格式是打印字符串,直到检测到'\0'结束。因arr2内无'\0',系统找不到'\0',则继续访问内存直到找到\0为止。而这个数组存放在内存中,前后都有空间,所以避免不了访问不属于自己的空间。

打印烫的原因:烫字的GBK编码正好都是0xcc

请添加图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>int main()
{char arr4[] = { "烫" };char arr5[] = { "烬" };int i = 0;for (i = 0; i < 2; i++) {printf("%x ", arr4[i]);//十六进制打印}printf("\n");for (i = 0; i < 2; i++) {printf("%x ", arr5[i]);}return 0;
}

p.s. 函数strlen返回值为size_t( #define unsigned int size_t ),但它依旧是以\0为结束标志。所以strlen(arr2)的返回值是随机的(统计\0之前的字符数)。

即使printf("%d",strlen(arr2));成功输出,结果也无代表性。

转义字符

转义,即转变意思的意思。

案例:

#include <stdio.h>
int main()
{printf("c:\code\test.c\n");return 0;
}

输出:

请添加图片描述

这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。

下面看一些可能比较常用的转义字符。

\?

在书写连续多个问号时使用,防止他们被解析成三字母词。

比如:??]就是],在早期的一些编译器会将??]解释成三字母词并转变成其他符号。

\'

用于表示字符常量'

\"

用于表示一个字符串内部的双引号

\\

用于表示一个反斜杠,防止它被解释为一个转义序列符。

\a

警告字符,蜂鸣

\b

退格符。

例如。

#include <stdio.h>
int main()
{int i=0;printf("ab\b");scanf("%d",&i);printf("\n");printf("ab\bc");return 0;
}

第5行输出ab,但光标夹在a、b中间,输入任意数字都会将b给覆盖。

第8行先输出ab,后经过\b退格,使光标夹在a、b中间,再输出c就会将b给覆盖掉。

\f

进纸符

\n

换行

\r

回车。感觉上更像Tab键,推进2~4个字节(空格)的空间。

\t

水平制表符

\v

垂直制表符

\ddd

ddd表示1~3个八进制的数字。 如: \130表示X。

13 0 ( 8 ) = 1 × 8 2 + 3 × 8 1 + 0 = 8 8 ( 10 ) 130_{(8)}=1\times8^2+3\times8^1+0=88_{(10)} 130(8)=1×82+3×81+0=88(10),ASCII码值可知这个符号是X

在计算机中的字符被解释成十进制(详见下方的ASCII码表),每个字符规定一个值。

请添加图片描述

其中\777转换成十进制数则大于127(即ASCII码的最大码值),对字符来说太大,vs会警告。

\xdd

dd表示2个十六进制数字。 如: \x30是字符0

在了解这些转义字符后,再来看这个代码:

#include <stdio.h>
int main()
{//在屏幕上打印一个单引号'printf("%c\n", '\'');//在屏幕上打印一个字符串,字符串的内容是一个双引号“printf("%s\n", "\"");return 0;
}

若第5行这样写:printf("%c\n", ''');,编译器会将前两个'解释成一对,从而使后面的'落单,这样一来编译器反而不能识别这个代码。

三个0的区别:

0: 数字0

'0':字符0,ASCII值为48。

'\0':字符,ASCII值是0。

注释

  1. 代码中有不需要的代码可以直接删除,也可以注释掉。

  2. 代码中有些代码比较难懂,可以加一下注释文字。

可以理解为注释是写给程序员看的,编译器在预编译阶段会将注释删除。

注释有两种风格:

  • c语言风格的注释/*xxxxxx*/

缺陷:不能嵌套注释。

例如,

/*1
/*
*/2
*/3

1和2进行匹配,使得3暴露在外。

  • C++风格的注释//xxxxxxxx

    • 一次只能注释一行。

函数

同样是代码块执行多次,但不能每次都写循环,这样会增加代码的长度,于是就有了函数。

因此函数的作用是代码复写(或者说重复利用)。

#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0;
}

上述代码,写成函数如下:

#include <stdio.h>
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);printf("sum = %d\n", sum);return 0;
}

关于scanf的返回值

例如:

#include<stdio.h>int main(){int a,b;int c;c=scanf("%d %d",&a,&b);return 0;
}

scanf是从键盘上获取数据到变量空间中,若输入成功,则scanf返回成功填充的字符个数。

所以scanf将读到的数据赋值给a后返回1;给ab返回2,即c的值为1或2。

所以scanf的返回值为读到的数据个数。若读取失败则返回EOF也就是-1。

stdio.h给出的定义是

#define EOF (-1)

EOF:end of file,用于文件结束的标志。

scanf读取失败,在控制台输入Ctrl+z即可。部分编译器比如vs可能需要多输入几次。

常见关键字

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

我的打算是学习时遇到一个关键字就做总结,在学完c语言的大部分核心内容之后,再出一篇c语言的关键字的总篇集,方便查询。

c语言的关键字:

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

#define 定义常量和宏

在一篇文章看懂c语言-CSDN博客已经提到#define的作用。这里再介绍一个和函数的功能十分类似的功能,也就是宏。

例如:

//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
int main()
{int sum = ADD(2, 3);sum = 10 * ADD(2, 3);return 0;
}

将这个代码在控制台通过gcc进行预编译即可得到如下结果:

请添加图片描述

#include#define这种#开头的符号称预处理指令,它不是关键字。

关于宏:宏虽然在使用上和函数类似都是代码重用,但毕竟是符号替换,在程序源码编写上存在区别。

宏的不标准写法:#define ADD(x, y) (x+y)。将参数用()括起来可以更准确,防止因为优先级与其他符号产生冲突。

指针

通过指针可以理解变量是如何在内存中存在的。

内存

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

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

为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。这种地址在c/c++中又把他称作指针

为啥不分到最小单位bit?若这样分配,则相当于指定到某房间的第几平米处处理数据(太细不好处理),1个char类型的变量1个字节,再细的话不合理。

很多时候32位的二进制序列太长,我们将他们用十六进制表示。

请添加图片描述

每个内存单元都有自己的编号,编号称做地址,地址又称作指针。

所以编号、地址、指针三个说法是一回事。

地址的产生(可跳过)

当我们在32位机器上,有32根地址线(有物质形态的电线),该电线是通电的,通电后有高、低电平,高、低电平转换成数字信号就是高电平为1和低电平为0(也可以反逻辑即高电平为0和低电平为1)。

这种32位机器表示的32位二进制数能代表 2 32 2^{32} 232种电信号,此时32根电线产生的电信号,转换成数字信号的二进制序列可作为内存编号,通过内存编号可找到对应的内存空间。

所以内存分为一个个内存单元,每个内存单元都对应一个编号,编号由硬件电路产生。

请添加图片描述

一个内存单元是1个字节,这种内存单元可以给出一个地址。能产生 2 32 2^{32} 232个地址(或 2 32 2^{32} 232个二进制序列),即一个32位机器用于记录地址的数据有 2 32 2^{32} 232个,它们能够管理2^{32}byte的空间。

2 32 2^{32} 232byte = 4 =4 =4GB。

在vs界面可发现x86处有一个配置管理器,通过更改配置管理平台,指针变量的地址存储空间会发生变化。

一般 X86 对应 32位(bit),X64 对应 64位(bit)。

变量的地址

#include <stdio.h>
int main()
{int num = 10;&num;//取出num的地址//注:这里num的4个字节,每个字节都有地址,//取出的是第一个字节的地址(较小的地址)printf("%p\n", &num);//打印地址,%p是以地址的形式打印return 0;return 0;
}

请添加图片描述

&num实际占用4byte的空间(X64下是8byte),每个byte都有自己的地址,&num只是取出第1个byte空间的地址。

取出的地址也是十六进制数,也需要内存空间存储,通常用

type* name = &num;

来存储。我们把name称指针变量(存放地址也就是指针的变量),name的类型是type*

*说明name是指针变量,type说明name指向的对象是type类型。*跟随变量还是类型没有具体要求。

指针的使用实例:

#include <stdio.h>
int main()
{int num = 10;int* p = &num;*p = 20;return 0;
}

&num:获得num的地址。&是取地址操作符。

*p*是解引用操作符,解引用是p里存地址,*p就是解引用,它是通过p里的地址找到这个地址指向的变量,对那个变量的存储的数据进行操作。

结构体

结构体是一些具有某种联系的变量、数组等的集合体。尽管不用结构体,将变量单独列出来通过运算也能展示关系。

比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。

就可以用结构体来描述。

struct Stu
{char name[20];//名字int age;//年龄char sex[5];//性别char id[15];//学号
};

复杂类型生成的复杂对象(类似数据类型生成的变量)不能使用单个内置类型来描述。

内置类型即c语言本身就具有的,比如:charshortintlonglong longfloatdouble

struct是自定义类型,并不属于内置类型。

结构体的简单应用:

#include <stdio.h>
struct Stu {char name[20];//名字int age;//年龄char sex[5];//性别char id[15];//学号
};
int main() {//结构体变量的初始化struct Stu s = { "张三",20, "男", "20180101" };//.为结构成员访问操作符printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);//->操作符,用于指针变量struct Stu* ps = &s;printf("name = %s age = %d sex = %s id = %s\n", (*ps).name, ps->age, ps->sex, ps -> id);return 0;
}

ps->name可用(*ps).name代替。即先找到对象,再访问成员。

通常引用成员:

结构体变量.成员

结构体指针->成员

看到这里,对c语言相比有了一个大概的框架。后面都是对某一类知识点做更详细的介绍。全篇下来整合成一篇完全适合小白的书籍完全可以。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx核心功能及正则表达

目录 一&#xff1a;正向代理 1&#xff1a;编译安装nginx &#xff08;1&#xff09;安装支持软件 &#xff08;2&#xff09;创建运行用户、组和日志目录 &#xff08;3&#xff09;编译安装nginx &#xff08;4&#xff09;添加nginx系统服务 2&#xff1a;配置正向代…

npm命令介绍(Node Package Manager)(Node包管理器)

文章目录 npm命令全解析简介基础命令安装npm&#xff08;npm -v检插版本&#xff09;初始化项目&#xff08;npm init&#xff09;安装依赖包&#xff08;npm install xxx、npm i xxx&#xff09;卸载依赖包&#xff08;npm uninstall xxx 或 npm uni xxx、npm remove xxx&…

【Linux】Linux基础概念

一些比较重要的使用Linux的前情提要。 部分经验来源于网络&#xff0c;若有侵权请联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 Shell命令参数 2 系统变量…

阿里开源Qwen3:大语言模型的新突破

一、模型概览&#xff1a;丰富的模型家族 Qwen3 系列包含了 2 款混合专家&#xff08;MoE&#xff09;模型与 6 款密集&#xff08;Dense&#xff09;模型&#xff0c;参数量覆盖范围极广&#xff0c;从 0.6B 一直延伸至 235B 。其中&#xff0c;旗舰模型 Qwen3 - 235B - A22B…

数字智慧方案5856丨智慧环保综合解决方案(50页PPT)(文末有下载方式)

资料解读&#xff1a;智慧环保综合解决方案 详细资料请看本解读文章的最后内容。 随着城市化进程的加速和环境问题的日益严峻&#xff0c;智慧环保成为提升城市环境管理水平的重要手段。本文将对智慧环保综合解决方案进行详细解读&#xff0c;探讨其在实际应用中的需求、解决…

基于ssm的网盘管理系统(全套)

一、系统架构 前端&#xff1a;vue | element-ui 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | tomcat | nodejs 二、代码及数据库 三、功能介绍 01. 注册 02. 登录 03. 管理员-首页 04. 管理员-个人中心 …

PostgreSQL 的 VACUUM 与 VACUUM FULL 详解

PostgreSQL 的 VACUUM 与 VACUUM FULL 详解 一、基本概念对比 特性VACUUMVACUUM FULL定义常规维护操作&#xff0c;清理死元组激进重组操作&#xff0c;完全重写表数据锁级别不阻塞读写(共享锁)排他锁(阻塞所有操作)空间回收只标记空间为可用&#xff0c;不返还OS空间返还操作…

复刻低成本机械臂 SO-ARM100 舵机配置篇(WSL)

视频讲解&#xff1a; 复刻低成本机械臂 SO-ARM100 舵机配置篇&#xff08;WSL&#xff09; 飞特舵机 组装之前需要配置舵机的ID&#xff0c;如下的网址为舵机的资料&#xff0c;实际上用不到&#xff0c;但可以mark在这里 Software-深圳飞特模型有限公司 User Guide里面可以…

Tailwind CSS实战技巧:从核心类到高效开发

使用 Kooboo平台 训练实战技巧&#xff0c;无需配置安装&#xff0c;直接引入CDN就可以在线练习了&#xff01;具体操作流程&#xff1a;进入Kooboo后&#xff0c;选择创建空白站点 -> 站点开发 -> 控制面板 -> 页面 ->新建普通页面 -> 编写代码 一、核心布局类…

【LINUX操作系统】线程操作

了解了线程的基本原理之后&#xff0c;我们来学习线程在C语言官方库中的写法与用法。 1. 常见pthread接口及其背后逻辑 1.1 pthread_create 与线程有关的函数构成了⼀个完整的系列&#xff0c;绝⼤多数函数的名字都是以“pthread_”打头的 • 要使⽤这些函数库&#xff0c;…

【AI面试准备】Azure DevOps沙箱实验全流程详解

介绍动手实验&#xff1a;通过 Azure DevOps 沙箱环境实操&#xff0c;体验从代码提交到测试筛选的全流程。如何快速掌握&#xff0c;以及在实际工作中如何运用。 通过 Azure DevOps 沙箱环境进行动手实验&#xff0c;是快速掌握 DevOps 全流程&#xff08;从代码提交到测试筛选…

VulnHub-DC-2靶机

主机发现 sudo arp-scan -l 以sudo管理员权限扫描本地活动ip地址 Interface: eth0, type: EN10MB, MAC: 08:00:27:22:46:4f, IPv4: 192.168.252.230 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.252.6 4c:5f:70:74:3c:3b …

藏语英语中文机器翻译入门实践

&#x1f3af; 项目目标&#xff1a; 输入藏文句子&#xff0c;自动翻译成英文和中文&#xff08;或输入中文&#xff0c;翻译为英文和藏文&#xff09;。 &#x1f50d; 技术与原理简介 机器翻译&#xff08;Machine Translation, MT&#xff09;是人工智能中自然语言处理&a…

【阿里云大模型高级工程师ACP习题集】2.9 大模型应用生产实践(上篇)

练习题 【单选题】在自然语言处理的法务咨询场景中,以下哪种模型选择最为合适? A. 通用大语言模型 B. 经过数学领域微调的模型 C. 面向法律领域训练的模型 D. 视觉模型 【多选题】以下哪些属于模型非功能性需求?( ) A. 模型对不同语言的支持能力 B. 模型的响应速度要求 C.…

WPF之ProgressBar控件详解

文章目录 1. ProgressBar控件简介2. ProgressBar的基本属性和用法2.1 基本属性2.2 基本用法2.3 代码中修改进度 3. 确定与不确定模式3.1 确定模式&#xff08;Determinate&#xff09;3.2 不确定模式&#xff08;Indeterminate&#xff09; 4. 在多线程环境中更新ProgressBar4.…

IntelliJ IDEA 保姆级安装教程(附安装包)

文章目录 一、下载二、安装三、启动 一、下载 Ultimate 2021.1.1 - Windows x64 (exe) 二、安装 三、启动 首次安装启动 非首次安装启动

Performance API 性能上报

以下是关于 Performance API 性能上报的基本知识点总结: 一、性能监控核心指标体系 1. 关键性能指标(Web Vitals) 指标标准采集方式健康阈值LCP (最大内容绘制)测量加载性能PerformanceObserver≤2.5sFID (首次输入延迟)测量交互响应PerformanceObserver≤100msCLS (累积布…

C语言-指针(一)

目录 指针 内存 概念 指针变量 取地址操作符&#xff08;&&#xff09; 操作符“ * ” 指针变量的大小 注意 指针类型的意义 作用 void * 指针 const修饰指针变量 const放在*前 const放在*后 双重const修饰 指针的运算 1.指针 - 整数 2.指针 - 指针 3.指…

华为云Astro大屏连接器创建操作实例:抽取物联网iotda影子设备数据的连接器创建

目录 样图(API连接器创建成功) 说明 操作场景(以Astro大屏抽取iotda影子参数为例) 实际操作步骤 新建连接器 设置基本信息。 接口鉴权方式,支持API鉴权、AK/SK、API Key和无身份验证 无身份验证 AK/SK认证(目前暂不能用) API Key认证(第三方使用) API鉴权认…

【硬件系统架构】哈佛架构

一、引言 在计算机科学的浩瀚宇宙中&#xff0c;计算机体系结构犹如星辰般繁多且各有独特光芒。哈佛架构便是其中一颗耀眼的明星&#xff0c;它在众多计算机体系结构中占据着独特而重要的地位。从计算机技术的萌芽期一路走来&#xff0c;哈佛架构不断发展演变&#xff0c;在不同…