zoukankan      html  css  js  c++  java
  • c/c++指针总结[pointer summary]

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/pointer-summary.html

    1.指针注意事项

    (1). 指针类型字符串不容许修改

    char *str1=”abcd”; char str2[]=”abcd”;的区别。指针类型的字符串一般不允许修改,如:str1[0]=’c’;这样的语句会导致运行时错误。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    void test_string()
    {
        
    char *str1 = "abcd";
        
    char str2[] = "1234";

        cout << str1 << endl; 
    // abcd
        cout << str2 << endl; // 1234
        cout << *str1 << endl; // a
        cout << *str2 << endl; // 1

        
    //str1[0]='X'; // ERROR
        str2[0] = 'Y'// right
        cout << *str2 << endl; // Y
    }

    (2).指针/数组作为参数进行传递

    在C语言中,参数是使用值传递的。 int func(int a );当调用者调用该函数的时候将传递一个值给a,这个a只是你传递进去的参数的一个副本。而数组传递的时候,会退化为指针,其将数组的首地址复制给形参。看下面的一个例子。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    void fun(char str[])
    {
        printf(
    "After transform:%d "sizeof(str));  //4
    }
    int main()
    {
        
    char strs[] = "abcdefg";
        printf(
    "Before transform:%d "sizeof(strs)); //8
        fun(strs);
        
    return 0;
    }

    (3). 在函数内部修改指针本身(无效)vs修改指针指向的内容(OK)

    许多初学C指针的同学想在函数内部修改作为参数传递进来的指针的值。看以下代码:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    #include "stdafx.h"
    #include <iostream>
    using namespace std;

    typedef struct Link_Node
    {
        
    int Elem;
        
    struct Link_Node *next;
    } LinkNode, *PLinkList;

    void CreateList(LinkNode *header)
    {
        
    int i = 0;
        header = (LinkNode *)malloc(
    sizeof(LinkNode));
        header->Elem = 
    10;
        header->next = 
    NULL;
    }

    int main()
    {
        LinkNode *head = 
    NULL;
        CreateList(head);
        
    if(head != NULL)
            printf(
    "%d ", head->Elem);
        free(head);
        
    return 0;
    }

    /*
    A: head---0
    ---CreateList---
    B: header---0
    C: NODE
    B: header---C
    ---CreateList---
    A: head---0
    */

    此做法无效,在函数内部修改header的地址,函数结束后回到main函数,head仍然是null。

    我们可以修改其指向的变量的值,而不能修改指针本身的内容了。为了能够修改指针本身的内容,我们需要传递指针本身的地址。所以在上面那例中,需要传递head指针本身的地址。代码如下:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    #include "stdafx.h"
    #include <iostream>
    using namespace std;

    typedef struct Link_Node
    {
        
    int Elem;
        
    struct Link_Node *next;
    } LinkNode, *PLinkList;

    void CreateList(LinkNode **header)
    {
        
    int i = 0;
        (*header) = (LinkNode *)malloc(
    sizeof(LinkNode));
        (*header)->Elem = 
    10;
        (*header)->next = 
    NULL;
    }

    int main()
    {
        LinkNode *head = 
    NULL;
        CreateList(&head);
        
    if(head != NULL)
            printf(
    "%d ", head->Elem);
        free(head);
        
    return 0;
    }

    /*
    A: head---0
    ---CreateList---
    B: header---A
    C: NODE
    A: head---C
    B: header---A
    ---CreateList---
    A: head---C
    */

    下面我们再看一例,在函数内部修改指针指向的内容。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    void Trans(int *Arr, int nLength)
    {
        
    for(int i = 0; i < nLength; i++)
        {
            
    // modify content of *pointer
            Arr[i] += i + 20;
        }
    }

    int main()
    {
        
    int nArr[5] = {0};
        
    int  i;
        printf(
    "Before: ");
        
    for(i = 0; i < 5; i++)
            printf(
    "%d  ", nArr[i]);
        
    //0 0  0  0  0

        Trans(nArr, 
    5);
        printf(
    " After ");
        
    for(i = 0; i < 5; i++)
            printf(
    "%d  ", nArr[i]);
        
    // 20  21  22  23  24
        return 0;
    }

    http://blog.csdn.net/gamecreating/article/details/5382711

    http://www.cnblogs.com/nezha/p/3204410.html

    2. 指针vs数组

    数组名不是变量!指针是变量!

    数组名仅仅是一个符号,不是变量,它没有自己的存储空间,而指针是个变量,有自己的空间。

    C标准有一条:当数组出现在函数的参数中时,无论是形参还是实参,都转换为指针再进行操作。

    http://blog.jobbole.com/44863/

    3. 指针的指针

    http://blog.jobbole.com/60647/

    4. 数组指针vs指针数组

    http://blog.csdn.net/touch_2011/article/details/6966980

    http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html

    简单举例说明:

    int *p[2]; 首先声明了一个数组,数组的元素是int型的指针。

    int (*p)[2]; 声明了一个指针, 指向了一个有两个int元素的数组。(数组指针,也称行指针)

    其实这两种写法主要是因为运算符的优先级, 因为[]的优先级比*高。所以第一种写法,p先和[]结合,所以是一个数组,后与*结合,是指针。后一种写法同理。

    指针数组如下处理就会很清楚: typedef int* intPtr; intPtr p[2]; 一目了然,所以为了避免迷惑,做适当的typedef也是很有必要的。

    同理,数组指针也可以作类似处理: typedef int intArray2[2]; intArray2 * p; 和原来的声明都是等价的。

    数组指针(也称行指针)

    定义 int (*p)[n];

    ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

    如要将二维数组赋给一指针,应这样赋值:

    int a[3][4];

    int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。

     p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]

     p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

    所以数组指针也称指向一维数组的指针,亦称行指针。

    指针数组

    定义 int *p[n];

    []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。

    如要将二维数组赋给一指针数组:

    int *p[3];

    int a[3][4];

    for(i=0;i<3;i++)

           p[i]=a[i];

    这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]

    所以要分别赋值。

    这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

    还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。

    比如要表示数组中i行j列一个元素:

    *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

    优先级:()>[]>*

    sizeof分析

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    int _tmain(int argc, _TCHAR *argv[])
    {
        
    // array pointer
        int a[2][3] = {123456};
        
    int (*p)[3];
        p = a;

        
    // test sizeof
        // for a
        cout << sizeof(a) << endl; // 24
        cout << sizeof(a + 0) << endl; // 4  (24 in debug local watch)
        cout << sizeof(a + 1) << endl; // 4  (24 in debug local watch)

        cout << 
    sizeof(a[0]) << endl; // 12
        cout << sizeof(a[1]) << endl; // 12
        cout << sizeof(*(a + 0)) << endl; // 12
        cout << sizeof(*(a + 1)) << endl; // 12
        cout << sizeof(a[0][0]) << endl; // 4

        
    // for p
        cout << sizeof(p) << endl; // 4
        cout << sizeof(p + 0) << endl; // 4
        cout << sizeof(p + 1) << endl; // 4

        cout << 
    sizeof(p[0]) << endl; // 12
        cout << sizeof(p[1]) << endl; // 12
        cout << sizeof(*(p + 0)) << endl; // 12
        cout << sizeof(*(p + 1)) << endl; // 12
        cout << sizeof(p[0][0]) << endl; // 4

        
    return 0;
    }

    5. 函数指针

    http://www.cnblogs.com/nezha/p/3204410.html

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/6/3
    */

    typedef int (*func)(char a[], int nLength);

    int total(char a[], int nLength)
    {
        
    int nTotal = 0;
        
    for(int i = 0; i < nLength; ++i)
            nTotal += a[i];
        
    return nTotal;
    }

    int main()
    {
        
    char a[] = "abcde";
        
    int nLength = strlen(a);
        func fp;
        fp = total;
        printf(
    "%d ", fp(a, nLength));
        
    return 0;
    }

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/pointer-summary.html

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    校验文件数字签名的合法性(VerifyPE)
    windbg help
    VIM的常用操作
    使用Jsonp解决跨域数据访问问题
    Linux下不同文件编码的转换
    Segoe Font 介绍
    关于框架的一些思考
    Linux下Aptana Plugin For Eclipse的破解
    增强网站易用性的10个设计技巧
    Firebug中的console tab使用总结
  • 原文地址:https://www.cnblogs.com/hellogiser/p/pointer-summary.html
Copyright © 2011-2022 走看看