数组与指针

一、声明与定义

  “声明”与“定义”最大的区别在于“定义”创建了一个对象并且为它分配了内存空间,而“声明”并没有为它分配内存空间。

二、内存空间

  下图描述了内存空间中的一些相关概念。
              这里写图片描述
  栈:这是存储器用来保存局部变量的部分。每当调用函数,函数的所有局部变量都在栈上创建。该内存空间由编译器自动分配释放。其操作方式类似于数据结构中的栈。
  堆:堆用于动态存储。程序在运行时创建的一些数据会保存在堆中。该内存空间由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收。其操作方式类似于数据结构中的链表,与数据结构中的堆要区分开。
  全局量:又可以称作“静态区”。主要存储全局变量和局部静态变量。全局量位于函数之外,在程序开始运行时创建,对所有函数可见。程序结束后该内存空间由系统释放。
  常量段:常量是在程序中要用到的不变量,也是在程序开始运行时创建。程序结束后由系统释放。
  代码段:存储器中用来加载机器代码的部分。
  在上述5个区域中,常量段与代码段都是只读的。

三、数组、指针和语法糖

   声明char names[]在不同的地方出现具有不同的意义。如果是普通的变量声明,names就是一个数组,而且必须马上赋值,比如

int function(){
    char names[] = "ABC";
    ...
}

   但是如果names以函数参数的形式声明,那么names其实就是指针,它不过是*names的语法糖。

void function(char names[]){
    ...
}

void function(char *names){
    ...
}

// 上面两种形式是等价的

四、数组与指针

   先看下面两段代码:

#include <stdio.h>

int main()
{
    char *cards = "JQK";
    char a_card = cards[2];

    cards[2] = cards[0];
    cards[0] = cards[1];
    cards[1] = a_card;

    return 0;
}
#include <stdio.h>

int main()
{
    char cards[] = "JQK";
    char a_card = cards[2];

    cards[2] = cards[0];
    cards[0] = cards[1];
    cards[1] = a_card;

    return 0;
}

   第二段代码可以正常地编译运行,但是根据运行环境的不同,第一段代码编译运行时会得到各种不同的错误。简单的看,问题的原因是“字符串无法更新”。
  在第一段代码中,计算机存储器是这样运作的:
  1. 计算机加载字符串字面值
  当计算机把程序载入到存储器时,会把所有常量值(如字符串常量JQK)放到常量存储区,这部分存储器是只读的。
  2. 程序在栈上创建cards变量
  cards是局部变量,被保存到栈中。
  3. cards变量指向”JQK“的地址
  4. 计算机试图修改字符串
  计算机试图修改cards变量指向的字符串时会失败,因为字符串所在的常量区是只读的。
  具体流程如下图示:
              这里写图片描述
  
  
  在第二段代码中,计算机存储器是这样运作的:
  1. 计算机加载字符串字面值
  当计算机把程序载入到存储器时,会把所有常量值(如字符串常量JQK)放到常量存储区,这部分存储器是只读的。
  2. 程序在栈上新建一个数组
  由于声明了数组,程序会在栈上开辟一块内存空间给数组。
  3. 程序初始化数组
  程序将字符串字面值”JQK“内容复制到栈上。
  4. 计算机修改字符串
  程序对栈中的字符串副本进行修改,达到目的。
  具体流程如下图示:
                这里写图片描述
  
  为了规避上述问题,在把指针设置为字符串字面值的时候,需要使用关键字constconst char *s = "ABC",这样一来,如果编译器发现有代码试图修改字符串,就会提示编译错误。需要注意的是,加不加关键字const,字符串字面值都是只读的,const只是敲醒了编辑器。

五、再说几句

   对于char s[] = "ABCD"char *t = "ABCD"
  sizeof()函数会有不同,sizeof(s) == 5为数组在存储器中的长度而sizeof(t)的大小等于该环境下char的长度。
  对于取址符号&&s返回的是数组,即数组s的地址就是数组本身&t则表示char型变量t的地址。
  当创建指针变量时,计算机会为它分配一定大小的内存空间。但如果创建的是一个数组,计算机会为数组分配内存空间,但不会为数组变量分配任何空间,编译器仅在它出现的地方把它替换为数组的起始地址。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值