第七章 指针与引用

来源:互联网 发布:学编程好找工作吗 编辑:程序博客网 时间:2024/05/22 13:58

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];
其运行结果如下图所示:


0 0
原创粉丝点击