C语言指针剖析

发表于:2015年4月18日 11:53  分类:c 527次浏览

在使用c语言编程解决实际问题的时候,一般都会定义各种的变量,包括基本数据类型、指针、数组、结构体等,然后调用库函数处理数据,或是自己编写函数处理,最后程序结束。如果c程序不允许变量,那么你必须手动对内存进行操作,类似汇编语言,在c程序底层,一切的操作都是将内存中的数据拿到寄存器中,再把寄存器中的数据放到内存中,都是指针的操作。所以只要有指针,就完全可以替代各种变量,甚至函数操作。

1、在虚拟8086模式下,使用turbo c 2.0 ,将一个字符c打印到屏幕正中间,要求不定义变量。

main()
{
	*(int far *)(0xb8000000 + 160*12 + 40*2) = 'c' + 0x200;
}

直接将常量拷贝到显存地址(0xb8000000 + 160*12 + 40*2)处,运用到了远指针跨段操作。
cupoint0

2、接上一个程序,将8个c打印到屏幕中间。

main()
{
	for(*(char far *)(0x200) = 0; *(char far *)(0x200) < 8; (*(char far *)(0x200))++)
	*(int far *)(0xb8000000 + 160*12 + (36+(*(char far *)(0x200)))*2) = 'c' + 0x200;
}

通过for操作符循环打印c共8次,其中的循环变量(*(char far *)(0x200)),使用了0:200处的一个字节存放。
cupoint1

3、修改程序2,体现变量的本质。

#define p ((int far *)(0xb8000000 + 160*12 + 36*2))
#define n (*(char far *)(0x200))

main()
{
	for(n = 0; n < 8; n++)
	p[n] = 'c' + 0x200;
}

将指针操作封装到宏里面,使用方法和定义一个变量完全相同,说明了变量的本质在于操作内存,而指针恰恰是为了直接操作内存而存在的;并且任何一块内存都可以看做是数组,采用指针[]的方式索引内存,每次增减的步长可以动态伸缩,具体取决于指针所指向的类型大小。

4、在屏幕中间打印一串彩色的字符串。

#define p ((int far *)(0xb8000000 + 160*12 + 36*2))
#define n (*(char far *)(0x200))

main()
{
	for(n = 0; *("Hello World!"+n); n++)
	p[n] = *("Hello World!"+n) + 0x200*(n+1);
}

常量字符串其实也是一个指针变量,指向类型为unsigned char,每加1,偏移1字节。

cupoint2

宏定义常量字符串,更新上面的程序。

#define p ((int far *)(0xb8000000 + 160*12 + 36*2))
#define n (*(char far *)(0x200))
#define str "Hello World!"

main()
{
	for(n = 0; str[n]; n++)
	p[n] = str[n] + 0x200*(n+1);
}

5、引入字符+颜色的结构体类型,简化程序4.2

typedef struct
{
	char ch;
	char color;
}Word;

#define p ((Word far *)(0xb8000000 + 160*12 + 36*2))
#define n (*(char far *)(0x200))
#define str "Hello World!"

main()
{
	for(n = 0; str[n]; n++)
	{
		p[n].ch = str[n];
		p[n].color = 0x2*(n+1);
	}
}

将p定义为指向Word类型的指针,+/-运算的步长为2字节,可以调用结构体成员ch和color。

6、将打印字符串的操作封装到一个函数中,用函数指针来调用这个函数。

typedef struct
{
	char ch;
	char color;
}Word;

#define str "Hello World!"
#define func (*(void (far **)(char *))(0x202))

void far print(char * s)
{
	#define p ((Word far *)(0xb8000000 + 160*12 + 36*2))
	#define n (*(char far *)(0x200))
	for(n = 0; s[n]; n++)
	{
		p[n].ch = s[n];
		p[n].color = 0x2*(n+1);
	}
	#undef n
	#undef p
}

main()
{
	func = print;
	(*func)(str);
}

定义了print函数,将函数指针指向该函数,使用指针来调用函数,说明了函数名其实是一个入口地址。

本文由李轶博的个人博客整理,转载请注明!本文链接地址:C语言指针剖析


最后编辑于:2015/1/9作者:李轶博

技术控一枚,互联网浪潮的追随者(非业界),喜欢折腾CODE,爱分享个人学习、生活经历。如果你喜欢李轶博的个人博客,欢迎和我一起交流!QQ:927796402

发表评论

电子邮件地址不会被公开。 必填项已用*标注