【C语言】预处理编译链接调试技巧详解

主页:醋溜马桶圈-CSDN博客

专栏:C语言_醋溜马桶圈的博客-CSDN博客

gitee:mnxcc (mnxcc) - Gitee.com

目录

1.预处理

1.1 预定义符号

1.2 #define

1.2.1 #define 定义标识符

1.2.2 #define 定义宏

1.2.3 #define 替换规则

1.2.4 #和##

1.2.4.1 # 的作用

1.2.4.2 ## 的作用 

1.2.5 带有副作用的宏参数

1.2.6 宏和函数的对比 

对比

1.2.7 内联函数 

1.2.8 命名约定 

1.3 #undef

1.4 命令行定义 

1.5 条件编译

1.5.1 常见的条件编译指令

1.6 头文件包含

1.6.1 头文件被包含的方式

1.6.2 嵌套文件的包含

2.程序环境 编译和链接

2.1 翻译环境和执行环境

2.2 编译和链接

2.3 翻译

2.3.1 翻译的几个阶段

2.3.1.1 预编译

2.3.1.2 编译

词法分析

符号汇总

2.3.1.3 汇编

生成符号表

2.4 链接

2.4.1 合并段表

 2.4.2 合并符号表和重定位

2.5 运行

3.实用调试技巧 

3.1 什么是bug?

3.2 调试是什么?有多重要?

3.3 调试的基本步骤

3.4 debug和release的介绍

3.5 windows环境调试介绍

3.5.1 调试环境的准备

3.5.2 学会快捷键

3.5.3 调试的时候查看程序当前信息 

3.5.3.1 查看临时变量的值

3.5.3.2 查看内存信息

3.5.3.3 查看调用堆栈

3.5.3.4 查看汇编信息

3.5.3.5 查看寄存器信息

3.6 如何写出好(易于调试)的代码

3.6.1 常见的coding技巧

3.6.1.1 assert

3.6.1.2 const

常量指针

指针常量

区分常量指针和指针常量 

3.7 编程常见的错误

3.7.1 编译型错误

3.7.2 链接型错误

3.7.3 运行时错误

3.8 编程思维 


1.预处理

1.1 预定义符号

__FILE__          //进行编译的源文件

__LINE__         //文件当前的行号

__DATE__       //文件被编译的日期

__TIME__        //文件被编译的时间

__STDC__       //如果编译器遵循ANSI C,其值为1,否则未定义

这些预定义符号都是语言内置的

举个例子:

1.2 #define

#define是一种预处理指令,他有两种用法:

  1. #define 定义常量(标识符)
  2. #define 定义宏 

1.2.1 #define 定义标识符

语法:

        #define  name  stuff

举个例子:

#define 是完全替换,比如

所以在定义的时候,为了强调他是一个整体,需要自己带上括号:

注意:由于是完全替换,在define定义标识符的时候,不要在最后加   ;   否则替换的时候会将  也替换过去,会导致语法错误

1.2.2 #define 定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常会被解释为宏(macro)或定义宏(define macro)

下面是宏的声明方式:

#define name( parament-list ) stuff

其中的parament-list是一个由逗号隔开的符号表,他们可能出现在stuff中

注意:

参数列表的左括号必须与name紧邻

如果两者之间有任何空白存在,参数列表就会被释解释为stuff的一部分

如:

#define定义宏也是完全替换,比如:

为了防止出现失误,我们在声明的时候需要加上括号:

我们在写宏的时候,如果逻辑需要,我们可以加上足够多的括号来使宏变得完整

1.2.3 #define 替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,他们首先被替换
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程

注意:

  1. 宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归
  2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索 

1.2.4 #和##

1.2.4.1 # 的作用

如何把参数插入到字符串中?、

我们发现字符串是有自动连接的特点的

假设有这样的代码:

我们如何用宏来实现printf的功能呢,这里我们使用#

他的替换是周怎么完成的呢 

这里只有当字符串作为宏参数的时候才可以把字符串放在字符串中

使用#,把一个宏参数变成对应的字符串 

比如:代码中的#N会被预处理器处理为:“N”

所以“#N”即被处理为““N””

1.2.4.2 ## 的作用 

