数据结构 study 1 -- C语言 传值 调用与 传址 调用 和 指针变量

仔细思考 下面的案例
#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两个变量还是会被销毁,但是我们已经将这块地址的值改变了,所以实际参数的值也会被改变,因为他们的地址是相同的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值