当前位置: 首页 > news >正文

C语言基础学习之基本语法

写在前面

本部分看下枯燥无聊而又不得不看的基础语法。

0:零散知识点

0.1:typedef

typedef用来定义新类型,如:

// 定义一个新的无符号类型COUNT
typedef unsigned int COUNT;
COUNT counter;

// 定义一个新的结构体类型Simple2
typedef struct
{
    int a;
    char b;
    double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;

0.2:void *

void * 类型表示未确定类型的指针。C、C++ 规定 void * 类型可以通过类型转换强制转换为任何其它类型的指针。

1:宏和const定义常量

宏和const都可以用来定义常量,但是宏没有类型,且作用范围为整个文件,而const定义常量需要类型,且范围为对应的方法或者是代码块:

#include <stdio.h>

// 定义一个宏,无类型,全局使用
#define LENGTH 10
#define WIDTH 5
int main() {
    int size = LENGTH * WIDTH;
    printf("长: %d", LENGTH);

    printf("xxxx: %d", size);

    const float PI = 3.14159265758979;

    printf("呸是: %f", PI);

    return 0;
}

运行:

PS E:\vscode-workspace\C> cd "e:\vscode-workspace\C\" ; if ($?) { gcc includeAndConst.c -o includeAndConst } ; if ($?) { .\includeAndConst }
长: 10xxxx: 50呸是: 3.141593

2:sizeof

用来计算数据某数据类型的占用空间大小:

#include <stdio.h>
#include <float.h>

int main() {
   printf("int类型的大小:%d\n", sizeof(int));
   printf("float类型的大小:%d\n", sizeof(float));
   return 0;
}
int类型的大小:4
float类型的大小:4        

3:extern关键字

声明变量是外部变量:

#include <stdio.h>
 
// 函数外定义变量 x 和 y
int x;
int y;
int addtwonum()
{
    // 函数内声明变量 x 和 y 为外部变量
    extern int x;
    extern int y;
    // 给外部变量(全局变量)x 和 y 赋值
    x = 1;
    y = 2;
    return x+y;
}
 
int main()
{
    int result;
    // 调用函数 addtwonum
    result = addtwonum();
    
    printf("result 为: %d",result);
    return 0;
}
result 为: 3

也可以引用另一个文件中的变量,先定义addtwonum.c文件定义变量:

#include <stdio.h>
/*外部变量声明*/
extern int x ;
extern int y ;
int addtwonum()
{
    return x+y;
}

定义文件test.c引用变量:

#include <stdio.h>
  
/*定义两个全局变量*/
int x=1;
int y=2;
int addtwonum();
int main(void)
{
    int result;
    result = addtwonum();
    printf("result 为: %d\n",result);
    return 0;
}

测试:

PS E:\vscode-workspace\C> gcc .\addtwonum.c .\test.c -o main
PS E:\vscode-workspace\C> ./main
result 为: 3

4:整数常量后缀是 U 和 L

U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。

212         /* 合法的 */
215u        /* 合法的 */
0xFeeL      /* 合法的 */
078         /* 非法的:8 不是八进制的数字 */
032UU       /* 非法的:不能重复后缀 */

85         /* 十进制 */
0213       /* 八进制 */
0x4b       /* 十六进制 */
30         /* 整数 */
30u        /* 无符号整数 */
30l        /* 长整数 */
30ul       /* 无符号长整数 */

int myInt = 10;
long myLong = 100000L;
unsigned int myUnsignedInt = 10U;

5:&*

&获取变量指针,*通过指针访问变量值:

#include <stdio.h>
  
int a = 4;
// 定义int类型的指针
int* ptr;
int main(void)
{
    int a = 4;
    ptr = &a;    /* 'ptr' 现在包含 'a' 的地址 */
    printf("a 的值是 %d\n", a);
    printf("*ptr 是 %d\n", *ptr);
     

    return 0;
}
a 的值是 4
*ptr 是 4

6:通过sizeof和宏获取数组元素个数

6.1:使用sizeof

C语言并没有length之类的方法或者是属性来获取元素的个数,即数组的长度,但是可以通过sizeof来实现,思路是先获取总的内存占用大小,然后除以一个元素的内存大小就得到了元素的个数了:

#include <stdio.h>

int main() {
    int array[] = {1, 2, 3, 4, 5};
    // sizeof(array) 总占用大小  sizeof(array[0])一个元素占用大小
    int length = sizeof(array) / sizeof(array[0]);

    printf("数组长度为: %d\n", length);

    return 0;
}

运行:

数组长度为: 5

6.2:使用宏

如下:

#include <stdio.h>

#define LENGTH(array) (sizeof(array) / sizeof(array[0]))

int main() {
    int array1[] = {1, 2, 3, 4, 5};
    // 类似于函数调用,但实际不是,因为是在编译时会进行替换为
    // int length = (sizeof(array1) / sizeof(array1[0])) 这样的好处是如果有很多地方都需要获取数组的长度,就可以不需要写大量重复的代码了
    int length = LENGTH(array1);

    printf("数组长度为: %d\n", length);

    return 0;
}

运行:

数组长度为: 5

7:枚举enum

定义一个枚举类型,需要使用 enum 关键字,后面跟着枚举类型的名称,以及用大括号 {} 括起来的一组枚举常量。每个枚举常量可以用一个标识符来表示,也可以为它们指定一个整数值,如果没有指定,那么默认从 0 开始递增。
在C 语言中,枚举类型是被当做 int 或者 unsigned int 类型来处理的。
可以先定义枚举类型,再定义枚举变量,也可以定义枚举类型的同时定义枚举变量。看个例子:

#include <stdio.h>
 
// 定义枚举
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} oneDay; // 定义枚举的同时直接生成名一个变量
 
