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

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 "优化成一块。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值