int a[10] 定义一个整型数组 里面有10个元素
a 数组名,同时也为首元素地址 +1 +4字节
&a 数组地址 +1 +40字节
&a[0] 数组首元素的地址 +1 +4字节
int a[4][3]
a 数组名,同时也为首行地址 +1 +12
&a 数组地址 +1 +48
a[0] 首行首元素地址 +1 +4
&a[0] 首行地址 +1 +12
&a[0][0] 首元素地址 +1 +4
--------------------------------------------------------------
指针
不管什么类型的指针
sizeof(int *) 四字节
sizeof(char *) 四字节
sizeof(long *) 四字节
sizeof(float *) 四字节
int a = 1;
int *p = &a; 或 p = &a;
p+1 +4字节
指针 + 数组
int a[10] = {1,2,3,4,5,6,7,8,9,10} 数组名a为常指针
int *p = a;
a[i] *(a+1) *(p+1) 三个是等价的
-----------------------------------------------------------------------
指针数组的定义
指针数组:指针数组可以说成是”指针的数组”
首先这个变量是一个数组,其次,”指针”修饰这个数组,
意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。
char *arr[4] = {"hello", "world", "shannxi", "xian"};
这就相当与定义char *p1 = “hello”,char *p1 = “world”,char *p3 = “shannxi”, char *p4 = “xian”,这是四个指针,每个指针存放一个字符串首地址,然后用arr[4]这个数组分别存放这四个指针,就形成了指针数组。
arr为指针数组的首地址 也是hello的地址
*arr %s输出的是 hello
*arr + 1 %s输出的是 ello
*(arr + 1) %s输出的是 world
arr[0] %s输出的是 hello
arr[1] %s输出的是 world
所以对于数组指针而言 *(arr + 1) arr[1] 也是等价的
-------------------------------------------------------
数组指针:数组指针可以说成是”数组的指针”,
首先这个变量是一个指针,其次,”数组”修饰这个指针,
意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
int (*pa)[4]; 此时pa的步长为4*4=16个字节
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4] = a; //定义一个数组指针 步长为16
a[i][j] ;*(*(p+i)+j);(*(p+i))[j] //这三个是等价的
-------------------------------------------------------------------------
指针的指针
如果不通过函数的参数传递的话
char *ptr = (char *)malloc(sizeof(char) * 64);
就可以了,但是用了的话:
void A(char **str)
{
*str = (char *)malloc(sizeof(char) * 64);
}
int main()
{
char *ptr = NULL;
A(&ptr);
strcpy(ptr,"hello");
}
那么为什么要用到指针的指针呢?
printf("%s ",ptr) -->(null)
printf("%s ",*ptr) -->segment fault
printf("%p ",&ptr) -->0xbfd26f00
printf("%p ",ptr) -->0x8c3b008c
如果A(ptr); 把null传递给了形参 没意义
如果A(&ptr);把地址传给了形参,这时候的地址是指针的地址,而本来指针就是存放内存地址的,所以这时候就是指针的指针,形参要用**p接!!!
----------------------------------------------------------------
int main()
{
char *str[] = {"hello","world","ni","hao"};
char **p;
int i;
for(i = 0; i < 4; i++)
{
p = str + i; //p是指针的指针,存放的是指针的地址,
//str为指针数组存放的就是指针的地址,所以可以赋值
printf("%s \n",*p);
}
return 0;
}
---------------------------------------------------------------
函数指针的定义
void (*p)();
int add(int x,int y);
int (*q)(int,int);
q = add;
q(1,2);
总结一下,指针和数组最重要的就是对地址的操作,就是通过指针或者是数组的地址赋值来操作内存中存放的数据!
要分清楚什么时候调用的是地址,什么时候是取值!
‘*’在定义时:表示后面的变量是一个指针
‘*’在使用时:表示取值,即取地址的值