C语言从零开始(十七)-指针2

作者: 天花板 | 来源:发表于2016-01-05 20:43 被阅读2007次

上一节中我们讲了指针的最基本的概念,目的是让大家对指针有个最基本的认识。接下来我们会通过一些具体的练习题帮大家一点点搞清楚指针相关的全部知识点。

指针的移动

我们先看一下这段代码。

int main()
{
    char* p1 = "China";
    char *p2;

    p2 = (char*)malloc(10);
    memset(p2, 0, 10);
    while (*p2++ = *p1++);
    printf("%s\n", p2);

    return 0;
}

这段代码的目的是为了把指针p1指向的字符串拷贝到指针p2中。但运行结果却为空。接下来我们就看看这段代码究竟犯了哪些错误。

1. 代码的对称性

前面讲过,函数malloc的作用是在内存的堆中申请一段空间,我们可以用指针去管理这段空间的地址。

p2 = (char*)malloc(10);

这句代码实现了从堆中申请了一段10个Bytes的空间,指针p2指向这段空间的首地址。

memset(p2, 0, 10);

之后,又用memset这个函数将这10个Bytes的空间内容全部初始化为零。这两句话没有任何问题。

但这里需要注意的是,malloc申请了空间之后,如果在使用完之后不调用free函数释放这段空间,它会一直被认为是正在使用中,其它任何程序都不能使用。如果每次申请空间都不释放的话,就会有内存很快被占满的可能。这是C语言程序设计中的大忌。

因此,我们需要在程序中加入这句话:

free(p2);

理论上讲,程序中没出现一个malloc,就需要在申请的这段空间的作用域最后有一个free。这就是程序设计中的对称性。一些静态代码检查工具就是根据这个来初步判断是否可能出现内存溢出。

2. 指针偏移

加了free(p2)是不是就正确了呢?其实还有问题。最开始,内存中如图所示:


内存1

指针p1指向栈中的一段空间的首地址,指针p2指向了堆中的一段空间的首地址。而在执行while循环结束后,内存中的情况成了这样:

内存2

字符串已经拷贝完成,但问题是两个指针都改变了之前的位置。那么问题就来了:

  • p2已经不是之前申请的那段10个Bytes的空间的首地址了,此时执行free(p2)语句无法实现释放内存的目的
  • p2此时指向的位置是'\0',在用printf输出时,系统会认为是一个空字符串,因此什么都打印不出来

3. 正确代码

那么,究竟要如何修改才能正确实现功能呢。请看下面这段代码。

int main()
{
    char* p1 = "China";
    char *p2, *p3;

    p2 = (char*)malloc(20);
    memset(p2, 0, 20);

    p3 = p2;

    while (*p3++ = *p1++);
    printf("%s\n", p2);

    free(p2);

    return 0;
}

我们又多声明了一个指针p3,让它也指向p2的空间,于是在循环结束时,内存中是这样的:

内存3

此时再去打印和释放p2都不会有任何问题了。

指针使用的最大灵活性就是它的移动,通过这种移动可以省去复杂的计算偏移的工作,然而在移动的过程中一定要记录下最初的地址,否则很容易出现问题。

打印内存地址

在调试程序过程中,特别是复杂内存操作的程序,打印内存地址是个非常重要调试方法。那如何能够通过Printf函数将内存地址打印在屏幕上呢?请看下面这段代码:

int main()
{
    int a;
    printf("%p\n", &a);
    printf("0x%x\n", &a);

    return 0;
}

这段代码的功能是打印出变量a的地址。请大家自己试验查看结果。

在不同的环境中,这段程序的执行结果可能略有不同。在标准C语言中,%p打印出的地址前面会有"0X",而%x打印出的地址没有。因此我们这里用了“0x%x”。

今天就到这里,下一篇我们讲继续讲解指针相关的例题。

我是天花板,让我们一起在软件开发中自我迭代。
如有任何问题,欢迎与我联系。


上一篇:C语言从零开始(十六)-指针1
下一篇:C语言从零开始(十八)-指针3

相关文章

  • C语言从零开始(十七)-指针2

    上一节中我们讲了指针的最基本的概念,目的是让大家对指针有个最基本的认识。接下来我们会通过一些具体的练习题帮大家一点...

  • [Swift]结构体指针操作

    C语言的指针操作 在c语言中申明一个变量并通过指针修改该变量的值 a value is 2 c语言操作结构体指针操...

  • C语言05- 指针

    C语言05- 指针 13:指针 指针是C语言中的精华,也是C语言程序的重点和难点。 13.1:指针定义与使用 指针...

  • C语言:指针2

    一、指向数组的指针变量 1、指向数组元素的指针变量 由于数组元素与普通一样,所以定义指向数组元素的指针变量与定义指...

  • C语言指针2

    char * string =“I LOVE china”; 在C 语言中 只有字符变量,没有字符串变量。 cha...

  • 链表代码注意事项

    1、理解指针或引用的含义 比如C语言是指针,就是相当于JAVA的引用 2、警惕指针丢失和内存泄漏 C 语言,内存管...

  • 02-C语言的指针

    02-C语言的指针 目标 C语言指针释义 指针用法 指针与数组 指针与函数的参数 二级指针 函数指针 指针在C中很...

  • 维护中-1

    此文章已经移至 C语言从零开始(十)-循环基础for 上一篇:C语言从零开始(九)-选择结构下一篇:C语言从零开始...

  • C语言指针总结大学霸IT达人

    C语言指针总结大学霸IT达人 C语言的指针是C语言区别其它语言的最主要的特定之一。有了指针,C语言就可以抛开所有束...

  • 带小白学C语言指针

    C语言里指针才是C语言的开始和指针;C语言里基本所有东西都是由指针演变而成; 指针是指向地址的变量,类型就是指针...

网友评论

  • yysleep:您好,上一届说的是指针是地址,即 int* p = &a ,为什么这节的 char* p1 = "China",而不是&“China”
    小龙女爱吃大龙虾:这个问题问的相当好啊,字符串常量就是比较特殊。char* p1 = "China",p1的指针就指向了这个串的字母C。指向字符串的指针输出的时候,printf("%s\n", p2);,也是不用*。而且在scanf中,如果要输入的类型是字符串,也是不用&的,这个记住就好。至于为什么,我也不太清楚哎😔。你要是知道了告诉我。23333
  • 619197474fea:您好,为什么一下是 char* p1 = "China";一下是 char *p2;
    *的位置不同有什么区别?
    天花板:@猪肉蘑菇 在编译器看来,两种情况是一样的。
  • 76193e6c95d7:才开始学
  • 7bf1b9405cb0:讲汇编语言么
    天花板: @为你划地为牢 这个没有计划
  • 李公子Alice34:正好在学c语言

本文标题:C语言从零开始(十七)-指针2

本文链接:https://www.haomeiwen.com/subject/skyzhttx.html