您的位置:首页 > 其它

C---指针与数组知识总结

2013-09-06 11:09 190 查看
1. 指针数组和数组指针:

初学者总是分不出指针数组与数组指针的区别。其实很好理解:

指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。

数组指针:首先它是一个指针,它指向一个数组。在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。

int *p1[10]; -----因为[]比*优先级高, 所以p1和[]先结合为名为p1的数组, int与*结合为int类型的指针, 所以合起来就是10个int*类型指针的数组, 名为p1。

int (*p2)[10]; -----()比[]优先级高, 所以*p2先结合为一个指针, 指向有10个int类型数据的数组。注意此p2类型为int(*)[10], 可以认为其类型为int a[10]中的a的地址, 即可以这样赋值p2 = &a, 使用时a[2]就相当于*(*p2+2).

这里需要注意的是:C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。这条规则并不是递归的,也就是说只有一维数组才是如此,当数组超过一维时,将第一维改写为指向数组首元素首地址的指针之后,后面的维再也不可改写。比如:a[3][4][5]作为参数时可以被改写为(*p)[4][5],
而用 ***p 传参时就会提示类型错误.

通过typeid来判断类型:

int a[10] ----- typeid(a).name() ----- 输出int [10] ----- a是一个数组, 元素是10个int数据

int* a ----- typeid(a).name() ---- 输出 int* ----- a只是个一维指针, 指向一个int数据

int *a[10] ----- typeid(a).name() ----- int * [10] ----- a是个一维数组, 元素是int类型的指针

int (*a)[10] ----- typeid(a).name() ----- int (*)[10] ----- a是个一维指针, 指向一个一维数组

int (*a)[10][10] ----- typeid(a).name() ----- int (*)[10][10] ----- a只是个一维指针, 指向二维数组

int *a[10][10] ----- typeid(a).name() ----- int * [10][10] ----- a是个二维数组, 元素是int类型的指针

int a[2] = {1,2};

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

int (*p)[2];

p = &a; // *(*p+1) means a[1]

p = b; //*(*(p+1)+2) means b[1][2]

2. 数组作为函数参数

C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。

void fun(char a[10])

{

int i = sizeof(a);

char c = a[3];

}

可以发现在fun中的a只是占用了4个字节, 证明传过来的只是一个指针。当要使用确定大小的数组时,请再传一个参数确定数组下标。

3. 指针作为函数参数

C 语言中,无法把指针变量本身传递给一个函数。

void GetMemory(char * p, int num)

{

p = (char *)malloc(num*sizeof(char));

}

intmain()

{

char *str = NULL;

GetMemory(str,10);

strcpy(str,”hello”); //出错, 此时str仍为空

free(str); //free 并没有起作用,内存泄漏

return 0;

}

malloc 的内存的地址并没有赋给str,而是赋给了编译器自动分配和回收的一个str的拷贝,我们根本就无法使用。所以想这样获取一块内存是不行的。这时,
可以使用return:

char
* GetMemory(char * p, int num)

{

p = (char *)malloc(num*sizeof(char));

return p;

}

也可以使用二级指针:

void
GetMemory(char ** p, int num)

{

*p = (char *)malloc(num*sizeof(char));

return p;

}

调用时用GetMemory(&str,10);

这样的话传递过去的是str
的地址,是一个值。在函数内部,用钥匙(“*”)来开锁:*(&str),其值就是str。所以malloc 分配的内存地址是真正赋值给了str 本身。

4. 指针与数组内存分配

一般认为在c中分为这几个存储区:

◇栈 - 有编译器自动分配释放

◇堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收

◇全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放

◇常量区 - 专门放常量的地方。 - 程序结束释放

◇代码区 :就是存放程序源代码的地方

在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。全局变量以及静态变量(不管在哪里)都存放在全局区(静态区), 另外,常量以及函数中的 "adgfdf "这样的字符串存放在常量区。比如:

int a = 0; //全局初始化区

char *p1; //全局未初始化区

main()

{

int b; //栈

char s[] = "abc "; //栈

char *p2; //栈

char *p3 = "123456 "; //123456\0在常量区,p3在栈上。

static int c = 0; //全局(静态)初始化区

p1 = (char *)malloc(10);

p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。

strcpy(p1, "123456 "); //123456\0放在常量区,编译器可能会将它与p3所指向的 "123456 "优化成一块。

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: