C语言笔记(关键字)

gdb调试

  • gcc 源程序 -g;加gdb调试信息
  • gdb可执行程序;(gdb调试)
  • l(ist):查看源码,按一下从main开始10行以此往后
  • l n:查看n处上下10行的源码
  • run:运行程序
  • b(reak)行号:加断点
  • i(nfo) b:查看当前断点
  • d(elete) 断点序号:删除断点
  • p(rint) 变量名:查看变量的值
  • c(ontinue):程序继续运行
  • 单步运行程序:
  • n(ext):往后执行一步,不进入函数内部
  • s(tep):往下执行一步,进入函数内部执行
  • quit:退出

变量的命名规则

  1. 程序中不得出现仅靠大小写区分的相似的标识符
  2. 一个函数名禁止被使用于其他地方
  3. 所有宏定义,枚举常量,只读变量全用大写字母命名,用下划线分割
  4. 考录到习惯性问题,局部变量中可采用通用的命名方式,但仅限于n,i,j 等作为循环变量使用
  5. 结构体被定义时必须有明确的结构体名
  6. 定义变量的同时,不忘初始化
  7. 不同类型数据之间的运算要注意精度扩展的问题,一般低精度向高精度数据扩展
  8. 禁止使用八进制的常数(0 除外,因为严格意义上来讲 0 也是八进制数) 和八进制的转义字符
  9. 在计算机中,任何以 0 开头的数字都被以为是八进制格式的数(当然十六进制的0x不算)。所以当我们写固定长度的数字时,会存在一定的风险。如 code[3] = 052;(对应十进制的42)

sizeof关键字

sizeof 在计算变量所占空间大小时,括号可以省略,而计算类型大小时,不能省略。且一般情况下,sizeof时在编译时求值,所以
sizeof(i++)不会引起副作用,但是由于sizeof(i++)和sizeof(i)的结果一样,所以没有必要且不允许写这样的代码。同样“sizeof(i=1234)”这样的代码也不允许,**因为
i 的值没有被改变,并没有被赋值为1234**。

sizeof操作符里面不要有其他运算符,否则不会达到预期的目的。在C99 中,计算柔性数组所占用空间大小时,sizeof是在运行时求值,此为特例。

★在测字符串长度时,strlen函数时计算字符串长度,并不包含字符串在最后的’\0’

if、else组合

  • bool变量与“零值”的比较:

bool bTestFlag = FALSE;
(A) if (bTestFlag == 0);
(B) if (bTestFlag == TRUE);
(C) if (bTestFlag)
(A) 容易产生歧义,会误认为是整型变量。
(B) FALSE在编译器里被定义为 0 ;但 TRUE 的值则不唯一,所以这种写法不妥
(C) 既不会引起误会,也不会由于 TRUE 或 FALSE 的不同定义值而出错。

  • float变量与“零值”进行比较

float fTestVal = 0.0
(A) if (fTestVal == 0.0);
(B) if ((fTestVal >= -EPSINON) && (fTestVal <= EPSINON));
//EPSINON为事先定义好的精度
分析:
float与double类型的数据都是有精度限制的,不能直接拿来与0.0比
EPSINON为实现定义好的精度,如果一个数落在[0.0-EPSINON, 0.0+EPSINON]这个闭区间内,我们认为在某个精度内它的值与零相等。扩展一下,把0.0替换为你想比较的任何一个浮点数,那我们就可以比较任意两个浮点数的大小了,当然是在某个精度内
不要在很大的浮点数和很小的浮点数之间进行运算,使用浮点数应遵循定义好的浮点数标准
五种类型的浮点异常是:无效运算、被零除、上溢、下溢和不精确
四种射入方向:向最接近的可表示的值、当有两个最接近的可表示的值时,首选“偶数”值、向负无穷大(向下)和向正无穷大(向上)以及向0(截断)

  • 指针变量与“零值”进行比较

