c语言入门指针,C语言入门学习(第十天——指针)

本文深入讲解C语言中的指针,包括内存如何存储变量、取址与解引用操作、指针变量的定义以及指针与数组的交互。通过实例解析了指针如何作为数组的索引,以及指针数组和数组指针的概念。此外,还介绍了二重指针在处理多维数组时的作用。
摘要由CSDN通过智能技术生成

镇楼图

3011da53236cd7e7bc8081dc65f9980a.png

Pixiv:WANKE

这一次来讲一下指针,指针的内容特别多而且较难理解,希望大家别被劝退。

============

内存是如何存放变 量的?

一个变量是如何通过变量名来索引内存中存储的值呢?

内存的最小索引单元为1个字节,内存的索为字节。

在我们看来变量可能是这么取值:

【变量名】→【值】

但实际上是:

【变量名】→【内存地址】→【值】

编译器只知道【变量名】对应的是【内存地址】,通过对【内存地址】的索引来得到值

c89e6434331d20669b9c6af558638247.png

============

取址运算符、解引用运算符

*为解引用运算符

获取这个变量对应的内存地址

int *a = 0;

//含义:a的内存地址为0

&为取址运算符

获取这个变量的地址所对应的值

int *a=0;

int b = 3;

a = &b;//a的地址赋值为b的地址

printf("%d",*a);

//变量的值变了,变量的值会变

//变量的地址变量,变量的值也会变

现在你可以通过变换内存地址的方式来完成赋值啦~

============

定义指针变量

数据类型表明了定义的指针指向哪个数据类型;*表示取址也就是指针;后面为变量名

后面表明了指针初始的地址

什么类型的指针就只能存放什么类型的数据,但指针有跨类型的例外,下面会说明

int *a = 0;

野指针

int *a;

如果我写成这样,就代表没有初始化,没有初始化可能让内存指向一个会出现bug的内存地址,一定要避免这种写法。

NULL空指针

long *a = 0;

long *b =NULL;

printf("%p\n",a);

printf("%p",b);

空指针的定义能保证指针不会成为野指针,防止出现bug。

但空指针无法被赋予值,一定会出现bug,因为空指针代表没有内存,没有内存自然无法赋值

unsigned int *a = 0;

*a = 100;

printf("%d",*a);

//空指针无法赋值

注意NULL和NUL的区别!

void通用指针

void *a = 1;

int num = 1024;

int *pi = #

char *ps = "LIKE";

void *pv;

pv = pi;

printf("pi:%p, pv:%p\n",pi,pv);

pv = ps;

printf("ps:%p, pv:%p\n",ps,pv);

//pv既能到int上也能到char上

void指针的强大之处在于它可以指向任意类型你可以指向char、int、long、bool都可以!

但不可以引用,因为编译器并不知道类型,但有一种解决方法——类型强制转换

char *ps = "LIKE";

void *pv;

pv = ps;

printf("%s\n",(char*)pv);

int *a = 100;

pv = a;

printf("%s\n",*(int*)pv);

============

指针与数组

int a;

int* p=&a;

printf("请输入整数");

scanf("%d",&a);

printf("\n结果为%d",a);

printf("\n请重新输入整数");

scanf("%d",p);

printf("\n结果为%d",a);

printf("\n结果为%d",*p);

char str[120];

printf("请输入字符");

scanf("%s",str);

printf("\n结果为%s",str);

由上段代码可以得知,数组名就是首个元素的地址

str

&str[0]

这些形式都是等价的.

事实上 a[0] 、a[1]...a[i] 代表的都是值,a、(a+0)、(a+1)、(a+i) 代表的是地址;另外这里的 a 代表整个数组的首地址,相当于 a[0] 的地址,而这里 (a+1) 就代表的是 a[0+1] 的地址。

int a[10];

bool b[10];

char c[10];

double d[10];

printf("a[0]的地址是 %p",a);

printf("a数组地址是%p",&a);

现在可以使用指针的方法来检索数组

int a[100];

int* p = a;

for (int i = 0;i < 100;p++,i++){

*p = i;

printf("a[%d] = %d\n",i,a[i]);

}

//p++并不是简单地址的值+1,而是地址到下一个元素的地址

符号

具体含义以及区别

a

数组首元素地址(指向首个元素)

&a[0]

数组首元素地址(指向首个元素)

&a

数组地址(指向数组整体)

&a+1代表整个数组的长度+1也就是数组最后一个元素的位置

a+1只代表首元素到第二个元素,可以将上述代码再简化为以下代码

数组本身作为地址常量,无法进行运算;而指针可以进行运算

