第27课 数组的本质分析

1. 数组的概念

(1)数组是相同类型的变量的有序集合

(2)数组在一片连续的内存空间中存储元素

(3)数组元素的个数可以显示或隐式指定

【编程实验】数组的初始化

#include <stdio.h>

int main(){

    //数组初始化
    int a[5] = {1, 2};//第1、2个元素分别为1、2,其余为0
    int b[]  = {1, 2};//编译过程中,编译会为计算数组b的大小

    int i=0;
    for (i = 0;i < 4;i++)
    {
        printf("a[%d] = %d\n",i,a[i]);
    }

    printf("sizeof(a) = %d\n",sizeof(a));  //20
    printf("sizeof(b) = %d\n",sizeof(b));  //8

    printf("count for a: %d\n",sizeof(a)/sizeof(int));  //5
    printf("count for b: %d\n",sizeof(b)/sizeof(int));  //2

    return 0;
}

2. 数组地址(&a)与数组名a

(1)数组名a代表数组首元素的地址。因此,第2个元素的地址为a+1,以此类推……。注意a或a+i表示元素的地址。可以用*(a+i)取出元素的值,也可以用a[i]来取出元素的值,因为当编译中遇到a[i]会自动转为*(a+i)。反过来也可知,第1个元素的地址为a或&a[0],第2个元素的地址为a+1或&a[1],第i个元素的地址为(a+i)或&a[i]……

(2)数组的地址需要用取地址符&才能得到。即形如&a取的是整个数组的地址,所以&a+1表示指向整个数组的最后面的位置。

(3)数组的首元素的地址值与数组的地址值相同,但是两个不同的概念

【编程实验】数组名和数组地址

#include <stdio.h>

int main(){

    //将数组每个元素初始化为0
    int a[5] = {0};//含义,将第1个元素初始化为0,其余为0.

    printf("a = %p\n",a); //首元素的地址
    printf("&a = %p\n",&a); //整个数组的地址,从数值与看,与a一样。
    printf("&a[0] = %p\n",&a[0]);//第1个元素的地址

    return 0;
}

3. 数组名的盲点