int* p = NULL; //定义指针一定要同时初始化,指针和数组部分会详细讲
(A) if (p == 0);
(B) if (p);
(C) if (NULL == p);
(A) 写法:p时整型变量?容易引起误会,尽管NULL的值和0一样,但意义不同
(B) 写法:p时bool型变量,容易引起误会不好
(C) 正确

  • else到底与哪个if配对?

    C语言中规定:else始终与同一括号内最近的未匹配的if语句结合

  • 使用if语句的其他注意事项

规则1:先处理正常情况,再处理异常情况。
如果把执行概率更大的代码放到后面,也就意味着if语句将进行多次无谓的比较。所以,把正常情况的处理放在if后面,而不要放在else后面

规则2:确保if和else子句没有弄反

规则3:赋值运算符不能使用再产生布尔值的表达式上。
任何被认为是具有布尔值的表达式上都不能使用赋值运算。
例如一下两种情况:
if ((x = y) != 0)
{
foo();
}
或者:
if (x = y)
{
foo();
}

规则4:所有if-else if 结构应该由else子句结束
不管何时一条fi语句后有一个或多个else if 语句都应该应用本规则;最后的else if 必须跟有一条else语句。

switch、case组合

既然有了if、else组合,为什么还需要switch、case组合

  • 不要拿青龙偃月刀去削苹果

规则1:每个case语句的结尾绝对不要忘了加break,否则将导致多个分支重叠(除非有使用多个分支重叠)
规则2:最后必须使用default分支。即使程序真的不需要default处理,也应该保留以下语句:
default:
break;

这样做并非画蛇添足,可以避免让人误以为你忘了default处理
规则3:再switch case组合中,禁止使用return语句。
规则4:switch表达式不应是有效的布尔值。例如:
switch (x == 0) // not compliant - effectively Boolean
{
...
}

  • case关键字后面的值有什么要求么

记住: case后面只能是整型或字符型的常量或常量表达式(想想字符型数据在内存里是怎么存的)。

  • case语句的排列顺序

有以下几种规则:
1. 按字母或数字顺序排列各条case语句
2. 把正常情况放在前面,而把异常情况放在后面
3. 按执行频率排列case语句

  • 使用case语句的其他注意事项

有以下几种规则:
1. 简化每种情况对应的操作
2. 不要为了使用case语句而刻意制造一个变量
3. 将default子句只用于检查真正的默认情况

  • break与continue的区别(传送门)

break关键字很重要,表示终止本层循环。当代码执行到break时,本层循环便终止。
而continue表示终止本次(本轮)循环,当代码执行到continue时,本轮循环终止,进入下一轮循环

  • 循环语句的注重点:

建议使用以下规则:
1. 在多层循环中,如果有可能,应当将最长的循环放在内层,最短的循环放在外层,以减少CPU跨切循环层的次数。
2. 建议for语句的循环控制变量的取值采用“半开半闭区间”的写法(左闭右开)。
3. 不能在for循环体内修改循环变量,防止循环失控。
4. 循环要尽可能短,要使代码清晰,一目了然。
5. 把循环嵌套控制在3层以内。
6. for语句的控制表达式不能包含任何浮点类型的对象。

void关键字

  • void a

void字面意思是“空类型”,void * 则为“空类型指针”,void * 可以指向任何类型的数据。void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量。
void真正发挥的作用在于:对函数返回的限定;对函数参数的限定
任何类型的指针都可以直接赋值给void * ,无需进行强制类型转换,但反之则不能,因为“空类型”可以包容“有类型”,而“有类型”则不能包容“空类型”,比如,我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”。

  • void修饰函数返回值和参数

规则1:如果函数没有返回值,那么应该将其声明为void类型。
在C语言中,凡不加返回值类型限定的函数,就会被编译器作为返回整型值处理。如果函数没有返回值,那么一定要声明为void类型。这既是程序良好可读性的需要,也是编程规范性的要求。

