第七章 指针与引用

1.1 传递动态内存

例题1

//copyer of variable
void swap1(int p, int q) {
int temp;
printf("before change, p q in swap1(): %p, %p\n", &p, &q);
printf("before change, p q in swap1(): %d, %d\n", p, q);
temp = p;
p = q;
q = temp;
printf("after change, p q in swap1(): %p, %p\n", &p, &q);
printf("after change, p q in swap1(): %d, %d\n\n", p, q);
}

void swap2(int *p, int *q) {
int *temp;
// error: There is not the allocate memory for point temp.
*temp = *p;
*p = *q;
*q = *temp;
}

// address change
void swap3(int *p, int *q) {
int *temp;
printf("before change, p q in swap1(): %p, %p\n", p, q);
printf("before change, *p *q in swap1(): %d, %d\n", *p, *q);
temp = p;
p = q;
q = temp;
printf("after change, p q in swap1(): %p, %p\n", p, q);
printf("after change, *p *q in swap1(): %d, %d\n\n", *p, *q);
}

// value change
void swap4(int *p, int *q) {
int temp;
printf("before change, p q in swap1(): %p, %p\n", p, q);
printf("before change, *p *q in swap1(): %d, %d\n", *p, *q);
temp = *p;
*p = *q;
*q = temp;
printf("after change, p q in swap1(): %p, %p\n", p, q);
printf("after change, *p *q in swap1(): %d, %d\n\n", *p, *q);
}

void swap5(int &p, int &q) {
int temp;
printf("before change, &p &q in swap1(): %p, %p\n", &p, &q);
printf("before change, p q in swap1(): %d, %d\n", p, q);
temp = p;
p = q;
q = temp;
printf("after change, &p &q in swap1(): %p, %p\n", &p, &q);
printf("after change, p q in swap1(): %d, %d\n\n", p, q);
}

//change two pointers
void swap6(int **p, int **q) {
int temp;
printf("before change, p q in swap1(): %p, %p\n", p, q);
printf("before change, *p *q in swap1(): %p, %p\n", *p, *q);
printf("before change, **p **q in swap1(): %d, %d\n", **p, **q);
temp = **p;
**p = **q;
**q = temp;
printf("after change, p q in swap1(): %p, %p\n", p, q);
printf("after change, *p *q in swap1(): %p, %p\n", *p, *q);
printf("after change, **p **q in swap1(): %d, %d\n\n", **p, **q);
}

int main() {
int a = 1, b = 2;
int *p = &a; 
int *q = &b;
printf("before swap: a = %d, b = %d\n", a, b);
printf("before swap, p: %p, q: %p\n\n", p, q);
//swap1(a, b);
//swap2(&a, &b);
//swap3(&a, &b);
//swap4(&a, &b);
//swap5(a, b);
//swap6(&p, &q);
printf("after swap: a = %d, b = %d\n", a, b);
printf("after swap, p: %p, q: %p\n", p, q);
return 0;
}


通过函数调用,交换两个数,必须在调用函数里面操作到数,而不是其指向的地址。

当运行swap1()后,结果如下:可以看出传递的是参数的副本:在调用之前&a = 0x001af9b4, &b = 0x001af9a8,
在函数体内其参数副本为&p = 0x001af8b8, &q = 0x001af8bc。即在函数体内是对副本的操作,并不影响其传入的
参数值。


当运行swap2(), 会出现执行错误,没有分配内存空间。

当运行swap3(),运行结果如下:p,q分别指向a,b的地址。在函数体内,对a,b的地址
进行了交换,并没有对其地址里的数a,b进行交换。


当运行swap4(),运行结果如下:在函数体内,对操作数进行交换。


当运行swap5(),运行结果如下:引用传递,是变量的别名,相当于是对同一变量的操作。


当运行swap6(),运行结果如下:函数体内对操作数进行操作。


例题2

#include <stdlib.h>
#include <string.h>

//pointer copyer
void GetMemory(char *p, int num) {
printf("p in the GetMemory(): %p.\n", p);
p = (char *)malloc(sizeof(char*) * num);
printf("p in the GetMemory(): %p.\n", p);
}

void *GetMemory1(char *p, int num) {
p = (char *)malloc(sizeof(char*) * num);
printf("p in the GetMemory1(): %p.\n", p);
return p;
}

void GetMemory2(char **p, int num) {
*p = (char *)malloc(sizeof(char*) * num);
printf("*p in the GetMemory2(): %p.\n", *p);
}

int main() {
char *str = NULL;
printf("str: %p\n", str);
//GetMemory(str, 100);
//printf("str: %p\n", str);
//return 0;

//str = (char *)GetMemory1(str, 100);
//GetMemory2(&str, 100);
//printf("str: %p\n", str);
strcpy(str, "hello");
printf("*str char output: %c, str string output : %s", *str, str);
return 0;
}


