zoukankan      html  css  js  c++  java
  • C 数组与指针

    1数组的本质

    数组是多个元素的集合,在内存中分布在地址相连的单元中,所以可以通过其下标访问不同单元的元素。

    2指针

    指针也是一种变量,只不过它的内存单元中保存的是一个标识其他位置的地址。由于地址也是整数,在32位平台下,指针默认为32位。

    3指针的指向

    指向的直接意思就是指针变量所保存的其他的地址单元中所存放的数据类型。

    int * p ;//p 变量保存的地址所在内存单元中的数据类型为整型

    float *q;// ........................................浮点型

    不论指向的数据类型为那种,指针变量其本身永远为整型,因为它保存的是地址。

    4 字符数组

    char  str[10] = {"hello world"};

    char  *s ; s = "China";

    C语言中没有真正的字符串类型,可以通过字符数组表示字符串,因为它的元素地址是连续的,这就足够了;

    你把China 看作是字符串,但是编译器把它看作是地址 0x3000,即字符串常量的本质表现是代表它的第一个字符的地址;

    那么 %s ,它的原理其实也是通过字符串首地址输出字符串,printf("%s ", s);   传给它的其实是s所保存的字符串的地址。

     C语言中操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。

     5  char *  与 char  a[ ];

     char *s 只是一个保存字符串首地址的指针变量, char a[ ] 是许多连续的内存单元,单元中的元素为char ,之所以用 char *能达到char a [ ] 的效果,还是字符串的本质,地址,即给你一个字符串地址,便可以随心所欲的操所他。。但是,char* 和 char a[ ] 的本质属性是不一样的。

    6   char **  与char  * a[ ] ;

    先看 char *a [ ] ;

    由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址。。

    所以 char *a[ ] = {"China","French","America","German"};

    同过这句可以看到, 数组中的元素是字符串,那么sizeof(a) 是多少呢,有人会想到是五个单词的占内存中的全部字节数 6+7+8+7 = 28;

    但是其实sizeof(a) = 16;

    为什么,前面已经说到, 字符串常量的本质是地址,a 数组中的元素为char * 指针,指针变量占四个字节,那么四个元素就是16个字节了

        #include <stdio.h>
       int main()
       {
       char *a [ ] = {"China","French","America","German"};
               printf("%p %p %p %p
    ",a[0],a[1],a[2],a[3]); //数组元素中保存的地址
       printf("%p %p %p %p
    ",&a[0],&a[1],&a[2],&a[3]);//数组元素单元本身的地址
       return 0;
       }

    可以看到数组中的四个元素保存了四个内存地址,这四个地址中就代表了四个字符串的首地址,而不是字符串本身。。。

    因此sizeof(a)当然是16了。。

    注意这四个地址是不连续的,它是编译器为"China","French","America","German" 分配的内存空间的地址, 所以,四个地址没有关联。

    char **s;

    char **为二级指针, s保存一级指针 char *的地址。

    char *a [ ] = {"China","French","America","German"};
    char **s =   a;

    为什么能把 a赋给s,因为数组名a代表数组元素内存单元的首地址,即 a = &a[0] = 0012FF38;

    而 0x12FF38即 a[0]中保存的又是 00422FB8 ,这个地址, 00422FB8为字符串"China"的首地址。

    即 *s = 00422FB8 = "China";

    这样便可以通过s 操作 a 中的数据;

    7 数据存储

    首先要搞清楚编译程序占用的内存的分区形式,程序的内存分配:

    一个由c/C++编译的程序占用的内存分为以下几个部分
    1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
    2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
    3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
    4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。
    5、程序代码区

    #include <stdio.h>
    int main()
    {
        char * a1 = "abc";
        char a2[] = "abc";
        char *a3 ="abc";
        char a4[] = "abc";
        printf("char * a:%p
    ",a1);//打印a1的值 
        printf("char a2[]:%p
    ",a2);//打印a2的值 
        printf("char *a3:%p
    ",a3);//打印a2的值 
        printf("char a4[]:%p
    ",a4);//打印a2的值 
        return 0;
    }

    显而易见字符指针变量a 和a3的值是一样的,这说明它们指向同一块内存,这块内存就是上文所说的字符常量区;字符数组指针a2和a3的值不同且相差4字节,这说明它们指向的内存是不相同的,它们的“abc”其实是对字符常量区中“abc”的一份拷贝,并且数据是存放在栈中的。

    8 const int *a与int *const a

    C基础的6,7,9;


    原文链接:https://blog.csdn.net/weixin_40746176/article/details/89036100

    原文链接:https://blog.csdn.net/daiyutage/article/details/8604720

  • 相关阅读:
    用Ext.override重写控件属性
    如何设置DateField的默认值
    ExtJs中获得当前选中行号(Grid中多选或者是单选)及Grid的反选(取消选中行)
    Ext.form各类控件的配置及方法
    犀利的系统验收工作
    UML系列 (五) 为什么要用UML建模之建模的重要性
    牛腩新闻发布系统(2)使用存储过程查询表
    如何编写优质的需求文档
    SCM软件配置管理 (一)SVN 与 CVS
    牛腩新闻发布系统 (3) 存过过程或函数""需要""参数,但未提供该参数
  • 原文地址:https://www.cnblogs.com/straight/p/15128051.html
Copyright © 2011-2022 走看看