跟我一起学C语言(第七天)

本文通过实例代码详细讲解了C语言中指针与一维、二维数组的关系。强调了指针在操作二维数组时的注意事项,如行指针与列指针的转换,以及如何正确地通过指针访问数组元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第七天

好多学生都认为C语言中指针是最难的,在我看来,并没有想象的那么难,希望读者不要害怕指针。

  

指针:

地址从内存分配
什么地址?一个地址就是一个编号,编号和编号之间相差一个字节,如果地址需要存储占用4个字节
什么指针? 指针常量和指针变量
指针常量就是地址编号
指针变量就是存放地址编号的变量
通常直接将指针常量和指针变量简称为指针。

如何定义指针变量。
xxx *p;  
xxx代表了一个数据类型


int a = 10;
int *p = &a; *和int结合构成了一个指针类型叫做int *
*p = 20;本质修改了a的内容
操作的是指针变量指向的空间内容(一个空间包含多个地址编号,其中第一个地址编号就可以被称为指向了这个空间,
指针变量存放空间首地址编号,所以也可以直接描述为指针变量指向了这个空间)。


算数运算符:+ - ++ --
int a = 10;
int *p = &a;


p + 1跳过的字节数和p指向的空间的类型相关
*p ++  打印结果为10  p指向偏移了
(*p)++ 单纯打印也是10  p指向没有改变


int *p;叫做野指针


int a = 0x12345678;
char *p = (char *)&a;


*(p + 1) 获取了 0x56 
*(p + 3) 获取了 0x12 


一级指针和一维数组的关系
数组名是一个常量地址 
int a[5] = {a[0],a[1],a[2],a[3],a[4]};
//int *p1 = &a[0];
//int *p2 = &a[1];


int *p = a;
p + i <==> a + i
*(p + i) <==> *(a + i)    <==> a[i]
/\  操作a+i指向的空间内容
    ||
\/

   p[i]


例子:

#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[2][3];


//取出二维数组中实际元素,要对列指针操作
printf("a[1] = %p\n",a[1]);
printf("a[1] + 1 = %p\n",a[1] + 1);
printf("*(a + 1) = %p\n",*(a + 1));
printf("*(a + 1) + 1 = %p\n",*(a + 1) + 1);


printf("********************\n");


printf("a + 1 = %p\n",a + 1);
printf("a + 1 + 1 = %p\n",a + 1 + 1);
printf("&a[1] = %p\n",&a[1]);
printf("&a[1] + 1 = %p\n",&a[1] + 1);


//行指针取*变成列指针       列指针取地址变成行指针
//列指针取*获取了空间具体值
return 0;
}

   


指针和二维数组关系
int a[2][3];当作一个特殊的一维数组,定义如下:xxx a[2]; xxx是12字节的类型


a[0],a[1]都是a数组中的元素。每个元素是12个字节——12字节包含了3个整型,所以认为a[0],a[1]都代表了一个一维数组


“a[0],a[1]都代表了一个一维数组” <==> 普通的一维数组数组名是整个数组空间首地址
普通的一维数组名 + 1跳过了数组名代表的数组内部中一个元素。<==> a[0] + 1跳过了a[0]代表的一维数组中一个元素


二维数组中:
int a[2][3];<==> int (a[2])[3]; ==>转化后的类型是 int (*)[3];
行序优先
定义变量:数据类型 变量名;
    int (*)[3] p;  通过类型定义的一个变量
这里的p本质也是行指针
编译器识别的用法:int (*p)[3];很多资料上被叫做数组指针(一个指向数组的指针)
p = a;
行指针
a + i <==> &*(a + i) <==> &a[i]
p + i <==> &*(p + i) <==> &p[i]
列指针
a[i] + j <==> *(a + i) + j
p[i] + j <==> *(p + i) + j


例子:

#include<stdio.h>


int main(int argc, const char *argv[])
{
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
// int (*)[4] p;//这里的错误是编译器问题,老版本编译器允许这样做。现在编译器不允许。
int (*p)[4];//如果有一个指针类型是 xxx (*)yyy,定义的变量或者数组或者函数,都放到括号内部*的后面
//这里为什么出现[4],就是为了告诉指针,每次加1跳一行时,需要跳过4个元素。

p = a;
int i,j;

for(i = 0;i < 3;i ++)
{
for(j = 0;j < 4;j ++)
{
// printf("%d\t",a[i][j]);
// printf("%d\t",*(*(a + i) + j));
// printf("%d\t",*(a[i] + j));

printf("%d\t",p[i][j]);
printf("%d\t",*(*(p + i) + j));
printf("%d\t",*(p[i] + j));
}
}
printf("\n");
return 0;
}



指针和指针数组的关系:
char *str[2];
char **p = str;
{
int a=10;
int *p=&a;
int * *q=&p;
}


char (*str[2])[3];<==> char (*)[3] str[2];这是一个数组,里面存的是
char (*)[3] *p = str; <==> char (**p)[3] = str; 


int *q;
p = (char (**)[3]) q; 


char (*str[2][3])[4];这是什么?二维数组,存char (*)[4];
<==> char (*)[4] str[2][3];


char (*)[4] (*)[3]  p; <==> char (*(*p)[3])[4];

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值