当运行GetMemory() 函数后,其结果如下所示:虽然在GetMemory() 函数中分配了从地址0x00031AD0开始的一片内存,
但当从子函数结束后,并不能把其地址空间给函数体外面的指针变量,str还是指向0x00000000的地址。


当运行GetMemory1()函数后,其结果如下所示:在子函数GetMemory1()中,分配了从地址0x00501AD0开始的一片内存,
并通过函数返回这片内存空间。


当运行GetMemory2()函数后,其结果如下所示:这个相当于对传入的str的地址进行了操作。*p指向了&str的地址


例题3

//string constant is saved at read-only data segment; global 
//variable is saved at static memory region; local variable is 
//saved at stack.
char *strA() {
char str[] = "hello world";
return str;
}

char *strA1() {
char *str = "hello world";
return str;
}

char *strA2() {
static char str[] = "hello world";
return str;
}

int main() {
char *str = NULL;
str = strA();
printf("strA: %p, %s\n", str, str);
str = strA1();
printf("strA1: %p, %s\n", str, str);
str = strA2();
printf("strA2: %p, %s\n", str, str);
return 0;
}



运行结果如下所示:
strA()函数中"hello world"存在栈中,而存放于栈中的数据,当离开本函数后,其数据空间会被释放或由其他的程序使用,所以会出现下面输出该字符串的乱码现象。
strA1()函数中的“hello world”是字符串常量,它存放于只读的数据段,与是否离开本子函数体无关。
strA2()函数中的"hello world"存放在静态存储区,与是否离开本子函数体无关。

例题4

// pointer's subtraction must be the same type. 
int main() {
int a[3] = {1, 2, 3};
char b[3] = {'c', 'd', 'e'};
int *p, *q;
char *p1, *q1;
p = a;
q = &a[2];
//q-p = (&a[2] - &a[0])/sizeof(int);
printf("int a[q - p]: %d\n", a[q - p]);
p1 = b;
q1 = &b[2];
//q1-p1 = (&b[2] - &b[0])/sizeof(char);
printf("char b[q1 - p1]: %c\n", b[q1 - p1]);
return 0;
}


运行结果如下图所示:指针的减法必须要是同一类型,且为地址差除以类型大小。


1.2 函数指针

例题1

int max(int x, int y) {
return x > y ? x : y;
}

int main() {
int a = 0, b = 0, c = 0, d = 0;
int max(int, int);
int (*p)(int, int) = &max;
printf("please input three integer:\n");
scanf("%d%d%d", &a, &b, &c);
d = (*p)((*p)(a, b), c);
printf("maximum is %d among %d, %d, %d", d, a, b, c);
return 0;
}


运行结果如下:


1.3 指针数组和数组指针

例题1

int main() {
int i = 0;
int v[2][10] = {{1,2,3,4,5,6,7,8,9,10}, {11,12,13,14,15,16,17,18,19,20}};
//a pointer has ten int array. array pointer
int (*a)[10] = v;
for(i = 0; i < 2; i++)
printf("*a[%d]: %d\n\n", i, *a[i]);


printf("a: %p, **a: %d\n\n", a, **a);
printf("a+1: %p, **(a+1): %d\n\n", a+1, **(a+1));
printf("*a: %p, (*a+1): %p, *(*a+1): %d\n\n", *a, (*a+1), *(*a+1));
printf("a[0]: %p, a[0]+1: %p, *(a[0]+1): %d\n\n", a[0], a[0]+1, *(a[0]+1));
printf("a[1]: %p, *a[1]: %d\n", a[1], *a[1]);
return 0;
}


a是指向一个10个Int元素的数组v的指针。a+1,a[1]都表示a指针向后移动10个Int元素大小。
*a, a[0]都指向了数组v的第一个Int元素。

运行结果如下图所示:


例题2

int main() {
int a[] = {1, 2, 3, 4, 5};
int *ptr = (int*)(&a+1);
printf("&a: %p, &a+1: %p\n", &a, &a+1);
printf("*(a+1): %d, *(ptr-1): %d\n", *(a+1), *(ptr-1));
return 0;
}


运行结果如下图所示:数组名本身就是一个指针,再加&就为双指针(二维数组):当双指针+1时,数组整体加一行。


例题3

int main() {
int i = 0;
// pointer array. pointer a[0] pointer to the address of hello,....
char* a[3] = {"hello", "the", "world"};
//pointer pa points to pointer a[0];
char **pa = a;
for(i = 0; i < 3; i++) {
printf("&a[%d]: %p, a[%d]: %p, *(a[%d]): %c \n", i, &a[i], i, a[i], i, *(a[i]));
}
printf("pa: %p\n", pa);
pa++; //a[1]
printf("pa: %p\n", pa);
printf("*pa: %p, *pa: %s, **pa: %c\n", *pa, *pa, **pa);
return 0;
}