int main()
{
    // 定义DAY枚举类型的变量,并赋值为WED
    enum DAY day;
    day = WED;
    printf("rr %d\n",day);

    oneDay = SAT;
    printf("nn %d\n",SAT);

    return 0;
}

输出:

rr 3
nn 6

7.1:枚举在switch中使用

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    enum color { red=1, green, blue };
    // 定义枚举变量 favorite_color
    enum  color favorite_color;
 
    /* 用户输入数字来选择颜色 */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    // 将用户录入的值写到favorite_color的地址,即赋值到favorite_color
    scanf("%u", &favorite_color);
 
    /* 输出结果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是红色");
        break;
    case green:
        printf("你喜欢的颜色是绿色");
        break;
    case blue:
        printf("你喜欢的颜色是蓝色");
        break;
    default:
        printf("你没有选择你喜欢的颜色");
    }
 
    return 0;
}

输出:

请输入你喜欢的颜色: (1. red, 2. green, 3. blue): 1
你喜欢的颜色是红色

8:指针

想要成为一名优秀的 C 程序员,学习指针是很有必要的。
定义指针:

type *var_name;

在这里,type 是指针的基类型,它必须是一个有效的 C 数据类型,var_name 是指针变量的名称。在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

指针也就是内存地址(一个整数类型的长串,一般使用16进制的形式来表示)&获取变量地址,*通过变量地址访问变量值,小例子:

#include <stdio.h>
 
int main ()
{
    int var_runoob = 10;
    int *p;              // 定义int类型的指针变量
    // 获取变量地址
    p = &var_runoob;

    
   printf("var_runoob 变量的地址: %p\n", p);
   printf("通过*运算符获取var_runoob 变量的值: %d\n", *p);
   return 0;
}

var_runoob 变量的地址: 000000EF8E5FFC94
通过*运算符获取var_runoob 变量的值: 10

再一个例子:

#include <stdio.h>
 
int main ()
{
   int  var = 20;   /* 实际变量的声明 */
   int  *ip;        /* 指针变量的声明,int类型 */
 
   ip = &var;  /* &运算符获取变量的地址,并赋值到指针变量 */
 
   printf("var 变量的地址: %p\n", &var  );
 
   /* 在指针变量中存储的地址 */
   printf("ip 变量存储的地址: %p\n", ip );
 
   /* 使用*运算符通过指针访问值 */
   printf("*ip 变量的值: %d\n", *ip );
 
   return 0;
}

var 变量的地址: 000000FB01FFF864
ip 变量存储的地址: 000000FB01FFF864
*ip 变量的值: 20

8.1:NULL 指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:

#include <stdio.h>
 
int main ()
{
   int  *ptr = NULL;
 
   printf("ptr 的地址是 %p\n", ptr  );
 
   return 0;
}

ptr 的地址是 0000000000000000

在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

如需检查一个空指针,您可以使用 if 语句,如下所示:

#include <stdio.h>

int main()
{
    int *ptr = NULL;

    if (ptr)
    {
        printf("不是空指针啊!");
    } else {
        printf("空指针啊");
    }

    printf("\n");

    if (!ptr)
    {
        printf("使用!判断空指针啊");

    }

    return 0;
}

空指针啊
使用!判断空指针啊

8.2:指针内容(也比较重要)

在这里插入图片描述

8.3:函数指针

如其名称,为指向函数的指针,格式返回值类型 (*指针名称)(参数类型列表); ,如int (*fun_ptr)(int,int);
例子:

#include <stdio.h>
 