规则2:如果函数无参数,那么应声明其参数为void
在C语言中,可以给无参数的函数传送任意类型的参数,但是在C++编译器中编译同样的代码则会出错。在C++中,不能向无参数的函数传送任何参数。所以无论在C还是在C++中,若函数不接受任何参数,则一定要指明参数为void。

  • void指针

规则1: 千万小心又小心地使用void指针类型。
按照ANSI标准,不能对void指针进行算法操作,之所以这样认定,是因为它坚持:进行算法操所的指针必须是确定知道其指向数据类型大小的,也就是说必须知道内存目的地址的确切值。
在实际的程序设计中,为符合ANSI 标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:

void* pvoid;
(char*)pvoid++;     // ANSI: 正确; GNU:正确
(char*)pvoid += 1;  // ANSI: 错误; GNU:正确

规则2:如果函数的参数可以是任意类型指针,那么应声明其参数为void*
典型的如内存操作函数memcpy和memset的函数原型分别为:
void * memcpy(void * dest, const void * src, size_t len);
void * memset(void * buffer, int c, size_t num);
有趣的是,memcpy和memset函数返回的也是void * 类型。

  • void 不能代表一个真实的变量

void 不能代表一个真是的变量。void 体现了一种抽象,这个世界上的变量都是“有类型”的,譬如一个人不是男人就是女人(人妖不算)。
void 的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中“抽象基类”的概念,也很容易理解 void 数据类型。正如不能给抽象基类定义一个实例,我们不能定义一个 void(让我们类比的称void为“抽象数据类型”)变量。

return关键字

return 用来终止一个函数并返回其后面跟的值。
注意:return语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时自动销毁。

const关键字也许该被替换为readonly (传送门)

const 是 constant 的缩写,是恒定不变的意思,也翻译为常量和常数等。很不幸,正是因为这一点,很多人都认为被 const 修饰的值是常量。这是不精确的,精确来说应该是只读的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。或许当初这个关键字应该被替换为 readonly。
const 推出的初始目的,正式为了取代预编译指令,消除它的缺点,同时继承它的优点。

  • 节省空间,避免不必要的内存分配,同时提高效率

编译器通常不为普通 const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。例如:

#define M 3         // 宏常量
const int N = 5;    // 此时并未将N放入内存中
...
int i = N;          // 此时为N分配内存,以后不再分配
int I = M;          // 预编译期间进行宏替换,分配内存
int j = N;          // 没有内存分配
int J = M;          // 再进行宏替换,又一次分配内存

const i 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像 #define 一样给出的时立即数,所以const定义的 只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而#define 定义的宏常量在内存中有若干个备份。#define 宏是在 预编译阶段进行替换,而 const 修饰的只读变量实在编译的时候确定其值,#define 宏 没有类型,而 const 修饰的只读变量 具有特定的类型

  • 修饰指针

先忽略类型名(编译器解析的时候也是忽略类型名),我们看const 离哪个近,”近水楼台先得月“,离谁近就修饰谁

  • 修饰函数的参数

const 修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外改变时使用。

  • 修饰函数的返回值

const 修饰符也可以修饰函数的返回值,返回值不可被改变。

最易变的关键字——volatile

volatile int i = 10;

volatile 关键字告诉编译器,i 时随时可能发生变化的,每次使用它的时候必须从内存中取出 i 的值,因此编译器生成的汇编码会重新从 i 的地址处读取数据。
这样看来,如果 i 是一个寄存器变量,表示一个端口数据或者是多个线程的共享数据,那么就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

最会戴帽子的关键字——extern

博客园中有一篇关于extern的讲解(传送门)

struct关键字

struct是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。