char* a[3] = {"hello", "the", "world"}:表示指针a[0]指向hello常量字符串;指针a[1]指向the常量字符串;指针a[2]指向world常量字符串;
char **pa = a:表示指针pa指向指针a[0];
pa++:指向指针a[1];
其运行结果如下图所示:


说起 Flash 反编译,大家肯定会想到闪客精灵,但是闪客精灵己被国内软件代理商代理,所以想要长期使用,你必须购买正版。网上的闪客精灵特别版也不好找,但是今天小编(www.dayanzai.me)给大家分享的 Flash Decompiler Trillix 5.3.1370 汉化版它闪客精灵的界面上非常相似,而且功能上感觉也差不多,所以想反编译 Flash 的童鞋这也是一个不错的选择哦!Flash 反编译工具 Flash Decompiler Trillix 中文版Flash 反编译工具 Flash Decompiler Trillix 中文版Flash Decompiler Trillix 5.3.1400 汉化版让您转换 Adobe Flash SWF 文件返回到 FLA 格式,可以在原生 Flash 环境中进行编辑。Flash EXE 文件反编译的方法一样常见的 SWF 文件。 Flash Decompiler Trillix 5.3.1370 汉化版也可以转换成 Adobe 的 Flex 文件,由 Adobe Flex Builder 中创建的。Flash Decompiler Trillix 汉化版为您提供有关整个 Flash 影片,它的形状,图像,摇身一变等的详细信息,也追踪他们的位置在框架精灵,甚至挽救框架, ActionScript精灵的原始名称。除了转换成FLA ,Flash Decompiler Trillix 5.3 汉化版可以提取SWF文件中使用到各种格式的文件只是在几个点击的所有对象(图像,声音,视频,图形,文字,摇身一变,动作等) 。Flash Decompiler Trillix 汉化版独特的编辑选项让你无需转换为FLA编辑SWF文件的声音,图像,形状’的颜色,形状’行,静态/动态文本静态链接。你一定会欣赏全球ActionScript中搜索在所有的Flash电影,你必须在任务列表中,以及在特定的脚本的ActionScript搜索。此外,您可以自定义所有的SWF为FLA转换过程中通过配置补间动画,变形, FLA ,文字,动作的选择,等等。Flash Decompiler Trillix 5.3 汉化版还设有两个Web插件的Internet ExplorerFirefox保存Flash动画在线。Flash Decompiler Trillix 5.3.1400 汉化版特点:修改受保护的SWF文件如果您忘记了密码,您的SWF文件,它是没有问题的任何更长的时间。 Flash反编译Trillix绕过而反编译SWF文件资源的这种保护机制。一旦你将它转换为FLA ,你可以在你喜欢的闪存编辑器中设置新的保护。提取SWF文件的对象Eltima Flash Decompiler Trillix 5.3.1400 汉化版允许你提取的SWF文件中的所有资源投入到各种格式的文件只是在几个点击。 ActionScript中可以提取到AS或TXT ( P码或十六进制转储,或两者兼有) 。形状,摇身一变,字体,按钮,精灵框架可以被提取成SWF或FLA 。图像,声音,视频,文本二进制数据可以分别提取到SWFFLA还为其他格式(如JPEG , PNG或BMP格式图像) 。无需转换为FLA编辑SWFFlash Decompiler Trillix 5.3.1400 汉化版可以让你无需转换为FLA编辑SWF文件中的元素(声音,图像,形状’的颜色,形状’行,静态/动态文本静态链接) 。此外,你可以预览你保存它们之前所做的更改。Flash Decompiler Trillix 全功能列表:Flash Decompiler Trillix 5.3.1400 汉化版进行数字签名支持Flash的5 , 6 , 7 , 8 , 910支持的Adobe Flash Player专业CS6Flash文件转换到Adobe的Flash CS5的文件格式( XFL – 基于XML的FLA )支持的ActionScript 1.0 , 2.03.0SWF文件转换为基本标准的Flash预加载(如文件使用TLF文本)新支持嵌入到SWF文件作为二进制数据(嵌套的SWF文件)的SWF文件新批量反编译转换的Flash文件反编译EXE文件(投影机)的文件支持内置在Flex的SWF文件( v3v4支持)查看您的SWF的核心文件直接在Flash反编译Trillix在预览播放Flash影片内置Flash播放器编辑Flash对象,无须转换为FLA预览编辑,保存更改之前的SWF文件提取所有的Flash文件资源转化为各种格式的SWF为FLA转换的详细配置将SW
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值