首页 > 代码库 > C#-访问轰炸机,新建进程,结束进程...(ConsoleApp)---ShinePans

C#-访问轰炸机,新建进程,结束进程...(ConsoleApp)---ShinePans

各位先看一下下面的题目,看看能否给出答案以及真正了解原因。

#include "stdio.h"
#include "string.h"
#include "malloc.h"

void swap(int a,int b){
int temp;
temp = a;
a = b;
b = temp;
}

int get_int(int a){
int i = 1 + a;
return i;
}

char* get_memory0(){
char *p = (char *)malloc(sizeof(char) * 20);
strcpy(p,"hello world");
return p;
}

char* get_memory1(){
char *p = "hello world";
return p;
}

char* get_memory2(){
char p[] = "hello world";
return p;
}

int main(){
int x=4,y=3;
swap(x,y);
int z=x-y;
printf("z = %d\n",z);//问题1

z=get_int(z);
printf("z = %d\n",z);//问题2

char* c0 = get_memory0();
printf("c0 = %s\n",c0);//问题3

const char* c1 = get_memory1();
printf("c1 = %s\n",c1);//问题4

char* const c2 = get_memory2();
printf("c2 = %s\n",c2);//问题5
}

问题1的答案:z=1,,对于这个答案,相信很多人都不会答错,都知道a和b没有发生交换。但是理解其中的原因吗?

swap(int a,int b)是一个参数传值得函数,这就意味着函数体内的a和b是参数int a和int b的实参在函数内的 一份局部拷贝,所以a和b实际可以看成是局部变量,它们的值是由int a和int b传的实参复制而来的。函数内a和b的值得改变只在函数体内部有效,当函数体内的a和b变量离开函数作用域的时候,a和b变量就被销毁了。函数的实参值并没有发生改变,或者说自始至终没有改变过,改变的只是它们在函数体内的一份局部拷贝a和b。


问题2的答案:z=2

int get_int(int a)属于返回值是传值的函数,这就意味着函数int get_int(int a)会在函数返回处产生一个临时对象,用户存放局部变量i的值的一份拷贝(变量i的右值的拷贝),临时对象是没有名称的,这份没有名称的对象的值(右值)会存储在调用者的“栈”中。所以当i作为局部变量离开作用域后,虽然被销毁了,但它的拷贝仍然存在,并在函数返回时作为“右值”赋给“左值z”。


问题3的答案:c0=“ hello world”

函数返回的是指向“堆”内存的在指针。程序中malloc()是用于分配“堆”内存的库函数,而对于“堆”内存,只要程序中没有调用free()库函数去释放该“堆”内存,那么在程序运行期间,malloc()库函数分配的“堆”内存将一直存在。char* get_memory0()会在函数返回处产生一个队返回变量p的“左值”的拷贝,也就是在“左值”的拷贝中存储了指向“堆”的地址。作为局部变量的p,在离开了函数作用域的时候,虽然被销毁了,但函数返回的“左值”的拷贝是存在的,该拷贝存储了指向“堆”的地址,而该“堆”的值是“hello world”。


问题4的答案:c1="hello world"

在char* p = “hello world”中,左值是 局部指针变量p,存储于函数栈上,右值是字符串常量“hello world”,存储于常量存储区。

char* get_memory 1()属于返回值是传指针的函数,这就意味着函数char* get_memory 1()会在函数返回处产生一个对返回对象的“左值”的拷贝,也就是在“左值”拷贝中存储了指向字符串常量“hello world”的地址。作为局部变量的p,在离开函数作用域的时候虽然被销毁了,但 函数返回的“左值“拷贝仍然存储了指向常量存储区的字符串常量”hello world“的地址。


问题5的答案:c2=未知

返回值是传指针,会在函数返回时产生”左值“拷贝。

 函数返回的”左值“拷贝指向的是局部变量数组p[12]的首地址。当局部数组p[12]离开作用域后会被自动销毁。这时,函数返回的”左值“拷贝指向的是一个被销毁的局部变量地址。

C#-访问轰炸机,新建进程,结束进程...(ConsoleApp)---ShinePans