在网络协议,通信控制,嵌入式系统,驱动开发等地方,我们经常要传送的不是简单的字节流(char型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。经验不足的开发人员往往将所有需要传送的内容依顺序保存在char型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式和通信协议有所变化,程序就要进行非常机制的修改,非常容易出错。

这个时候只需要一个结构体就能搞定。平时我们要求函数的参数尽量不多于4个,如果函数的参数多余4个使用起来非常容易出错(包括每个参数的意义和顺序都容易出错),效率也会降低(与具体CPU有关,ARM芯片对于超过4个参数的处理就有讲究,具体请参考相关资料)。这个时候,可以用结构体压缩参数个数。

✦struct 与 class 的区别:struct 的成员默认情况下的属性是 public,而 class 成员的却是 private。

空结构体大小一般为1,在GCC里面计算的值为0,

union关键字

union 关键字的用法与 struct 的用法非常相似。

union 维护足够的空间来放置多个数据成员中的“一种”,而不是为每一个数据成员配置空间。在 union 中所有的数据成员公用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的其实地址。

一个 union 只配置一个足够大的空间来容纳最大长度的数据成员,在C++里,union 的成员默认属性为 public。union 主要用来压缩空间。如果一些数据不可能在同一时间同时被用到,则可以使用 union。

柔性数组

这边引用博客园中的一篇关于柔性数组的文章传送门

大小端模式对union类型数据的影响

下面看一个例子:

union
{int i;char a[2];
}* p, u;p = &u;
p->a[0] = 0x39;
p->a[1] = 0x38;

p.i 的值应该为多少呢?
这里需要考虑存储模式:大端模式和小端模式。

大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节存放在高地址中。

小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。

union 型数据所占的空间等于其最大的成员所占的空间。对 union 型成员的存取都从相对于该联合体基地址的偏移量为 0 处开始,也就是联合体的访问不论对哪个变量的存取都是从 union 的首地址位置开始。如此一解释,上面的问题是否已经有了答案呢?

如何用程序确认当前系统的存储模式

上述问题似乎还比较简单,那来个有计数含量的:请写一个 C 函数,若处理器是 Big_endian,则返回 0 ; 若是 Little_endian ,则返回 1。

先分析下,按照上面关于大小端模式的定义,假设 int 类型变量i被初始化为1.
以大端模式存储,其内存布局如图1.3所示。
以小端模式存储,其内存布局如图1.4所示。
这里写图片描述
这里写图片描述

变量 i 占 4 字节,但只有1个字节的值为 1,另外 3 个字节的值都为 0。如果取出低地址上的值为 0,毫无疑问,这是大端模式;如果取出低地址上的值为1,毫无疑问,这是小端模式。既然如此,我们完全可以利用 union 类型数据“所有成员的起始地址一致”的特点编写程序。到现在,应该知道怎么写了吧?参考文案如下:

int checkSystem()
{union check{int i;char ch;}c;c.i = 1;return (c.ch == 1);
}

现在你可以用这个函数来测试当前系统的存储模式,当然你也可以不用功函数而直接去查看内存来确定当前系统的存储模式,如图1.5所示:
这里写图片描述

图1.5中 0x01 的值存在低地址上,说明当前系统为小端模式。
不过要说明的一点是,某些系统可能同时支持这两种存储模式,你可以用硬件跳线或在编译器的选项中设置其存储模式。
留一个问题:
在 x86 系统下,以下程序输出的值为多少?

#include <stdio.h>int main()
{int a[5] = {1,2,3,4,5};int *ptr1 = (int *)(&a+1);int *ptr2 = (int *)((int)a+1);printf("&x, %x", ptr1[-1], *ptr2);return 0;
}

位域

对于位域的使用和自定义的行为需要详细说明,且在使用前需要用代码check当前系统的模式(大端或小端模式)

enum关键字

枚举类型的使用方法
一般的定义方式如下:

enum enum_type_name
{   ENUM_CONST_1,ENUM_CONST_2,...ENUM_CONST_n
}enum_variable_name;

注意:enum_type_name是自定义的一种数据类型名,而enum_variable_name为enum_type_name类型的一个变量,也就是我们平时常说的枚举变量。实际上enum_type_name类型是对一个变量取值范围的限定,而花括号内是它的取值范围,即enum_type_name类型的变量enum_variable_name只能取值为花括号内的任何一个值(都是常量,一般用大写),如果赋给该类型变量的值不在列表中,则会报错或者警告。
enum变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加一;如果都没有赋值,他们的值从0开始依次递增1.

枚举与#define宏的区别

  1. #define宏常量是在 预编译阶段 进行简单替换;枚举常量则是在 编译 的时候确定其值。
  2. 一般在调试器里,可以调试枚举常量,但是不能调试宏常量。
  3. 枚举可以以此定义大量相关的常量,而#define宏一次只能定义一个。

留2个问题:
1. 枚举能做的是,#define宏能不能做到?如果能,那为什么还需要枚举?
2. sizeof(ColorVal)的值是多少?为什么?

enum Color
{GREEN = 1,RED,BLUE,GREEN_RED = 10,GREEN_BLUE
}ColorVal;

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

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

相关文章

C语言笔记(符号)

注释符号 几个似非而是的注释问题 例子&#xff1a; (A) int / * ... * /i; (B) char * s "abcdefgh //hijklmn"; (C) //Is it a \valid comment? (D) in/ * ... * /t i; 我们知道C语言里可以有两种注释方式&#xff1a;“/* */” 和 “ // ”。那么上面几条…

java 命令: jmap 命令使用 ( 查看内存使用、设置 )

jdk安装后会自带一些小工具&#xff0c;jmap命令(Java Memory Map)是其中之一。主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。 jmap命令可以获得运行中的jvm的堆的快照&#xff0c;从而可以离线分析堆&#xff0c;以检查内存泄漏&am…

只用一套解决方案,就可解决80%的交通物流行业信息难题

行业背景 新中国成立70多年来&#xff0c;中国交通运输总体上已经形成了多节点、全覆盖的综合运输网络&#xff0c;“五纵五横”综合运输大通道基本贯通&#xff0c;一大批综合客运、货运枢纽站场&#xff08;物流园区&#xff09;投入运营&#xff0c;取得了一系列瞩目成果&am…

Linux 使用 jstat 命令查看 jvm 的 GC 情况

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Options&#xff0c;选项&#xff0c;我们一般使用 -gcutil 查看gc情况 vmid&#xff0c;VM的进程号&#xff0c;即当前运行的java进程号…

Docker 方式安装 Nginx 、阿里云服务器上装 Ngnix

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 非 Docker 方式安装&#xff0c;直接 Linux 安装见另一文&#xff1a;Linux 上 安装 nginx 、阿里云服务器上安装 nginx 1. 直接从镜像仓…

C#实现A*算法

理解A*寻路算法具体过程 这两天研究了下 A* 寻路算法, 主要学习了这篇文章, 但这篇翻译得不是很好, 我花了很久才看明白文章中的各种指代. 特写此篇博客用来总结, 并写了寻路算法的代码, 觉得有用的同学可以看看. 另外因为图片制作起来比较麻烦, 所以我用的是原文里的图片. 当…

玩转数据结构——均摊复杂度和防止复杂度的震荡(笔记)

数据规模 时间复杂度 并不是所有的双层循环都是O&#xff08;n^2&#xff09;的 复杂度实验来确定复杂度 // O(N) 两倍增加 int findMax( int arr[], int n ){assert( n > 0 );int res arr[0];for( int i 1 ; i < n ; i )if( arr[i] > res )res arr[i];return res…

解决:bash: vim: command not found、docker 容器不识别 vi / vim 、docker 容器中安装 vim

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在 Docker 容器中编辑文件&#xff0c;报错如下&#xff1a; bash: vim: command not found2. 安装 vim &#xff1a; apt-get in…

怎样正确使用车灯?

当我们被对面来车明晃晃的远光灯照得意识模糊时&#xff0c;当你快速接近一辆摩托车却发现那是一辆坏了一盏尾灯的卡车时&#xff0c;或是当你前方的小车忽然亮起倒车灯却在往前行驶&#xff0c;最后意识到那只是因为刹车灯与倒车灯线路颠倒时&#xff0c;你就会发现在人们都认…

如何配置DDS以使用多个网络接口?How do I configure DDS to work with multiple network interfaces?

最近在使用OpenDDS的时候遇到一个问题&#xff1a;存在多个虚拟网卡时&#xff0c;发布&#xff08;订阅&#xff09;端重新连接时会阻塞几分钟&#xff0c;在外网找到一篇与此相关的文章。 You cannot specify which NICs DDS will use to send data. You can restrict the NI…

使用可靠多播与OPENDDS进行数据分发

介绍 也许应用程序设计人员在创建分布式系统时面临的最关键决策之一是如何在感兴趣的各方之间交换数据。通常&#xff0c;这涉及选择一个或多个通信协议并确定向每个端点分派数据的最有效手段。实现较低级别的通信软件可能是耗时的&#xff0c;昂贵的并且容易出错。很多时候&a…

margin为负值的几种情况

1、margin-top为负值像素 margin-top为负值像素&#xff0c;偏移值相对于自身&#xff0c;其后元素受影响&#xff0c;见如下代码&#xff1a; 1 <!DOCTYPE html>2 <html lang"zh">3 <head>4 <meta charset"UTF-8" />5 &l…

事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上)

