仔细思考 下面的案例
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/io.h>
#include<math.h>
#include<pthread.h>
int init_data_one(int *pt,int v1,int v2,int v3)
{
pt=(int *)malloc(3*sizeof(int));
if(!pt){
exit(1);
}
(pt)[0]=v1,(pt)[1]=v2,(pt)[2]=v3;
printf("调用初始化函数前 ,pt的三个值为:%d %d %d\n",pt[0],pt[1],pt[2]);
return 1;
}
int main()
{
int *pData ;
int ret;
ret = init_data_one(pData,5,7,9);
printf("调用初始化函数后,ret=%d(1:成功) pt的三个值为:%d %d %d\n",ret,pData[0],pData[1],pData[2]);
return 0 ;
}
ubuntu 下面 ,gcc 编译
程序运行
调用初始化函数前 ,pt的三个值为:5 7 9
Segmentation fault (core dumped)
修改之后:
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/io.h>
#include<math.h>
#include<pthread.h>
int init_data_one(int *pt,int v1,int v2,int v3)
{
pt=(int *)malloc(3*sizeof(int));
if(!pt){
exit(1);
}
(pt)[0]=v1,(pt)[1]=v2,(pt)[2]=v3;
printf("调用初始化函数前 ,pt的三个值为:%d %d %d\n",pt[0],pt[1],pt[2]);
return 1;
}
int init_data_two(int **ppt,int v1,int v2,int v3)
{
*ppt=(int *)malloc(3*sizeof(int));
if(!*ppt){
exit(1);
}
(*ppt)[0]=v1,(*ppt)[1]=v2,(*ppt)[2]=v3;
printf("调用初始化函数前 ,pt的三个值为:%d %d %d\n",(*ppt)[0],(*ppt)[1],(*ppt)[2]);
return 1;
}
int main()
{
int *pData ;
int ret;
//ret = init_data_one(pData,5,7,9);
ret = init_data_two(&pData,5,7,9);
printf("调用初始化函数后,ret=%d(1:成功) pt的三个值为:%d %d %d\n",ret,pData[0],pData[1],pData[2]);
return 0 ;
}
程序运行
调用初始化函数前 ,pt的三个值为:5 7 9
调用初始化函数后,ret=1(1:成功) pt的三个值为:5 7 9
抽象一下 数据类型:
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/io.h>
#include<math.h>
#include<pthread.h>
typedef int ElemType ;
typedef ElemType *Triplet;
int init_data_two(Triplet *ppt,ElemType v1,ElemType v2,ElemType v3)
{
*ppt=(ElemType *)malloc(3*sizeof(ElemType));
if(!*ppt){
exit(1);
}
(*ppt)[0]=v1,(*ppt)[1]=v2,(*ppt)[2]=v3;
printf("调用初始化函数前 ,pt的三个值为:%d %d %d\n",(*ppt)[0],(*ppt)[1],(*ppt)[2]);
return 1;
}
int main()
{
Triplet pData ;
int ret;
//ret = init_data_one(pData,5,7,9);
ret = init_data_two(&pData,5,7,9);
printf("调用初始化函数后,ret=%d(1:成功) pt的三个值为:%d %d %d\n",ret,pData[0],pData[1],pData[2]);
return 0 ;
}
再抽象一下
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/io.h>
#include<math.h>
#include<pthread.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status;
typedef int Boolean;
typedef int ElemType ;
typedef ElemType *Triplet;
int InitTriplet(Triplet *ppt,ElemType v1,ElemType v2,ElemType v3)
{
*ppt=(ElemType *)malloc(3*sizeof(ElemType));
if(!*ppt){
exit(1);
}
(*ppt)[0]=v1,(*ppt)[1]=v2,(*ppt)[2]=v3;
printf("调用初始化函数前 ,pt的三个值为:%d %d %d\n",(*ppt)[0],(*ppt)[1],(*ppt)[2]);
return 1;
}
Status Get(Triplet T,int i, ElemType *e)
{ /* 初始条件:三元组T已存在,1≤i≤3。操作结果:用e返回T的第i元的值 */
if(i<1||i>3)
return ERROR;
*e=T[i-1];
return OK;
}
int main()
{
Triplet T ;
int ret;
ElemType m;
//ret = init_data_one(pData,5,7,9);
ret = InitTriplet(&T,5,7,9);
printf("调用初始化函数后,ret=%d(1:成功) pt的三个值为:%d %d %d\n",ret,T[0],T[1],T[2]);
ret=Get(T,2,&m);
if(ret==OK){
printf("T的第2个值为:%d\n",m);
}
return 0 ;
}
C语言 传值 调用与 传址 调用
int x = 1, y = 2;
swap(x, y);
void swap(int a, int b)
{
…
}
外部变量,x,y 的值 赋值给 swap 内部的局部变量 a和b。
如果 x,y的类型是 int ,那么就是把 x,y的值赋值给a和b
如果 x,y的类型是 int *, 那么就是把 x,y指向的地址赋值给 局部变量a和b了。
指针变量 作为一个 变量 他是有一个地址的。指针变量的地址 是固定的,指针变量的值是可以变化的。
指针变量 作为 变量 他有一个值。这个值 ,同时是一个地址。
如果在函数内部,把 a 和 b的地址变化了,不会影响函数外部的x和y。
1:传值调用。
传值调用顾名思义就是将参数的值传递给函数,而函数在进行调用时会复制这个值,然后将复制的值在函数中进行调用。
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main(void)
{
int x = 1, y = 2;
swap(x, y);
printf("%d %d\n", x, y);
return 0;
}
这是一个swap函数,用来交换两个变量的值,然后在主函数中调用了这个函数目的是将x, y两个变量的值进行交换, 但是这个函数却达不到目的。
分析一下这个函数, 首先是一个void类型无返回值的函数,a和b是两个整型的形式参数,然后交换其两个变量的值。
主函数中 swap(x, y), x和y是实际参数, 函数在调用的时候首先会复制x和y的值, 我们将复制的值假设为n和m(n == x, m == y,但是&n != &x, &m != &y)意思就是值虽然相同 但是地址是不同的。
在函数中实际是对m和n的值进行调用, 改变了m和n的值, 但是退出函数时,这个值将会被销毁, 因为他是存储在栈上的,所以传值调用不改变实际参数的值。
传址调用
2:传址调用:传址就是将参数的地址传给函数进行调用。还是用刚才的swap函数的例子。
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main(void)
{
int x = 1, y = 2;
swap(&x, &y);
printf("%d %d\n", x, y);
return 0;
}
这个函数是将一个指向整型的指针当作参数传递,首先调用的时候还是会将参数进行复制,假设复制后的指针为p1和p2,(p1 == &x, p2 == &y),首先复制的指针的地址和实际参数的地址是相同的,然后再看函数,函数对指针进行间接引用,将指针所指向地址的值进行了改变,当退出函数时,p1和p2两个变量还是会被销毁,但是我们已经将这块地址的值改变了,所以实际参数的值也会被改变,因为他们的地址是相同的。