int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函数指针,指向函数max */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
 
    /* 与直接调用函数等价,d = max(max(a, b), c) */
    // 使用函数指针p执行两次函数调用
    d = p(p(a, b), c); 
 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

结果:

请输入三个数字:6
5
8
最大的数字是: 8

8.3:函数指针与回调函数

回调函数是将函数作为函数的参数,调用者传入,回调执行,例子:

#include <stdlib.h>  
#include <stdio.h>
 
// size_t相当于int getNextValue是函数指针的名称
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void)
{
    return rand();
}
 
int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    // 使用回调函数getNextRandomValue给数组myarray初始化值
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

执行:

41 18467 6334 26500 19169 15724 11478 29358 26962 24464

9:size_t

在C语言中,size_t 是一个表示大小的无符号整数类型,通常用于数组索引和循环计数器。它是由 typedef 定义的,不是一个新的数据类型,也不是关键字。size_t 的大小足以保证存储内存中对象的大小,其取值范围与机器架构和操作系统相关。在32位系统中通常是 unsigned int,而在64位系统中通常是 unsigned long。

size_t size = 5;
printf("%zu\n", size); // 显示5

10:C 字符串

在 C 语言中,字符串实际上是使用空字符 \0 结尾的一维字符数组。因此,\0 是用于标记字符串的结束。
空字符(Null character)又称结束符,缩写 NUL,是一个数值为 0 的控制字符,\0 是转义字符,意思是告诉编译器,这不是字符 0,而是空字符。 \0 可以省略不写,编译器会默认添加,但长度必须多一个,例子:

#include <stdio.h>
 
int main ()
{
   char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
 
   printf("菜鸟教程: %s\n", site );
 

   // \0 可以省略不写,编译器会默认添加,但长度必须多一个
   char site1[3] = {'A', 'B' };
 
   printf("菜鸟教程1: %s\n", site1 );

   return 0;
}

结果:

菜鸟教程: RUNOOB
菜鸟教程1: AB

11:常用函数

在这里插入图片描述
例子:

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[14] = "runoob";
   char str2[14] = "google";
   char str3[14];
   int  len ;
 
   /* 复制 str1 到 str3 */
   strcpy(str3, str1);
   printf("strcpy( str3, str1) :  %s\n", str3 );
 
   /* 连接 str1 和 str2 */
   strcat( str1, str2);
   printf("strcat( str1, str2):   %s\n", str1 );
 
   /* 连接后,str1 的总长度 */
   len = strlen(str1);
   printf("strlen(str1) :  %d\n", len );
 
   return 0;
}

结果:

strcpy( str3, str1) :  runoob
strcat( str1, str2):   runoobgoogle
strlen(str1) :  12

12:结构体

类似Java的对象,struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:

struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;

如:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

其他类型的定义实例:

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct
{
    int a;
    char b;
    double c;
} s1;

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
// 注意这里要带着struct关键字,如果是是使用typedef声明了新变量类型的话就不需要struct关键字了
struct SIMPLE t1, t2[20], *t3;

//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
// 这里使用typedef声明了新类型后就不需要在前面写struct关键字了
Simple2 u1, u2[20], *u3;

12.1:互相包含结构体

互相包含需要进行不完整声明,这样可以先用

struct B;    //对结构体B进行不完整声明

//结构体A中包含指向结构体B的指针
struct A
{
    struct B *partner; // 先使用不完整声明了
    //other members;
};

//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B
{
    struct A *partner;
    //other members;
};

12.2:结构体变量的初始化

#include <stdio.h>

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};

int main()
{
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}

运行:

title : C 语言   
author: RUNOOB   
subject: 编程语言
book_id: 123456  

12.3:访问结构成员

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);

   /* 输出 Book2 信息 */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

运行:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

12.4:结构体作为函数参数

#include <stdio.h>
#include <string.h>
 
// 定义结构体
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

/* 函数声明 */
// 注意这里要有struct关键字,如果是使用typedef的话就不需要了
void printBook( struct Books book );
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printBook( Book1 );

   /* 输出 Book2 信息 */
   printBook( Book2 );

   return 0;
}
// 注意这里要有struct关键字,如果是使用typedef的话就不需要了
void printBook( struct Books book )
{
   printf( "Book title : %s\n", book.title);
   printf( "Book author : %s\n", book.author);
   printf( "Book subject : %s\n", book.subject);
   printf( "Book book_id : %d\n", book.book_id);
}

运行:

Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700

12.5:使用sizeof计算结构体大小

#include <stdio.h>

struct Person {
    char name[20];
    int age;
    float height;
};

int main() {
    struct Person person;
    printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));
    return 0;
}

运行:

结构体 Person 大小为: 28 字节