用户模式的线程同步机制效率高&#xff0c;如果需要考虑线程同步问题&#xff0c;应该首先考虑用户模式的线程同步方法。但是&#xff0c;用户模式的线程同步有限制&#xff0c;对于多个进程之间的线程同步&#xff0c;用户模式的线程同步方法无能为力。这时&#xff0c;只能考…

axios 中文文档、使用说明

以下内容全文转自 Axios 文档&#xff1a;https://www.kancloud.cn/yunye/axios/234845 ##Axios Axios 是一个基于 promise 的 HTTP 库&#xff0c;可以用在浏览器和 node.js 中。 Features 从浏览器中创建 XMLHttpRequests从 node.js 创建 http 请求支持 Promise API拦截请…

数据库 -- 02

引擎介绍 1.什么是引擎 MySQL中的数据用各种不同的技术存储在文件&#xff08;或者内存&#xff09;中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术&…

OpenDDS用idl生成自定义数据类型时遇到的一个问题

问题&#xff1a;这里会提示LNK2005重复定义的错误 解决方案&#xff1a; 解决后&#xff1a;

Docker 方式安装 Nexus 私服

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 从Docker 官方仓库查找镜像&#xff1a; docker search nexus 2. 拉取镜像&#xff1a; docker pull 你选中的镜像的名字  pull…

shader飞线改进版

项目github地址&#xff1a;https://github.com/ecojust/flyline 前面写过一个飞线(基于THREE.Line进行的颜色变化)&#xff0c;只是简单地将可视区片元颜色的alpha通道值设为1.0&#xff0c;不在可视区的设为0.0。效果是这样的&#xff1a; 做得很粗糙&#xff0c;而且因为线是…

C++获取本机所有ip地址,可区分类型是有线无线虚拟机还是回环

一个小程序&#xff0c;可以获取本地所有ip地址&#xff0c;包括有线&#xff0c;无线&#xff0c;虚拟机&#xff0c;环回接口网卡&#xff0c;等。 如图&#xff0c;一台机器多个网卡&#xff1a; 程序执行结果&#xff1a; #include"stdio.h" #include"…

Mybatis 在 IDEA 中使用 generator 逆向工程生成 pojo,mapper

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 使用mybatis可以逆向生成pojo和mapper文件有很多种方式&#xff0c;我以前用的是mybtais自带的generator包来生成&#xff0c;连接如下&…