int a[100];

for (int i = 0;i < 100;i++){

a[i] = 2*i;

printf("a[%d] = %d\n",i,*(a+i));

}

char *p1[5]={"12","23","34","45","56"};

int i;

for (i = 0; i < 5; i++){

printf("%s\n", p1[i]);

}

//用指针定义的字符串数组略微特殊

============

指针数组与数组指针

int *p1[5];

//指针数组

int (*p2)[5];

//数组指针

指针数组

*p1[5]

首先[]的优先级比*要高,先定义了p1[5]这个数组,然后类型是指针类型,所以元素存储的是内存地址,就是一组存储指针的元素,简称指针数组。

char *p[3] = {

"我",

"真",

"帅"

};

for (int i = 0;i<3;i++){

printf("%s",p[1]i);

}

数组指针

int (*p)[5]

这一次凭着括号,先定义了指针,再由这个指针去指向一个数组(整体),这个就称为数组指针

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

int (*p)[5] = &a;

//注:数组指针需要指向整体,不能写成a而要写成&a。

int i;

for (i = 0; i < 5; i++){

printf("%d\n", *(*p + i));

//p指向了数组的地址,而*p指向了首元素地址,**p为首元素,如果你看到这里感到困惑的话下一章的二重指针将能解决你的疑问

}

return 0;

============

二重指针

假设存在一个数组array[50],现在我们知道array[0]代表首元素,array或者&array[0]代表首元素地址,而&array代表了整个数组的地址(虽然值与array一致)。

这直接构成了一个逻辑关系,而我们也可以利用指针来更加明确这个关系。

array[n]←*(array+n)第n个元素

array←首元素地址

&array←

int array[5] = {2,3,4,5,6};

int (*p)[5] = &array;

//现在p就是数组地址,*p就是首元素地址,**p则代表了首元素

for (int i = 0; i < 5; i++){

printf("%d\n", *(*p + i));

}

当为二维数组时关系变成为了这样,一维指针已经不够用了,需要用二维指针

array[m][n]←*(*(array+m)+n)第二维第m行第n列

array[m]←*(array+m)第一维第m行

array←首元素地址

int array[4][5] = {0};

int i,j,k = 0;

for(i = 0;i<4;i++){

for(j = 0;j<5;j++){

array[i][j] = k++;

}

}

printf("*(array+1):%p\n",*(array+1));

printf("array[1]:%p\n",array[1]);

printf("&array[1][0]:%p\n",&array[1][0]);

printf("**(array+1):%d\n",**(array+1));

int (*p)[4] = array;

printf("**(p+1):%d\n", **(p+1));

printf("**(array+1):%d\n",**(array+1));

printf("array[1][0]:%d\n",array[1][0]);

/*

如果这么定义

int *p = array;

那一定会出错的,为什么在一维数组里可以这么写到二维数组就出错了呢?

因为int *p为指向int的指针,+1只会前移int个单位,而int (*p)[4]却是数组指针,会前移一整行

这种对应关系比较号推理,同理我们也能知道一个(逻辑上)三维、四维的数组可以使用指针来索引

三维数组的索引

int array[2][2][2] = {1,2,3,4,5,6,7,8};

int (*p)[2][2] = array;

int i = 0,j = 0,k = 0;

for (;i<2;){

printf("%d\n",p[i][j][k]);

//也可以换成*((*(p+i)+j)+k)

k++;

if (k== 2){

k = 0;

j++;

}

if (j== 2){

j = 0;

i++;

}

}

五维数组的索引

//array是待处理的五维数组

#define SIZE 5

int array[2][2][2][2][2] = {0};

int (*p)[2][2][2][2] = array;

int num[5] = {0};

int x = 0;

while (num[0] != 2){

p[num[0]][num[1]][num[2]][num[3]][num[4]] = x;

x++;

num[4]++;

for (int index = 5;index != 0;index--){

if (num[index] == 2){

num[index] = 0;

num[index-1]++;

}

}

}

num[0] = 0;

//对五维数组进行赋值

while (num[0] != 2){

printf("%d\n",p[num[0]][num[1]][num[2]][num[3]][num[4]]);

num[4]++;

for (int index = 5;index != 0;index--){

if (num[index] == 2){

num[index] = 0;

num[index-1]++;

}

}

}

//获取五维数组的数据

由此我们可以知道:

n维数组需要使用数组(n-1维)指针

============

总结:無

标签:第十天,int,C语言,num,数组,printf,array,指针

来源: https://www.cnblogs.com/AlienfronNova/p/14413354.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值