首页
关于
README
Search
1
mdk3工具使用
156 阅读
2
Windows11pro 下载体验
122 阅读
3
关于C语言
120 阅读
4
关于Docker容器--0×01
119 阅读
5
关于本站
99 阅读
默认分类
网络技术
渗透测试
编程语言
C语言
Python
Linux
搞机技巧
Termux
golang
Search
标签搜索
printf
Toanle
累计撰写
24
篇文章
累计收到
78
条评论
首页
栏目
默认分类
网络技术
渗透测试
编程语言
C语言
Python
Linux
搞机技巧
Termux
golang
页面
关于
README
搜索到
4
篇与
C语言
的结果
2021-05-29
.data,.bss和.rodata段的区别与联系
在逆向工程中,我们在ELF格式的可执行文件中,全局内存包括三种:bss、data和rodata。其它可执行文件格式与之类似。了解了这三种数据的特点,我们才能充分发挥它们的长处,达到速度与空间的最优化。1、 bss(Block Started by Symbol)bss是指那些没有初始化的和初始化为0的全局变量和静态变量* ,bss类型的全局变量只占运行时的内存空间,而不占文件空间。另外,大多数操作系统,在加载程序时,会把所有的bss全局变量全部清零,无需要你手工去清零。但为保证程序的可移植性,手工把这些变量初始化为0也是一个好习惯。2、 data 与bss相比,data就容易明白多了,它的名字就暗示着里面存放着数据。当然,如果数据全是零,为了优化考虑,编译器把它当作bss处理。通俗的说,data指那些初始化过(非零)的非const的全局变量和静态变量。 由此可见,data类型的全局变量是即占文件空间,又占用运行时内存空间的。3、 rodata rodata的意义同样明显,ro代表read only,即只读数据(const)。只读数据段,存放常量,字符常量,const常量,据说还存放调试信息。关于rodata类型的数据,要注意以下几点: 常量不一定就放在rodata里,有的立即数直接编码在指令里,存放在代码段(.text)中。 对于字符串常量,编译器会自动去掉重复的字符串,保证一个字符串在一个可执行文件(EXE/SO)中只存在一份拷贝。 rodata是在多个进程间是共享的,这可以提高空间利用率。 在有的嵌入式系统中,rodata放在ROM(如norflash)里,运行时直接读取ROM内存,无需要加载到RAM内存中。 在嵌入式linux系统中,通过一种叫作XIP(就地执行)的技术,也可以直接读取,而无需要加载到RAM内存中。 由此可见,把在运行过程中不会改变的数据设为rodata类型的,是有很多好处的:在多个进程间共享,可以大大提高空间利用率,甚至不占用RAM空间。同时由于rodata在只读的内存页面(page)中,是受保护的,任何试图对它的修改都会被及时发现,这可以帮助提高程序的稳定性。4、 text通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。5、变量与关键字 static关键字用途太多,以致于让新手模糊。不过,总结起来就有两种作用,改变生命期和限制作用域。如: 修饰inline函数:限制作用域 修饰普通函数:限制作用域 修饰局部变量:改变生命期 修饰全局变量:限制作用域const 关键字倒是比较明了,用const修饰的变量放在rodata里,字符串默认就是常量。对const,注意以下几点就行了。指针常量:指向的数据是常量。如 const char* p = “abc”; p指向的内容是常量 ,但p本身不是常量,你可以让p再指向”123”。 常量指针:指针本身是常量。如:char* const p = “abc”; p本身就是常量,你不能让p再指向”123”。指针常量 + 常量指针:指针和指针指向的数据都是常量。const char* const p =”abc”; 两者都是常量,不能再修改。violatile关键字通常用来修饰多线程共享的全局变量和IO内存。告诉编译器,不要把此类变量优化到寄存器中,每次都要老老实实的从内存中读取,因为它们随时都可能变化。这个关键字可能比较生僻,但千万不要忘了它,否则一个错误让你调试好几天也得不到一点线索。
2021年05月29日
22 阅读
0 评论
1 点赞
2021-05-07
关于C语言argc与arcv参数
在C语言与C++编程中我们会经常看到(int argc, char *argv[])这两个参数那么他们有什么作用纳;C语言程式的main函数如果不需要读取任何来自于命令列的参数,则main函数就使用最简单的写法即可:#include <stdio.h> int main() { return 0; } 若需要将执行程式时,使用者所输入的命令列参数读取进来,则可在main函数中加上argc与argv两个参数:include <stdio.h>int main( int argc, char *argv[]) { printf( "We have %d arguments: n " , argc); for ( int i = 0 ; i < argc; ++i) {printf( "[ %d ] %s \n " , i, argv[i]);} return 0 ;}我们使用gcc编译:gcc -o argv argv.c执行时就可以在命令列输入要传给程式的参数: ./argv txst anle ss 输出如下: We have 4 arguments: [0] ./arcv [1] txst [2] anle [3] ss argv阵列中包含了在命令列中所输入的每一个参数,其中第一个元素是程式本身的名称(在这里就是./argv),之后就是执行时所输入的各个参数,其排列顺序就跟输入时的顺序相同。而argc是一个整数,其值就是argv阵列的长度。 若执行程式时,不加任何参数,argv的长度(argc的值)就会是1,也就是说argv就只包含程式本身的名称: 这是C++版本的程式码,argc与argv的用法完全相同: include <iostream>int main( int argc, char *argv[]) { std::cout << "We have " << argc << " arguments" << std::endl; for ( int i = 0 ; i < argc; ++i) {std::cout << "[" << i << "] " << argv[i] << std::endl;} return 0 ;}编译输出与上面一样; 有些人会把*argv[]写成**argv这种不同的写法,就像这样:int main( int argc, char **argv) { // ... }两种不同的写法都是通用的,使用上没有太大的差异。
2021年05月07日
21 阅读
0 评论
0 点赞
2021-03-09
关于C语言
0×00:C 语言是一门抽象的、面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首先要学的位置上。下面这幅图说明情况:可以看到,C 语言是一种底层语言,是一种系统层级的语言,操作系统就是使用 C 语言来编写的,比如 Windows、Linux、UNIX 。如果说其他语言是光鲜亮丽的外表,那么 C 语言就是灵魂,永远那么朴实无华。C语言特性那么,既然 C 语言这么重要,它有什么值得我们去学的地方呢?我们不应该只因为它重要而去学,我们更在意的是学完我们能学会什么,能让我们获得什么。C语言的设计C 语言是 1972 年,由贝尔实验室的丹尼斯·里奇(Dennis Ritch)和肯·汤普逊(Ken Thompson)在开发 UNIX 操作系统时设计了C语言。C 语言是一门流行的语言,它把计算机科学理论和工程实践理论完美的融合在一起,使用户能够完成模块化的编程和设计。计算机科学理论:简称 CS、是系统性研究信息与计算的理论基础以及它们在计算机系统中如何实现与应用的实用技术的学科。C语言具有高效性C 语言是一门高效性语言,它被设计用来充分发挥计算机的优势,因此 C 语言程序运行速度很快,C 语言能够合理了使用内存来获得最大的运行速度C 语言具有可移植性C 语言是一门具有可移植性的语言,这就意味着,对于在一台计算机上编写的 C 语言程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作量。C语言特点1.C 语言是一门简洁的语言,因为 C 语言设计更加靠近底层,因此不需要众多 Java 、C# 等高级语言才有的特性,程序的编写要求不是很严格。2.C语言具有结构化控制语句,C 语言是一门结构化的语言,它提供的控制语句具有结构化特征,如 for 循环、if⋯ else 判断语句和 switch 语句等。3.C语言具有丰富的数据类型,不仅包含有传统的字符型、整型、浮点型、数组类型等数据类型,还具有其他编程语言所不具备的数据类型,比如指针。4.C 语言能够直接对内存地址进行读写,因此可以实现汇编语言的主要功能,并可直接操作硬件。5.C 语言速度快,生成的目标代码执行效率高。
2021年03月09日
120 阅读
0 评论
1 点赞
2021-03-09
关于C语言使用printf的问题-编译系统求值时读取的顺序
今天在学习C语言的时候写到了如下的两端代码,简单来看,我一开始以为应该是一样的输出结果的,但是并不是这样。#include <stdio.h> int main() { int i=8; printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--); return 0; }代码段1与其执行结果:代码段2:#include <stdio.h> int main() { int i=8; printf("%d\n",++i); printf("%d\n",--i); printf("%d\n",i++); printf("%d\n",i--); printf("%d\n",-i++); printf("%d\n",-i--); return 0; }代码段2与其执行结果:一开始我是非常蒙的,但是后来网上找了一些资料以后发现,不同的编译器的求值的编译顺序是不同的。我使用的编译器是gcc,它的计算的顺序(注意:不是输出的顺序。)是从右往左的,网上看到的是说C语言的压栈顺序是从右往左。像代码段1的运算过程就是:i=8 → 输出-i → i=i-1 → 输出-i → i=i+1 → 输出i → i=i-1 → 输出i → i=i+1 → i=i-1 → i=i+1 → 输出i(即在一段运算中++i与--i的值与i的最终值相同)。而代码段2就是直接一个一个的输出,就是很正常的值了。OwO,关于即在一段运算中++i与--i的值与i的最终值相同
2021年03月09日
21 阅读
0 评论
0 点赞