C语言(指针(中))

一、指针和数组

1、数组的指针

(1)一个变量有一个地址,一个数组则包含若干的元素,而每个数组元素都在内存中占用了内存单元,它们都有相应的地址,所谓数组的指针是指数组的起始地址。

(2)数组名表示数组的首地址,因此数组名也是一种指针

(3)通过数组名访问数组中的元素

int ch[] = {1,2,3,4};

//访问ch中的第3个元素:
ch[3] == 4;

//也可通过指针法引用数组中的元素:
*(ch + 3);

//如果想访问第n个元素
*(ch + n)
//注意:n<=sizeof(ch)/sizeof(ch[0])-1
/*
    1、假如有数组 int a[4]
    2、通过键盘上输入数字对数组a的每一个元素进行赋值
    3、打印处数组a中每一个元素的地址
    4、通过指针法将数组a中的每一个元素的值打印出来
*/

#include <stdio.h>

int main(){
	int a[4];
	int i;
	for(i=0;i<4;i++){
        printf("输入整数");
		scanf("%d",&a[i]);
	}
	for(i=0;i<4;i++){
        printf("结果");
		printf("%p,%d\n",&a[i],*(a+i));
	}
	
	return 0;
}

(4)通过指针变量间接访问数组

#include <stdio.h>

int main()
{
	int a[4] = {1,2,3,4};
    char ch[] = {'a','b','c'};

	int *p;
    char *p2;

	p = a;
    p2 = ch;

	*(p+2) = 100; //通过指针间接访问了数组a中下标为2的元素,并修改成100
	*(p2+2) = 'A';

    printf("%d\n",a[2]);
    printf("%c\n",ch[2]);
	
	return 0;
}
#include <stdio.h>


int main()
{ 
    int ch[] = {1, 2, 3, 4};

    printf("%d\n", ch[4]);
    printf("%p %p\n", &ch[3], &ch[4]);
    
    
    //数组名:数组的首地址
    printf("ch: %p\n", ch);
    
    //数组中的第0个元素的地址:数组的首地址
    printf("&ch[0]: %p\n", &ch[0]);
    printf("%d %d\n", ch[3], *(ch+3));
    
    int a[4];
    int i;
    for (i = 0; i < 4; i++)
    {
        scanf("%d", &a[i]); //a+i
        getchar();
    }
    
    //打印数组中每个元素的地址
    for (i = 0; i < 4; i++){
        printf("%p\n", &a[i]);
    }
    
    //通过指针法将数组a中的每一个元素的值打印出来
    for (i = 0; i < 4; i++){
        printf("%d\n", *(a+i));
    }
    
    int *p;
    p = a; //指针p指向了数组a
    
    //指针指向了一个数组,可以将指针当数组看待
    for (i = 0; i < 4; i++){
        printf("%d\n", p[i]); //通过下标发访问数组中的元素
    }
    
    // printf("%d\n", *(p+i));

    return 0;
}

(5)数组指针越界

#include <stdio.h>

int main()
{
    int b[4] = {10,20,30,40};
    int a[4];    
    a[4] = 100;

    printf("a[4]:%d\n",a[4]);
    printf("b[0]:%d\n",b[0]);
    printf("a:%u,b:%u\n",&a,&b); //打印数组a和b的首地址

    return 0;
}

2、指针数组

(1)指针数组就是:存放指针的数组,本质是数组,数组中的每个元素都是指针

#include <stdio.h>

int main()
{
    int a = 10,b = 20,c = 30;

    int *p[3];

    p[0] = &a;
    p[1] = &b;
    p[2] = &c;

    return 0;
}

(2)注意:int *p[3];等价于 (int*)p[3];因为[]比*的优先级要高先与p匹配

(3)思考:如何通过一个数组存储10个人的姓名?

char *name[10] = {"zhangsan", "lisi", "wangwu", "zhaoliu, "tianqi"};

name 数组中保存了10个字符串常量的首地址

注意:没有保存字符串常量而是常量的首地址

 3、指针变量的地址

(1)在定义指针变量的时候,编译器会分配一块空间来存储这个指针变量的值,分配的这块内存空间肯定有一个地址编码,那么这个地址编码肯定就是这个指针变量的地址。

#include <stdio.h>

int main()
{
    int a = 10;
    int *p;
    p = &a;
    
    //打印指针变量p的值以及变量a的地址(结果是相同的)
    printf("p:%p,a:%p\n",p,&a);

    //打印指针变量p的地址(存储指针变量的内存空间的首地址)
    printf("&p:%p\n",&p);

    return 0;
}

(2)注意:指针变量p的值保存的是另外一个变量a的地址,指针变量的地址是存储p这个指针变量的值的那块内存空间的首地址,这块空间保存的值是a的地址。 

4、一级指针作为函数的形参

(1)函数的形参为数组

如果函数的形参是数组,该形参的定义方法为:

void func(int a[],int n){}

也可以将形参定义为指针类型:

void func(int *a,int n){}

通常我们使用第二种方法

(2)调用函数时需要传递字符串可将形参设计为char*类型

#include <stdio.h>

void Print(char *p)    //调用函数时将字符串的地址赋值给指针变量p
{
    printf("%c\n",p[0]);
}

int main()
{
    Print("hello world!");
    return 0;
}

(4)注意:如果函数的形参是指针,在函数体中一般先对指针的值进行判断,判断指针的值是否为NULL。

二、二级指针

(1)一个指针变量保存一个一级指针变量的地址,这种指针我们叫做二级指针。

(2)二级指针的定义

数据类型 **变量名;

int a = 10;
int *p = &a;    //p为一级指针,保存变量a的地址
int **pp = &p;  //pp为二级指针 保存一级指针p的地址

 (3)二级指针的应用

//二级指针的应用

#include <stdio.h>

int main()
{
    int a =10;
    int *p = &a;
    int **p2 = &p;    //二级指针p2保存了一级指针p的地址(p2指向了p)
    int ***p3 = &p2;  //三级指针

    //*p2 == p == &a
    printf("%p %p %p\n",*p2,p,&a);

    //**p2 == *p == *(&a) == a
    printf("%d %d %d %d\n",**p2,*p,*(&a),a);
    **p2 = 100;
    printf("%d %d %d %d\n",**p2,*p,*(&a),a);

    //*p3 == p2 = &p
    //**p3 == *p2 == p == &a
    //***p3 == **p2 == *p == *(&a) == a    
    printf("***p3:%d\n",***p3);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值