##可以把位于他两边的符号合成一个符号

他允许宏定义从分离的文本片段创建标识符

注意:这样的连接必须产生一个合法的标识符,否则其结果就是未定义的

1.2.5 带有副作用的宏参数

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的有永久性效果

x+1;//不带副作用

x++;//带副作用

MAX宏可以证明具有副作用的参数所引起的问题 

这段代码输出的结果是什么?

这里我们得知道预处理之后的结果是什么: 

这段代码是证明执行的呢?

1.2.6 宏和函数的对比 

宏通常被应用于执行简单的运算

比如在两个数中找出较大的一个

#define MAX(a, b) ((a)>(b)?(a):(b))

那为什么不用函数来完成这个任务?

原因有二:

  1. 用于调用函数和从函数返回的代码可能实际执行这个小型计算工作所需要的时间更多
    所以宏比函数在程序的规模和速度方面更胜一筹
  2. 更为重要的是函数的参数必须声明为特定的类型
    所以函数只能在类型合适的表达式上使用
    宏是类型无关的

 宏的缺点:当然和函数相比,宏也有劣势的地方:

  1. 每次使用宏的时候,一份宏定义的代码将插入到程序中,除非宏比较短,否则可能大幅度增加程序的长度
  2. 宏是没法调试的
  3. 宏由于类型无关,也就不够严谨
  4. 宏可能会带来运算符优先级的问题,导致过程容易出现错误

 宏有时候可以做函数做不到的事情,比如:宏的参数可以出现类型,但是函数做不到

对比

建议:

如果逻辑比较简单,可以使用宏来实现

如果计算逻辑比较负责,那么就使用函数实现 

1.2.7 内联函数 

C99之后,C++引入了内联函数的概念  inline关键字

内联函数具有函数和宏的双重优点:

  1. 内联函数是函数
  2. 内联函数又像宏一样,在调用的地方展开

1.2.8 命名约定 

一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者

那我们平时的一个习惯是:

  • 把宏名全部大写               //MAX
  • 函数名不要全部大写        //Max

1.3 #undef

这条指令用于移除一个宏定义

1.4 命令行定义 

许多C的编译器提供了一种能力,允许在命令行中定义符号,用于启动编译过程

例如:当我们根据同一个源文件要编译出一个程序的不同版本的时候,这个特性有点用处

(假定某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一 个机器内存大写,我们需要一个数组能够大写。)

1.5 条件编译

在编译一个程序序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的,因为我们有条件编译指令

条件编译就是:满足条件就编译,不满足条件就不编译

比如说:

调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译

1.5.1 常见的条件编译指令

1.
#if   常量表达式
        //...
#endif
//常量表达式由预处理器求值
如:
#define __DEBUG__ 1
#if __DEBUG__
        //..
#endif

表达式为真则编译,为假则不编译

2.多个分支的条件编译
#if 常量表达式
        //...
#elif 常量表达式
        //...
#else
        //...
#endif

只会选择以一个#if或者#elif执行 

3.判断是否被定义
#if defined(symbol)
#ifdef symbol

#if !defined(symbol)
#ifndef symbol

判断(symbol)是否被定义过,如果被定义过则执行代码

4.嵌套指令
#if defined(OS_UNIX)
        #ifdef OPTION1
                unix_version_option1();
        #endif
        #ifdef OPTION2
                unix_version_option2();
        #endif
#elif defined(OS_MSDOS)        
        #ifdef OPTION2
                msdos_version_option2();
        #endif
#endif

注意:#if 与 #endif 是配套使用的,同时出现,同时消失

1.6 头文件包含

我们已经知道,#include 指令可以使另外一个文件被编译,就像它实际出现于 #include 指令的地方一样

这种替换的方式很简单:

预处理器先删除这条指令,并用包含文件的内容替换
这样一个源文件被包含10次,那就实际被编译10次

1.6.1 头文件被包含的方式

头文件的包含一般有两种方式:

1.包含本地文件(自己的.h文件)
#include "xxx.h"(用双引号)

2.包含标准库中的文件
#include <xxx.h> (用尖括号)

查找策略:

先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件

#include包括""和<>这两种情况

