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 "优化成一块。
}
初学者总是分不出指针数组与数组指针的区别。其实很好理解:
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在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 "优化成一块。
}
相关文章推荐
- C/C++基础知识总结——数组、指针域、字符串
- C语言指针和数组知识总结(上)
- C语言指针和数组知识总结(下)
- C语言中 指针的基础知识总结, 指针数组的理解
- C语言指针和数组知识总结(下)
- C语言指针和数组知识总结(上)
- 指针知识梳理5-字符串与指针,程序内存总结
- 数组与指针的一些小知识
- 函数指针与函数指针数组应用总结
- C/C++基础知识(一)数组和指针
- C语言指针,数组,函数总结
- C小知识:数组和指针的区别
- 字符数组,字符指针,sizeof,strlen总结
- 黑马程序员 Java基础知识总结-数组
- 对字符数组,字符指针,字符串常量以及其sizeof的一些总结
- 指针与数组知识点总结
- C++总结1——指针和引用/数组的区别
- 数组和指针可交换性的总结
- C和指针之数组和函数部分总结
- C++ 数组和指针学习总结