(1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组。如int a[5]表示a的类型为int[5],所以sizeof(a)表示取整个数组的大小,&a表示数组的地址。

(3)数组名的外延:除了sizeof(a)和&a外,数组名经常被可看作是一个常量指针。但要注意这里仅仅是“看作”,而不是真正的指针。不同于指针,数组名只是编译过程中的一个符号,编译器并不为其分配内存,有人称之为“伪变量”。因此,形式a++\a—或a=b(其中b是另一个数组名)这些都是错误的,因为a只是一个符号,编译器会把数组信息(如大小,地址)放入符号表中,每次遇到数组名a时,就会从符号表中取出这个数组的地址,然后用这个固定的地址代替 a,所以这个符号并没有被分配内存空间,而上述操作都是针对变量而言的,故数组名只能做为右值使用。

(4)对数组的引用,如a[i]或*(a+i),只需访问内存一次,而指针的引用如*(p+i)则需要两次,首选通过&p找到p指针,然后加i,再从p+i里面取出的内容。

(5)当数组名作为形参时,将退化为指针。即可以把数组名当成指针来用,这里的sizeof(数组名)为4,即指针的长度。

【实例分析】数组和指针并不相同

#include <stdio.h>

int main(){

    //将数组每个元素初始化为0
    int a[5] = {0};
    int b[2];
    int* p = NULL;

    p = a;

    printf("a = %p\n",a);  //首元素的地址
    printf("p = %p\n",p);  //p==a。
    printf("&p = %p\n",&p);//指针p的地址

    printf("sizeof(a) = %d\n",sizeof(a));//数组的大小:20
    printf("sizeof(p) = %d\n",sizeof(p));//指针的大小为4.

    printf("\n");

    p = b;

    printf("b = %p\n",b);  //首元素的地址
    printf("p = %p\n",p);  //p==b。
    printf("&p = %p\n",&p);//指针p的地址

    printf("sizeof(b) = %d\n",sizeof(b));//数组的大小:8
    printf("sizeof(p) = %d\n",sizeof(p));//指针的大小为4.

    //a = b; //编译错误,数组名不能作为左值;
    //a++;   //编译错误,数组名被编译一个固定地址,相当于0xaabbccdd++的错误
    return 0;
}

4. 小结

(1)数组是一片连续的内存空间

(2)数组的地址和数组首元素的地址意义不同

(3)数组名在大多数情况下被当成常量指针处理

(4)数组名其实并不是指针,不能将其等同于指针。

时间: 2024-10-30 00:26:12

第27课 数组的本质分析的相关文章

数组的本质分析

数组是相同类型的变量的有序集合 数组在一片连续的内存空间中存储元素 数组元素的个数可以显示或隐式指定 int a[5] = {1,2}; int b[] = {1,2}; 数组名代表数组首元素的地址 数组的地址需要取地址符&才能得到 数组首元素的地址与数组的地址值相同 数组首元素的地址与数组的地址是两个不同的概念 数组名可以看作一个常量指针 数组名"指向"的是内存中数组首元素的起始位置 数组名不包含数组的长度信息 在表达式中数组名只能作为右值使用 只有在下列场合中数组名不能看做

第5课 引用的本质分析

引用作为变量别名而存在,因此在一些场合可以代替指针 引用相对于指针来说具有更好的可读性和实用性 swap函数的实现对比如下: 注意: 函数中的引用形参不需要进行初始化. 示例程序如下: 形参没有初始化,而是在第15行调用的时候对引用形参进行初始化. const引用: 当使用常量对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名. 例: 结论: 使用常量对const引用初始化后将生成一个只读变量.普通引用不能使用常量值进行初始化,但是const引用可以. 我

第51课 继承对象模型分析——多态的本质分析

多态的本质分析 用C写面向对象,用C实现多态 #ifndef _51_2_H_ #define _51_2_H_ typedef void Demo; typedef void Derived; Demo* Demo_Create(int i, int j); int Demo_GetI(Demo* pThis); int Demo_GetJ(Demo* pThis); int Demo_Add(Demo* pThis, int value); void Demo_Free(Demo* pThi

C++--第27课 - 动态类型识别

第27课 - 动态类型识别 问题:下面的程序有问题吗? class Parent { public: virtual -Parent() { } }; class Child : public Parent { }; void test(Parent* p) { Child* c = (Child*)p;  //将父类强制转化为子类 } 1. 动态类型 由于基类指针可以直接指向派生类对象,因此可能存在指针所指类型与具体指向的对象类型不同的情况. (p指向的静态类型为Parent)Parent*

26,27删除数组重复项

目录 26,27删除数组重复项 题目 双指针法 题26解法 题27解法一 题27解法二 26,27删除数组重复项 题目 题目26 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例: 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2. 你不需要考虑数组中超出新长度后面的元素. 题

C++中关于[]静态数组和new分配的动态数组的区别分析

这篇文章主要介绍了C++中关于[]静态数组和new分配的动态数组的区别分析,很重要的概念,需要的朋友可以参考下 本文以实例分析了C++语言中关于[]静态数组和new分配的动态数组的区别,可以帮助大家加深对C++语言数组的理解.具体区别如下: 一.对静态数组名进行sizeof运算时,结果是整个数组占用空间的大小:因此可以用sizeof(数组名)/sizeof(*数组名)来获取数组的长度.int a[5]; 则sizeof(a)=20,sizeof(*a)=4.因为整个数组共占20字节,首个元素(i

第十六课 数组的引入 【项目1-5】

第十六课 数组的引入 项目一 [数组大折腾] (1)创建一个有20个元素的整型数组,通过初始化,为数组中的前10个元素赋初值,然后通过键盘输入后10个元素的值,从前往后(从第0个到第19个)输出数组中元素的值,每5个元素换一行. [cpp] view plain copy print? int main( ) { int a[20]={...};  //初始化前10个元素 //键盘输入后10个元素的值 //由前往后输出数组中所有元素的值 printf("由前往后,数组中的值是:\n")

a和&amp;a的区别、二维数组的本质及多维数组

1 a和&a的区别 int a[10] = {1,2};//其他初始化为0 a代表数组首元素的地址,不是整个数组的地址 &a表示整个数组的地址 &a,a代表的数据类型不一样 &a数组类型int[10] a 数组首元素的类型 2 数组指针的用法 int i=0;//循环变量 int a [5] = {3, 4, 5, 6, 2}; //直接定义一个数组指针 int (*p)[5] = &a; for (i=0; i<5; i++) { printf("

数组与指针分析

数组的本质 数组是一段连续的内存空间 数组的空间大小为sizeof(array_type)*array_size 数组名可以看做指向第一个元素的常量指针 指针的运算 指针是一种特殊的变量,与整数的运算规则为 p+n: <--> (unsigned int)p + n * sizeof(*p); 结论: 当指针p指向一个同类型的数组的元素时,p+1将指向当前元素的下一个元素:p-1将指向当前元素的上一个元素. 指针之间只支持减法运算,参与减法运算的指针类型必须相同, 注意: 只有当两个指针指向同