""是在用户工作目录下寻找(用户的工作目录是通过编译器指定的)
<>是找系统标准库函数,通过系统环境变量指定系统库目录

如果找不到就提示编译错误

1.6.2 嵌套文件的包含

如果出现这样的场景

comm.h和comm.c是公共模块
test1.h和test1.c使用了公共模块
test2.h和test2.c使用了公共模块
test.h和test.c使用了test1模块和test2模块。
这样最终程序中就会出现两份comm.h的内容
这样就造成了文件内容的重复

我们可以用条件编译解决这个问题

每个头文件的开头写:

#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif  //__TEST_H__

或者 

#pragma once

就可以避免头文件的重复引入

2.程序环境 编译和链接

2.1 翻译环境和执行环境

在ANSI C的任何一种实现环境中,存在两个不同的环境

  • 第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令
  • 第二种是执行环境,它用于实际执行代码

2.2 编译和链接

2.3 翻译

  • 组成一个程序的每个源文件通过编译过程分别抓换成目标代码(object code)
  • 每个目标文件文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序
  • 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也 链接到程序中

2.3.1 翻译的几个阶段

2.3.1.1 预编译

预编译的过程:

  1. 注释的替换(删除) 注释被替换成一个空格
  2. 头文件的包含  #include < >
  3. #define 符号的替换

所有的预处理指令都是在预编译阶段处理的 (文本操作)

2.3.1.2 编译
词法分析

假如有下面一段代码

array[index] = (index+4)*(2+6) 

将源代码程序输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符等)

上面程序进行词法分析后得到了16个记号:

生成一棵语法树

符号汇总

一个工程中可以包含多个.c文件,如何在一个.c文件中调用另一个.c文件中的函数呢

这里我们了解一个概念叫做符号汇总

假设有这样的代码

进行符号汇总

注意:符号汇总只能汇总全局变量

2.3.1.3 汇编

把汇编代码翻译成了二进制的指令,生成了.o文件(目标文件)

生成符号表

假设给汇总的符号给上地址,生成一个符号表

2.4 链接

2.4.1 合并段表

 2.4.2 合并符号表和重定位

2.5 运行

程序执行的过程:

  1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成
  2. 程序的执行便开始。接着便调用main函数
  3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程中一直保留他们的值
  4. 终止程序。正常终止main函数;也有可能是意外终止

3.实用调试技巧 

3.1 什么是bug?

作为程序员,每天被bug支配着,当然应该了解下对手了。

bug原意本来为昆虫的意思,1947年9月9日,葛丽丝·霍普(Grace Hopper)发现了第一个电脑上的bug。当在Mark II计算机上工作时,整个团队都搞不清楚为什么电脑不能正常运作了。经过大家的深度挖掘,发现原来是一只飞蛾意外飞入了一台电脑内部而引起的故障(如图所示)。这个团队把错误解除了,并在日记本中记录下了这一事件。也因此,人们逐渐开始用“bug”来称呼计算机中的隐错。

在这里插入图片描述

3.2 调试是什么?有多重要?

所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了;如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径

顺着这条途径顺流而下就是犯罪,逆流而上就是真相

一名优秀的程序员是一名出色的侦探

每一次尝试都是尝试破案的过程

