首页
关于 About
网站安全性 Security
Search
1
Chrome/Chromium 在 Linux 平台的视频硬解方案(含NVIDIA)
2,288 阅读
2
解决 Windows 11 提示“此模块被拒绝加载到本地安全机构”
1,469 阅读
3
关闭 Intel VMD 解决 INACCESSIBLE_BOOT_DEVICE 蓝屏
543 阅读
4
新版本 Chrome 122+ 关闭安全提示、扫描
429 阅读
5
连接 USB 设备到 WSL2
382 阅读
数字安全
教程
公告
默认
高通设备开发
Rockchip 设备开发
Windows
Android
Python
C 语言
登录
Search
标签搜索
Linux
Windows
Qualcomm
QCS8250
SM8250
高通
Android
Chrome
Chromium
AppArmor
PKI
OpenWrt
NVIDIA
CertificateTransparency
X509
Python
pip
Docker
Electron
WSL
日暮清林 Levi Marvin
累计撰写
25
篇文章
累计收到
12
条评论
首页
栏目
数字安全
教程
公告
默认
高通设备开发
Rockchip 设备开发
Windows
Android
Python
C 语言
页面
关于 About
网站安全性 Security
搜索到
17
篇与
的结果
2025-08-04
大学生期末必备!0基础快速入门C语言程序设计
C 语言零基础入门教程(基础版)版本:2025/08/04前言本来写这篇教程是为了期末周教一下室友,后面觉得也可以拿出来放到网上。本人只是一个业余 C 语言程序员,非专业 C 语言程序设计教师,亦无相关比赛参赛经验,文章内容有误还请指出。本文不涉及指针、数据结构相关内容(因为我的大学 C 语言程序设计课程也不考这些)。硬件基础键盘SHIFT:切换(上档),打出印有两行文字的按键中,上面一行文字的按键。CTRL:控制键,常与其他字母组合成快捷键。如复制Ctrl + C、粘贴Ctrl + V等。CAPS LOCK:大写锁定,按下后字母键均打出大写字母。TAB:缩进,自动添加四个空格或制表符,使得文字显示可以对齐。HOME:跳转到行首。END:跳转到行尾。操作系统基础所有的 C 语言程序必须有 main() 函数。操作系统在执行程序时,始终从 main 函数开始执行。程序结束后,必须给操作系统返回一个状态值,操作系统以此判断程序是否正常运行/退出。main函数是所有 C 语言程序的入口点,其函数一般以return+返回值结尾,用于向系统返回一个状态值。若使用return 0;代表程序正常退出(正常执行完毕),所有非0的返回值,代表程序出现故障,非零返回值的具体含义只有编写代码的人才知道,但操作系统知道“非0返回值代表程序运行出了问题”这个共识。计算机是无法直接运行程序的“源代码”的,源代码需要被“编译器”编译后,链接生成可以由计算机运行的“机器码”。这是高级编程语言的特性。全角字符和半角字符,中英文输入:中文的字符,!?“” —— 都是全角字符。英文的字符,! ? "" - 都是半角字符。C 语言程序代码中应当使用半角字符。操作系统的文件通常由两部分组成:文件名(Filename)和后缀(Suffix)。部分 Windows 系统会默认开启“隐藏已知文件的扩展名”(这里的扩展名就是文件后最)。文件后缀通常用以区分文件的类型。如.txt是文本文件,.xlsx是 Excel 表格,.mp3 是 MP3 格式音频文件,.h 是C/C++ 语言头文件等。C or C++什么是 C 语言,什么是 C++ 语言?顾名思义 C++ 与 C 相比,后面多了两个“++”,一看就更高级。从事实上来讲也确实如此。C 语言是面向过程的编程语言,程序设计的核心思想是“分步”,依次(按照时序图)实现所有需要的操作。C++ 语言是面向对象的编程语言,程序设计的核心思想是“对象”,可以使用“对象”支持的特性(如“多态”、“继承”等),通过将所需功能的实现载体抽象为许多不同的对象,实现对象间的操作,来实现程序的功能。比如在经典案例“学生管理系统”中,将“学生”抽象为Student对象,给这个对象实现了名字(name)、学号(number)、年级(year)等属性(变量),并实现对这些属性(变量)的操作。C++ 是兼容 C 语言的,但 C 语言不能使用 C++ 语言的代码。C 语言程序源文件通常以.c结尾,C++ 语言程序源文件通常以.cpp结尾。进制 —— 二进制、八进制、十进制、十六进制“进制” —— 一个数,不只有一位。例如在十进制中,我们有个位、十位、百位、千位...十进制的 1763日常生活中使用的是十进制,即满十进一,例如:10 + 10 = 209 + 1 = 1019 + 1 = 20二进制即为满二进一,例如:1 + 1 = 10 (不是十,十一零)0 + 1 = 110 + 1 = 11 (不是十一,是一一)11 + 1 = 100 (不是一百,是一零零)十六进制即为满十六进一,十六进制引入了字母来表示从 10 到 15 的“数”。即:0 1 2 3 4 5 6 7 8 9 a b c d e f。对应关系:DecHex0011223344556677889910a11b12c13d14e15f0x后跟十六进制数。 十进制 十六进制 十位 个位 十位 个位 0 9 0 f + ----------------------- 0 1 0 f 10 0x1eASCII(美国信息交换标准代码)ASCII(或习惯称“ASCII码”)为美国信息交换标准代码,ASCII码的第32~126为可读字符。也就是说我们的数字(可读字符形式)、字母(大写和小写)、符号(如感叹号、问号、警号、与号、星号等)都有一个唯一对应的数字(十进制、十六进制)来表示,这些“字符”可以和其唯一对应的数字相互转换。字符 十进制ASCII码0 48A 65a 97命名在 C 语言中,我们会遇到很多命名,变量的命名、函数的命名。C 语言编程中,所有的名字都是严格区分大小写的。例如 Abc 和 abc 和 abC,他们三个指代不同的东西。命名需要遵守命名规范。即:名称允许包含大小写英文字母和阿拉伯数字(不建议使用中文)和下划线,但是有条件:名称不得以数字开头,允许下划线开头;名称不得出现允许字符之外的字符(即只允许出现上述规定的字符);名称不得与 C 语言中现存“关键字”重复;一个变量/函数只能有一个“唯一的”名字,同一个名字不得重复使用。关键字:const/int/char/float/auto/register/extern/if/while...int a_b; int 0ac; // 错误 int Ab0; int _0a; int _; int Aiojsdajio; int a91ja; int const; // 错误 int inta; int int_jioa; int _int; int Abc = 0; int ABC= 0; int Abc =0; // 错误,不得与已定义变量名重复 变量变量的实质,是操作系统,根据变量的类型(所占的内存空间大小)向内存中分配一块恒定大小的内存空间区域,随后变量指向该内存区域的地址。使用变量的过程就是向该地址读写数据。基本数据类型int 整型:正整数、负整数、0short 短long 长long longlong long long...float 实型(单精度浮点型):精度为小数点后六(或七)位,多的位数会四舍五入到最后一位精度。double 实型(双精度浮点型):精度为小数点后十五位,多的位数会四舍五入到最后一位精度。char 字符型:单个字符void 无/空类型(特殊)注:使用prinf()函数%f/%lf输出时,float 和 double 默认保留 6 位小数,不足 6 位,以 0 补齐,超出则第 6 位会进行四舍五入。注:字符串必须用双引号包裹。char A = 'A'; char a = 'a'; char nihao = 'nihao'; // 错误 char A = "A"; // 可能错误 char *A = "A"; char *nihao = "Hello"; // 字符串(指针类型) char nihao[5] = "Hello"; // 字符串(数组类型) char nihao[5] = {'H', 'e', 'l', 'l', 'o'}; // 字符串(数组类型)变量的定义(存储类型) 数据类型 变量名 = 变量值(与类型匹配或支持类型转换);通常存储类型可以省略不写,不写则默认为auto(代表“动态变量”)。而存储类型表示变量的存储方式和位置。全局变量为static静态变量。如:int ZERO = 0; char A = 'A'; register int zero = 0; // 寄存器类型,变量会直接存储在 CPU 的寄存器中 static int _O = 'O'; // 静态类型,即使函数的生命周期结束,变量也不会被消失,且保留原值变量的初始化变量的初始化有两种方式:定义时赋值和先定义,后赋值(编译器会用默认值初始化)。int A = 0;int A; // 部分编译器会默认 A = 0 int main() { A = 1; // 此处对 A 人为赋值 return A; } 变量的赋值变量可以直接被赋值为固定值:int A = 100;也可以被赋值为某个函数的返回值:int _function() { return 333; } int main() { int A = _function(); printf("%d\n", A); return 0; }常量常量即长时间存在的量,不会改变,也不能改变,通常伴随整个程序或函数定义域内的生命周期。常量,我们用关键词const修饰,被const修饰的“变量”为不得修改的常量。常量的初始化必须在定义时进行。类型转换C 语言中,有很多不同的数据类型,比如整型、实型、字符型,实型甚至都分单精度浮点型和双精度浮点型。同时,我们还可以指定整型、实型、字符型变量有无“符号”(也就是是否能表示负数)。类型转换过程中,需要注意的核心要点是:数据精度和类型的兼容性。int A = 1; float B = 0.013f; int main() { // 第一种: B = A; // B 不是 1,是 1.0 // A 是整型int变量,B是实型float变量。转换过程精度增加。 // 第二种: A = B; // 精度减小。 } float A = 0.0000004f; double B = 0.0000000000013f; int main() { // 第一种: B = A; // 0.00000040000000... // 第二种: A = B; // 0.0 } float A = 0.0000004f; double B = 0.0000000000013f; int main() { // 第一种: B = A; // 0.00000040000000... // 第二种: A = B; // 0.0 } int main() { char A = 'A'; unsigned char result; result = A; }int main() { int a = -20000; unsigned int result; result = a; }数组数组:一组数据。数组取值时,需要用“数组下标”(又称“索引”)来去出数组中对应位数的数据。一维数组数据类型 数组名字[数组大小] = {数组的数据}数组大小:数组内元素的个数。数组的数据:数组内的数据,是由一个一个分开的单独的、独立的数据组成的。一组独立的数据构成数组。独立的数据类型应当与数组的数据类型一致。用逗号区分独立的数据。int asd[5] = {1, 2, 3, 4, 5}; // 取“3”值: asd[2]; int asd[5] = {1,2,3,4,5}; float dsa[2] = { 2.1, 3.4 };二维数组数据类型 数组名字[一维数组的个数][一维数组数据大小] = {数组的数据}int asd[4][5]; // 第九个元素 asd[a][b] a=1 b=3 // 0: 4 (5个) // 1: 3 (4个) // asd[1][3]生命周期 与 定义域int A = 0; // A 变脸的定义域/生命周期,是“全局”(GLOBAL) int f1() { int j = -1; // 定义域/生命周期仅限在f1函数内部。 for (int t = 2; t < 10; ++t) { // t 变量的定义域/生命周期仅限在f1函数内部的这个for循环中。 printf("%d ", t); } for (1) { printf("%d ", t); // 错误 // t 变量的定义域/生命周期仅限在f1函数内部的这个for循环中。 break; } printf("%d ", t); // 错误 return A; } int main() { int A = 1; // 错误,已有全局变量A int j = 1; // 可以,main函数的定义域找不到j变量。 printf("%d ", j); // 错误 return A; } 函数返回值类型 函数名(传入函数的变量) {//具体的代码}int main() { return 0; }函数的声明、实现和调用C语言中,函数的“声明”和“实现”可以分开。函数的调用中,必须在“被调用函数”声明后才可以调用该函数。例如在 A 函数中调用 B 函数,则需在 A 函数之前声明 B 函数。声明函数“签名”。返回值类型 函数名(定义传入函数的变量);实现返回值类型 函数名(定义传入函数的变量) { ... 具体的代码实现 ... }以下两个例子等价。int add(int a, int b) { // a, b 形参 int c = 10; //实参 return a+b; } int main() { return add(10, 11); } int add(int a, int b); int main() { c = 10; //实参 return add(1, 1); } int add(int a, int b) { return a+b; } void A() { return; } int B() { A(); return 0; }下面的用法是错误的:int main() { return add(1, 1); } int add(int a, int b) { return a+b; } 形参与实参返回值类型 函数名(定义传入函数的变量,即形参) { ... 具体的代码实现 ... }例如在函数中:int add(int a, int b) { // a 变量和 b 变量就是:形参,没有具体的值,具体的值由调用者决定 return a+b; } int main() { int result = add(1, 1); // 调用 add 函数,传入 a=1,b=1 printf("%d\n", result); return 0; }int add(int a, int b) { // a 变量和 b 变量就是:形参,没有具体的值,具体的值由调用者决定 return a+b; } int ab(int a, int b) { return a/b; } int main() { int a = 10; int b = 8; int c = add(a, b); // 等价于:c=a+b int d = ab(a, add(b, c)) + add(a, b); // 函数的嵌套调用 // 等价于:d=(a/(b+c))+(a+b) printf("%d\n", d); // d=18 return 0; }运算符数学运算符+ 加- 减* 乘法/ 除法日常生活中的数学运算中,各个符号的运算优先级同样适用于 C 语言编程。如,乘除运算优先级高于加减,我们可以使用小括号()来优先运算我们希望优先运算的运算。例如:int A = 1 + 2 * 3; // 结果为 7 int B = (1 + 2) * 3; // 结果为 9赋值运算符赋值运算符用“等于”号:=。i += a; 实际上是: i = i + a;i -= a; 实际上是: i = i - a;同理还有*=、/=等。指针运算符* 取值运算符,解引用运算符& 取地址运算符,获得指针地址比较运算符相等 ==(人 == 帅) 帅的话返回 TRUE 不帅则返回 FALSE不等 !=(人 != 可爱) TRUE FALSE或 || OR 满足一个即可与/且 && AND 同时满足(人 == 帅) && (人 == 可爱):如果人即帅又可爱,则返回TRUE,反之返回FALSE如果说只需要帅或者可爱满足一个条件即可,那么就用||(人 == 帅) || (人 == 可爱)! 取反值如果一个条件为真,你用“!”,则得到的值为假。如果说我们在只有一个人是不丑的情况下才执行操作:(人 != 丑)(人 == 帅)!(人 == 丑)// 除法 int printf_ab(int a, int b) { // b 是被除数,不能为0. if (b == 0) return 0; // 被除数不能为0,传入代码有无,函数返回错误值0 printf("%f\n", a/b); return 1; } int main() { int r = printf_ab(1, 0); // r=0 if (!r) printf("Error\n"); return 0; } 三元运算符<条件> ? (条件满足时执行) : (不满足时执行)例如:int a = 0; int b = (a == 0) ? 1 : 2; int c = (a != 0) ? 1 : 2; // 此时 b = 1, c = 2 int b = (a == 0) ? 1 : 2; if (a == 0) b = 1; else b = 2; return (a == 0) ? 0 : 1; // 返回0条件判断中的易错点“非 0 则真”:不论是正数还是负数,只要不是0,在条件中就代表为“真”,0代表“假”。int main() { int _TRUE = 1; int _FALSE = 0; if (_TRUE) { printf("TRUE\n"); } if (!_TRUE) { printf("TRUE?\n"); } if (!_FALSE) { printf("FALSE\n"); } if (_FALSE) { printf("FALSE?\n"); } return 0; }预编译指令与头文件预编译指令所有的预编译指令,均在源码中用井号(“#”)来开始。如 #include、#defineinclude 指令引入头文件,即将头文件的内容包含到源码文件中。已知,有两个文件:A.h和A.cA.h的内容为:int A = 0;A.c的内容为:#include <stdio.h> #include <A.h> int main() { printf("%d", A); return 0; }此时,如果在A.c中,不使用#include <A.h>,而且要实现相同的功能。我们可以这么写:#include <stdio.h> int A = 0; int main() { printf("%d", A); return 0; }define 指令define 指令通常用于“宏定义”。编译器,会在编译代码前,将所有宏定义,直接替换成定义的内容。#define HELLO "HELLO" #define HI hi // char *HELLO = "\"HELLO\""; int main() { printf("%s", HELLO); //相当于 printf("%s", "HELLO"); printf("%s", HI); //错误,相当于 printf("%s", hi); return 0; }上述代码中main()函数,实际等于:int main() { printf("%s", "HELLO"); return 0; }逻辑的力量(流程控制)一个程序必须要有相应的逻辑和流程控制,我们才能让程序实现我们想要的功能。判断 if (if...else if...else if...else)if (a == b) { // a等于b,执行 } // 不论a是否等于b,都继续往下执行 if (a == c) { // a等于c,执行 } else { // a不等于c,执行 }if (a == b) { // a等于b执行 } else if (a == c) { // 如果a不等于b,a等于c执行 } else { // 都不满足,执行这里 } 循环C 语言中有多种方式实现循环。跳出循环需要用 break 关键字,终止循环,继续执行循环外面的代码。继续下一个项需要用 continue 关键字。for (条件)对于 for (;...;) 这样的 for 循环,只要条件为真(非0或“TRUE”),便会一直循环执行内部的代码,除非条件不再为真(非0或“TRUE”)或者内部有代码跳出循环。for (;a == b;) { // ... if (a == c) break; if (a == d) // ... // ... } // ...for (初始化代码; 条件; 操作)对于 for (初始化代码; 条件; 操作) 这样的 for 循环,首先会执行一遍(且只会执行一遍初始化代码。随后:判断条件是否为真,若不为真,则终止循环,否则继续;循环执行内部的代码;执行操作;除非条件不再为真(非0或“TRUE”)或者内部有代码跳出循环。for (int i = 0; i < 10; i++) { // ... if (i == 5) break; // ... // ... } int i = -1; for (i = 0; i < 10; i++) { // ... if (i == 5) break; // ... // ... }while 或 do...whilewhile () { // ... if (i == 5) break; // ... }int uninitialized = 1; do { // 至少执行一遍,是否执行第二遍,看条件。 uninitialized = init(); // 如果初始化正常,init返回0,否则返回非0的数。 } while (uninitialized) // ...选择 switch (switch...case...default)switch (被判断的值) { case <条件1>: // 满足条件1的操作 case <条件2>: // 满足条件2的操作 // case ...: default: // 所有 case 的条件,都不满足,默认执行 }switch (被判断的值) { case <条件1>: // 满足条件1的操作 break; case <条件2>: // 满足条件2的操作 case <条件3>: // 满足条件3的操作 break; case <条件4>: case <条件5>: // 满足条件4或5的操作 break; // case ...: default: // 所有 case 的条件,都不满足,默认执行 break; }注释随着我们程序复杂度的增加,代码越写越多,人脑是有极限的,我们不可能会记住我们所有写的代码的功能、目的等。所以我们引入注释,来向人类解释或说明。编译器绝对不会理会任何注释。在编译时,编译器默认忽略全部的注释。在编译器看来“不存在”“注释”。单行注释// 我们要写的字// 第一行 // 第二行 // 第三行多行注释(块注释)/* 多行这么写 1234321 sadasd */ /* 一行这么写 */常见的 C 标准库与标准函数stdio.hmath.hstring.h
2025年08月04日
7 阅读
0 评论
0 点赞
2025-06-05
解决 Windows 11 提示“此模块被拒绝加载到本地安全机构”
前言部分国外开发的软件、程序等使用了一些第三方安全模块,但 Windows 11 自 22H2 起默认情况下开启了更高级别的安全防护,阻止将这些模块(如mdnsnsp.dll、prxernsp.dll)加载到本地安全机构(LSA)。对于新安装(例如重装系统等)的 Windows 11 22H2 及以上,Windows 会自动通过注册表启用 LSA 保护。对于从旧版本系统升级到 Windows 11 22H2 及以上的系统,一般情况下不会开启。解决方案方法一 使用注册表关闭(设备未使用 UEFI 变量来控制 LSA 保护)打开项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa找到 DWORD 值:RunAsPPL 和 RunAsPPLBoot。将其值全部修改为 0 即可。方法二 使用 UEFI 关闭(仅限于 UEFI 开启的安全防护)此时 RunAsPPL 于 NVRAM 中默认为 1,修改值为 0 即可。
2025年06月05日
1,469 阅读
0 评论
6 点赞
2025-04-07
RK3588 Linux & Android 开发备忘录
前言现在正在研究 Radxa Rock 5B,开发过程中遇到很多以前研究野火的鲁班猫5时候的问题。特写此文用以记录和备忘。问题与解决方案使用含 extlinux 的 boot 分区启动时,Linux 内核启动后无日志显示如显示 Starting kernel ... 或 I/TC: Secondary CPU X initializing 后无日志。解决方案:检查 extlinux.conf 文件中或内核编译时指定的内核命令(CMDLINE 或 BOOTCONFIG)中,是否指定了日志输出设备(如 console=tty1 等),如有则删去。刷入自行定制的 Debian 12 rootfs 并启动后,执行部分命令提示空间不足如显示 No space left on device 等,通过 df -h 命令查看挂载点的大小为 rootfs 镜像文件的大小,而非全部剩余空间(parameter.txt中的 grow)。使用命令 resize2fs /dev/mmcblk0p3 (后面的参数为实际的 rootfs 分区设备)即可。
2025年04月07日
56 阅读
0 评论
0 点赞
2025-02-19
GKI 2.0 内核启动时加载模块报错 Permission Denied 的解决方案
前言android15-6.6 内核编译后,打包镜像、DTB、内核模块到 AOSP,刷入后开机报错。查看日志发现 init 刚进入第一阶段,正在加载所有内核模块,结果第一个模块就报错,于是中止。研究发现内核模块的加载是错误码-EACCESS,查看代码分析发现是内核模块 exports protected symbol。该符号是定义在 abi_gki_protected_exports_aarch64 文件中的。因此要解决问题可以采用三个方案:built-in 内核模块修改该符号表禁用检查解决方案先尝试直接内置模块代码,不单独作为模块编译,结果其他模块都报错...估计是模块依赖的问题,要这样一个一个解决的话还不如把所有模块都内置了...于是果断选择方案三:禁用 CONFIG_MODULE_SIG_PROTECT。
2025年02月19日
182 阅读
0 评论
0 点赞
2024-07-23
新版本 Chrome 122+ 关闭安全提示、扫描
前言Google Chrome 新版本浏览器特别烦人,下载文件总会扫描浪费时间,在设置中关闭“安全浏览”禁止扫描又会提示已禁用“安全浏览”,无法验证文件安全性。解决方案使用 Chrome Enterprise Policy 即企业策略关闭相关限制。对于 Windows 平台可以使用注册表来导入,在HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome中添加下面四项 DWORD 十六进制值{alert type="info"}如果该注册表目录不存在,创建即可{/alert}DisableSafeBrowsingProceedAnyway=1DownloadRestrictions=0ForceGoogleSafeSearch=0ForceSafeSearch=0InsecureFormsWarningsEnabled=0SafeBrowsingEnabled=0SafeBrowsingProtectionLevel=0SafeBrowsingForTrustedSourcesEnabled=0也可以直接将下面的注册表文件导入:Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome] "DisableSafeBrowsingProceedAnyway"=dword:00000001 "DownloadRestrictions"=dword:00000000 "ForceGoogleSafeSearch"=dword:00000000 "ForceSafeSearch"=dword:00000000 "InsecureFormsWarningsEnabled"=dword:00000000 "SafeBrowsingEnabled"=dword:00000000 "SafeBrowsingProtectionLevel"=dword:00000000 "SafeBrowsingForTrustedSourcesEnabled"=dword:00000000 {message type="warning" content="下面的方法测试无效,但也可以尝试"/}打开 Chrome 内部设置 URL: chrome://settings/content/insecureContent 在“允许显示不安全内容”中添加[*.]com、 [*.]net、[*.]top、[*.]xyz、[*.]cn、[*.]su等
2024年07月23日
429 阅读
5 评论
1 点赞
1
2
...
4