13:联合体

使用关键字union,使用同一块内存来存储多种类型的变量,定义如下:

union [union tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];

union Data
{
   int i;
   float f;
   char  str[20];
} data;

13.1:占用大小

按照所需的最大类型分配内存,程序:

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   printf( "Memory size occupied by data : %d\n", sizeof(data));
 
   return 0;
}

运行:

Memory size occupied by data : 20

13.2:实战

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   data.i = 10;
   data.f = 220.5;
   strcpy( data.str, "C Programming");
 
   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

运行:

data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming

在这里,我们可以看到共用体的 i 和 f 成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是 str 成员能够完好输出的原因。

14:位域

C 语言的位域(bit-field)是一种特殊的结构体成员,允许我们按位对成员进行定义,指定其占用的位数。可以使用位域的类型只能为 int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型。正常如下:

struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status;

只需要增加: 长度就可以来定义位域了。如下:

struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status;

注意此时占用4个字节,因为最少要分配4个字节吧!
例子:

#include <stdio.h>
#include <string.h>

/* 定义简单的结构 */
struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status1;

/* 定义位域结构 */
struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status2;

int main( )
{
   printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
   printf( "Memory size occupied by status2 : %d\n", sizeof(status2));

   return 0;
}

运行:

D:\test>gcc -o one abc.c

D:\test>one.exe
Memory size occupied by status1 : 8
Memory size occupied by status2 : 4

15:头文件

头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。如:

#include <stdio.h>
#include <string.h>

15.1:标准库头文件

在这里插入图片描述

16:内存管理

内存管理相关函数如下:
在这里插入图片描述
函数可以在 <stdlib.h> 头文件中找到。

16.1:C 语言中常用的内存管理函数和运算符

在这里插入图片描述

17:命令行参数

执行程序时,可以从命令行传值给 C 程序。这些值被称为命令行参数,它们对程序很重要,特别是当您想从外部控制程序,而不是在代码内对这些值进行硬编码时,就显得尤为重要了。
函数原型:

int main(int argc, char *argv[]);
或者:
int main(int argc, char **argv);
argc (argument count): 表示命令行参数的数量,包括程序名本身。因此,argc 至少为 1。
argv (argument vector): 是一个指向字符串数组的指针,其中每个字符串是一个命令行参数。数组的第一个元素(即 argv[0])通常是程序的名称。接下来的元素是传递给程序的命令行参数。

例子:

#include <stdio.h>

int main( int argc, char *argv[] )
{
   if( argc == 2 )
   {
      printf("The argument supplied is %s\n", argv[1]);
   }
   else if( argc > 2 )
   {
      printf("Too many arguments supplied.\n");
   }
   else
   {
      printf("One argument expected.\n");
   }
}

运行:

D:\test>gcc -o one abc.c

D:\test>one.exe
One argument expected.

D:\test>one.exe aaaaa
The argument supplied is aaaaa

D:\test>one.exe aaaaa bbbbb
Too many arguments supplied.

D:\test>

18:系统头文件

类似工具类+常量类的组合。
在这里插入图片描述

写在后面

参考文章列表

菜鸟教程。

相关文章:

  • C++智能指针的使用
  • 服务器绑定 127.0.0.1 和 0.0.0.0 的区别
  • 深入理解 CSS 层叠上下文
  • 只需三步!5分钟本地部署deep seek——MAC环境
  • linux ollama deepseek等大语言模型的model文件的存储目录
  • 【Mastering Vim 2_01】开篇词:在 AI 时代持续深耕底层技术,做长期主义的坚定捍卫者
  • 【每日关注】科技圈重要动态
  • ArrayList、LinkedList、HashMap、HashTable、HashSet、TreeSet
  • 得物端智能视频封面推荐
  • WebSocket与Socket.io的区别
  • 将Docker容器打包成镜像提交
  • 评估多智能体协作网络(MACNET)的性能:COT和AUTOGPT基线方法
  • 今日学习总结
  • 【面试集锦】如何设计SSO方案?和OAuth有什么区别?
  • Open FPV VTX开源之OSD使用分类
  • 腿足机器人之二- 运动控制概览
  • Java NIO ByteBuffer 详解
  • 如何在Vscode中接入Deepseek
  • 【GIS】本地部署nominatim地理编码服务
  • TOML介绍
  • wordpress taobaoke/石家庄seo网站排名
  • 成都建设网站公司哪家好/白杨seo课程
  • 专业网站制作的公司/线上平台推广方案
  • 网上免费注册qq网站/网络公司网站模板
  • 上海专业网站建设案例/西安网站托管
  • 新沂网站制作/图片优化是什么意思