调试(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序

错误的一个过程。

3.3 调试的基本步骤

  • 发现程序错误的存在
  • 隔离、消除等方式对错误进行定位
  • 确定错误产生的原因
  • 提出纠正错误的解决办法
  • 对程序错误予以改正,重新测试

发现程序错误:程序员自己、测试人员、用户 

3.4 debug和release的介绍

  • Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序
  • Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用

测试人员站在用户的角度,测试的是发布版本 

代码:

#include <stdio.h>
int main()
{char *p = "hello world";printf("%s\n", p);return 0;
}

上述代码在Debug环境的结果展示

上述代码在Release环境的结果展示

Debug和Release反汇编展示对比

所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程

那编译器进行了哪些优化呢? 请看如下代码:

#include <stdio.h>
int main()
{int i = 0;int arr[10] = {0};for(i=0; i<=12; i++){arr[i] = 0;printf("hehe\n");}return 0;
}

如果是 debug 模式去编译,程序的结果是死循环。

如果是 release 模式去编译,程序没有死循环。

那他们之间有什么区别呢?

就是因为优化导致的

3.5 windows环境调试介绍

3.5.1 调试环境的准备

在环境中选择 debug 选项,才能使代码正常调试

3.5.2 学会快捷键

最常使用的几个快捷键:

F5

  • 启动调试,经常用来直接跳到下一个断点处

F9

  • 创建断点和取消断点
  • 断点的重要作用,可以在程序的任意位置设置断点
  • 这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去

F10

  • 逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句

F11

  • 逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部

CTRL + F5

  • 开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用 

在笔记本电脑上可以配合使用FN键 

3.5.3 调试的时候查看程序当前信息 

3.5.3.1 查看临时变量的值

在调试开始之后,用于观察变量的值

3.5.3.2 查看内存信息

在调试开始之后,用于观察内存信息

3.5.3.3 查看调用堆栈

通过调用堆栈,可以清晰的反映函数的调用关系以及当前调用所处的位置

3.5.3.4 查看汇编信息

3.5.3.5 查看寄存器信息

可以查看当前运行环境的寄存器的使用信息

多多动手,尝试调试,才能进步

  •  一定要熟练掌握调试技巧
  • 初学者可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写程序,但是80%的时间在调试。
  • 我们所讲的都是一些简单的调试。
  • 以后可能会出现很复杂调试场景:多线程程序的调试等
  • 多多使用快捷键,提升效率 

3.6 如何写出好(易于调试)的代码

  1. 代码运行正常
  2. bug很少
  3. 效率高
  4. 可读性高
  5. 可维护性高
  6. 注释清晰
  7. 文档齐全

3.6.1 常见的coding技巧

  1. 使用assert(断言)
  2. 尽量使用const
  3. 养成良好的编码风格
  4. 添加必要的注释
  5. 避免编码的陷阱
3.6.1.1 assert

assert函数是C语言标准库<assert.h>中的一个函数,函数原型为:

    void assert(int expression)

该函数输入参数只有一个int类型参数,返回值为void类型

assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行

用法总结与注意事项

  1. 在函数开始处检验传入参数的合法性
  2. 每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
  3. 不能使用改变环境的语句,因为assert只在Debug中生效,如果这么做,会使用程序在真正运行时遇到问题
  4. assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
  5. 有的地方,assert不能代替条件过滤
3.6.1.2 const
常量指针

常量指针是指针指向的内容是常量,可以有以下两种定义方式

const int* n;int const* n;

常量指针说的是不能通过这个指针改变变量的值,但是可以通过其他的引用来改变变量的值

int a=5;
const int* n=&a;
a=6;

常量指针指向的值不能改变,但是这并不意味着指针本身不能改变,常量指针可以指向其他的地址

int a=5;
int b=6;
const int* n=&a;
n=&b;
指针常量

指针常量是指指针本身是个常量,不能再指向其他的地址,写法如下

int*const n;

需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改

int a=5;
int*p=&a;
int* const n=&a;
*p=8;
区分常量指针和指针常量 

区分常量指针和指针常量的关键就在于星号(*)的位置,我们以星号为分界线

  • 如果const在星号的左边,则为常量指针 
  • 如果const在星号的右边,则为指针常量

如果我们将星号读作"指针",将const读作‘常量'的话,内容正好符合。

  • int const * n;是常量指针
  • int * const n;是指针常量

3.7 编程常见的错误

3.7.1 编译型错误

直接看错误提示信息(双击),解决问题,或者凭借经验就可以搞定

3.7.2 链接型错误

看错误提示信息,主要再代码中找到错误信息中的标识符,然后定位问题所在

一般是标识符名不存在或者拼写错误

3.7.3 运行时错误

借助调试,逐步定位问题

3.8 编程思维 

作为初学编程的各位小伙伴们,肯定已经或多或少地听说过编程思维这个词了,那么到底什么是编程思维呢

编程语言

表面含义,编程就是以各式的编程语言来编译代码,类似于英语,也是一门语言。那么作为语言,英语有诸多的语法,那么编程语言同样有一定的语法。毕竟写出来的代码是需要让机器看懂的。

编程思维

那么思维是什么呢,简单说就是做一件事情,脑海里要能够搭建起一个简单的框架,然后再填填补补。构建这个框架的思维就是编程思维,这要求咱们在编程前必须阅读并理解需求,不能只停留在代码的层面,要全局思考,结果会使得代码简洁又高效。

举例

For example,这是一段利用C语言写出最简单的逆序输出,显然,很通俗易懂,但是当输入n个内容,这段代码显然不适用了。

#include <stdio.h>
int main() {int a, b, c, d, e, f, g, h, i, j;scanf("%d %d %d %d %d %d %d %d %d %d",&a,&b,&c,&d,&e,&f,&g,&h,&i,&j);printf("%d %d %d %d %d %d %d %d %d %d", j, i, h, g, f, e, d, c, b, a);
}

那么就可以尝试使用下面这段码

#include<stdio.h>
int main()
{int arr[10] = {0};for(int i = 9;i>=0;i--){scanf("%d",&arr[i]);}for(int i = 0;i<10;i++){printf("%d ",arr[i]);}return 0;
}

显然,这段代码就有了一定的框架结构,这就是编程思维的外在体现。

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

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

相关文章

HTTPS 从懵懵懂懂到认知清晰、从深度理解到落地实操

Https 在现代互联网应用中&#xff0c;网上诈骗、垃圾邮件、数据泄露的现象时有发生。为了数据安全&#xff0c;我们都会选择采用https技术。甚至iOS开发调用接口的时候&#xff0c;必须是https接口&#xff0c;才能调用。现在有部分浏览器也开始强制要求网站必须使用https&am…

MySQL修改root用户的密码

在Windows上重置MySQL的root用户密码可以通过以下步骤进行&#xff1a; 停止MySQL服务&#xff1a;使用快捷键WINR打开运行窗口&#xff0c;输入cmd进入命令行。在命令行中输入net stop mysql来关闭MySQL服务。启动MySQL跳过授权表&#xff1a;将目录切换到MySQL安装目录下的b…

谷粒商城——缓存——SpringCache

1. 配置使用 首先需要导入相关的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency> 随后在配置文件中进行配置&#xff1a; spring:cache:t…

oracle补丁升级(19.3-19.22)

一、备份原来的opatch和数据库文件 这里要根据自己的路径&#xff1a; mv /u01/app/oracle/product/19.3.0/db_1/OPatch /u01/app/oracle/product/19.3.0/db_1/OPatch.bakcd /u01/app mkdir -p /u01/app/backup tar -pcvf /u01/app/backup/oracle_backup.tar /u01/app/oracle/…

使用llamafile 构建本地大模型运用

安装 https://github.com/Mozilla-Ocho/llamafile 下载 大模型文件&#xff0c;选择列表中任意一个 wget https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4.llamafile?downloadtrue https://github.com/Mozilla-Ocho/llamafile?tabre…

智慧农业领航:数字乡村助力乡村振兴与可持续发展

目录 一、引言 二、智慧农业的内涵与特点 三、数字乡村助力乡村振兴的路径 1、提升农业生产效率 2、优化农业产业结构 3、促进乡村社会治理现代化 三、智慧农业在可持续发展中的作用 1、促进资源节约与环境保护 2、提升农产品质量与食品安全 3、推动乡村经济多元化发…

VOC(客户之声)赋能智能家居:打造个性化、交互式的未来生活体验

随着科技的飞速发展&#xff0c;智能家居已成为现代家庭不可或缺的一部分。然而&#xff0c;如何让智能家居更好地满足用户需求&#xff0c;提供更贴心、更智能的服务&#xff0c;一直是行业关注的焦点。在这个背景下&#xff0c;VOC&#xff08;客户之声&#xff09;作为一种用…

Redis入门到实战-第十七弹

Redis实战热身t-digest篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代理…

【Java程序设计】【C00379】基于(JavaWeb)Springboot的旅游服务平台(有论文)

【C00379】基于&#xff08;JavaWeb&#xff09;Springboot的旅游服务平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c…

3.学习前后端关联

目录 1.接口类型 2.错误状态码 3.如何定义路由 4.那如何要求前端传入一个JSON数据呢&#xff1f; 4.解决前后端口不同源,跨域问题 1.使用CrossOrigin 2.直接复制代码使用 5.用户登录校验 1.接口类型 POST(新增数据)、PUT(更新更改数据)、GET(查询)、DELET(删除数据) …

Anaconda和Python是什么关系?

Anaconda和Python相当于是汽车和发动机的关系&#xff0c;你安装Anaconda后&#xff0c;就像买了一台车&#xff0c;无需你自己安装发动机和其他零配件&#xff0c;而Python作为发动机提供Anaconda工作所需的内核。 简单来说&#xff0c;Anaconda是一个集成了IDE、Notepad、P…

网络层介绍,IP地址分类以及作用

IP地址组成&#xff1a; TTL&#xff1a;生存时间 基于ICMP报文 特殊地址&#xff1a; 0.0.0.0-0.255.255.255 1.代表未指定的地址 默认路由 DHCP下发地址的时候&#xff0c;发个报文给DHCP服务器 临时用0.0.0.0借用地址&#xff0c;未指定地址。 2.全网地址&#xff1a;目…

阐述el-dropdown(下拉菜单)的基本知识

目录 1. 基本知识2. Demo3. 实战 1. 基本知识 el-dropdown是一个常用的UI组件&#xff0c;用于创建下拉菜单&#xff0c;通常用于实现各种交互式菜单、导航栏或下拉选项 确保安装Element UI库&#xff0c;它包含了el-dropdown组件 npm install element-ui # 或者 yarn add e…

配置Web运行环境与第一个网页

安装与配置Web环境: 如下使用了VSC作为web的运行环境。 下面是VSC的官网点击进入:Download Visual Studio Code - Mac, Linux, Windowshttps://code.visualstudio.com/download 1.下载 进入官网后可以看到有windows&#xff0c;linux&#xff0c;还有苹果按照自己的系统下载&…

Node Sass does not yet support your current environment

项目运行时报错&#xff1a;Node Sass does not yet support your current environment 原因是node版本过高。 解决办法&#xff1a; 使用nvm管理node版本&#xff0c;&#xff08;如何安装nvm&#xff1f;请点击跳转&#xff09; 具体步骤如下&#xff1a; 1.查看当前node…

Element UI中日期选择日(date-picker)等其他选择器下拉显示错位、位置错误解决

省流版 给选择器加上唯一key&#xff08;下面的想看就看&#xff09; 问题复现 需求是用一个下拉切换时间维度的选择&#xff0c;分别为年度、季度、月度&#xff0c;但是开发的时候发现&#xff0c;当切换的时候&#xff0c;视图可正常切换&#xff0c;但点击选择时却发现选…

Vue 2 组件发布到 npm 的常见问题解决

按照 Vue 2 组件打包并发布到 npm 的方法配置项目后&#xff0c;项目在实际开发过程中&#xff0c;随着代码写法的多样性增加而遇到的各种打包问题&#xff0c;本文将予以逐一解决&#xff1a; 本文目录 同时导出多个组件 样式表 import 问题解决 Json 文件 import 问题解决…

图论最短路径以及floyd算法的MATLAB实现

图论是数学的一个分支&#xff0c;起源于18世纪。1736年&#xff0c;数学家欧拉通过解决“哥尼斯堡七桥问题”&#xff0c;将问题抽象成点和线的关系&#xff0c;并通过理论分析得出结论&#xff0c;这个过程标志着图论的产生&#xff0c;欧拉也因此被称为“图论之父”。图论研…

智慧城市解决方案大全:标准规范顶层设计指南、整体解决方案、厂商售前宣讲PPT、招投标、智慧城市白皮书等全套680份,一次性打包下载

关键词&#xff1a;智慧城市&#xff0c;智慧城市解决方案&#xff0c;智慧城市发展的前景与趋势&#xff0c;智慧城市概念主力流出&#xff0c;智慧城市项目包括哪些方面&#xff0c;智慧城市项目方案&#xff0c;智慧城市宣传片&#xff0c;智慧城市白皮书&#xff0c;智慧城…

MySQL之MVCC如何实现可重复读和提交读

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;Github传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有…