c语⾔指针数组分配内存,指针数组数组指针的分配内存及函数
参数C语⾔版
最近写代码总是被基础知识卡住,⼗分耽误时间,今天⼜卡住了。所以下定决⼼⼀定要弄清楚这个问题,然后不好的是⽹上的资料总是解决的并不清楚,总是在纠结什么是什么是数组指针,看了《C缺陷和陷阱》也没有我想要的东西。要么就是C和C++混为⼀谈,new int[5]这种语法C肯定是错误的,所以个机会总结⼀下,然后希望以后不要再栽在基础上。
定义
指针数组:int p[10] 指针 int(*p)[5]。[]的优先级⾼所以 int *p[10]表⽰数组中都是int,⽽p指向数组⾸地址。没图说个p
反之int(*p)[5]表⽰ *p指向⼀个⼤⼩为5的数组,p则是⼆维数组的⾸地址。
使⽤
指针数组-本质是⼀个数组
int *p[10];
printf("%d\n",sizeof(p) );//是40
for (i = 0; i < 10; ++i)
{undefined
p[i] = malloc(sizeof(int)*i);
}
for (i = 0; i < 10; ++i)
{undefined
free(p[i]);
}
从sizeof(p)=40可以看出来p指向的是数组的⾸地址,数组也被分配到了栈上,所以只需要对其中10个int *分配就ok,free也是。对应的⼆维矩阵像是p[10][i]
数组指针-本质是⼀个指针
int (*p)[10];
p = malloc(sizeof(int *)*2);
printf("%d\n",sizeof(p) );
free(p);
从sizeof(p)=4看出来这就是个指针,指针就⼀定要分配内存了,但是sizeof⾥⾯只需要分配指针⼤⼩就可以。free对着p。这时p被分配到了堆。对应的⼆维矩阵像是p[i][10]
结构体
当然了只使⽤基本类型没什么难度,遇到结构体有可能就懵逼了。基本的原理都是⼀样的
typedef struct block
{undefined
int a;
int b;
int c;
}block_t;
建议不要这么定义结构体
typedef struct block
{undefined
int a;
int b;
int c;
}block_t *;
莫名给⾃⼰加个指针这种代码我怎么也看不懂。。。。⽽且对你理解问题会造成困扰。如果你得到的是block_t *那么使⽤->a其实计算的是对应⾸地址的偏移量,如果是block_t那么使⽤.表⽰⾥⾯的变量。
指针数组
block_t *x[5];
for ( i = 0; i < 5; ++i)
{undefined
x[i] = malloc(sizeof(block_t)*i);
}
x[2][1].a = 1;
printf("%d\n", (*(x+2)+1)->a);
数组指针
block_t (*x)[5];
int *a;
x = malloc(sizeof(block_t *)*2);
x[1][5].a = 5;
x[1][3].b = 1;
printf("%d\n",x[1][5].a );
printf("%d\n",sizeof(x[1]));
printf("%p %p %p %p\n",a,x,x[0],x[1] );
这个基本就可以看出是在栈还是堆分配的内存了
函数调⽤
往往我们还需要传⼊函数,这时指针可能会让你头晕,或者不清楚是否传⼊的是引⽤还是地址。
先从简单说起吧,如果我们在函数中需要改变p,⽽我们的函数是这样的
void fun(int p);
那肯定改变不了,这是最基本的知识了。
我们应该这么做
void fun(int *p);
然后
fun(&p);
没有任何问题吧。
那我们这样⾏吗?
int *p;怎么定义二维数组c语言
void fun(int p);
fun(*p);
别晕,不⾏,不是有了指针就ok了,传⼊的依然是*p指向的int的引⽤。有了这点基础,再加上我们上⾯对指针数组和数组指针本质的理解就应该可以想明⽩函数参数应该有⼏个指针了。看个例⼦
void for_each(block_t *b)
{undefined
int i;
for (i = 0; i < 5; ++i)
{undefined
printf("%d\n",b[i].a );
}
}
void test_fun(block_t *b)
{undefined
b = malloc(sizeof(block_t)*5);
int i;
for (i = 0; i < 5; ++i)
{undefined
b[i].a = i;
}
}
int main()
{undefined
block_t *b;
int i;
test_fun(b);
for_each(b);
}
上⾯的例⼦能达到⽬的么?不能,为什么因为b是指向⼀个数组的⾸地址,传⼊参数传⼊的是引⽤,不是这个⾸地址的地址。。(真特么绕,意思就是传⼊的这个参数实际是引⽤,因为他是数组的⾸地址)怎么办,加指针啊!
void for_each(block_t *b)
{undefined
int i;
for (i = 0; i < 5; ++i)
{undefined
printf("%d\n",b[i].a );
}
}
void test_fun(block_t **b)
{undefined
*b = malloc(sizeof(block_t)*5);
int i;
for (i = 0; i < 5; ++i)
{undefined
(*b+i)->a = i;
}
}
int main()
{undefined
block_t *b;
int i;
test_fun(&b);
for_each(b);
}
ok搞定!
上⾯的例⼦其实都是⼀维指针,然后传⼊⼆维地址,跟我们的指针数组和数组指针(⼆维)没有关系。但是记住,确定指针的维数然后再做就会减少犯错的机会。还有就是指针数组的地址是在栈分配的,所以如果在函数中分配记得分配⾄堆上或者从调⽤者传⼊,(int **p)。数组指针多⽤于⼆维数组传⼊函数时的函数签名中的类型定义,什么意思
int a[][5];
void fun(int (*a)[]);
C⾥⾯必须定义⼆维数组的宽度,⽽且必须是编译时可以确定的!C++是不⼀样的
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论