`
rokuan
  • 浏览: 20415 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

一个C语言指针问题

阅读更多
今天重新拿起C语言的书学习学习,遇到了一个诡异的问题,开始不可理解,现在记录下整个分析过程。
首先上代码:
#include <stdio.h>

void strcopy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
    ;
}

int main()
{
    int i = 3;
    char a[] = "abcdefg";
    char *p;	
    strcopy(p, a);
    printf("%d\n",i);
}

我估计大多数人看到这个程序都会认为会打印出3,但是结果出乎意料:


于是我分别做了两次修改,都使程序正常了。
第一次,我把strcopy函数注释掉了
#include <stdio.h>

void strcopy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
    ;
}

int main()
{
    int i = 3;
    char a[] = "abcdefg";
    char *p;	
    //strcopy(p, a);
    printf("%d\n",i);
}

打印结果是3.
第二次,我把int i = 3;移动p指针下面定义:
#include <stdio.h>

void strcopy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
    ;
}

int main()
{
    char a[] = "abcdefg";
    char *p;	
    int i = 3;
    strcopy(p, a);
    printf("%d\n",i);
}

也得到了正确的结果。
于是我用C free对原来的程序进行调试。

找到变量i的内存地址,可知其存放的是00000003,也就是数字3。
接着我执行strcopy方法后,就出状况了:


结果表明字符串被拷贝到了变量i的内存地址处。我对i处内存的内容进行十六进制转十进制,64636261转十进制后正好是1684234849.也就是这个诡异的输出结果。
综合以上的分析,所得结果如下:
#include <stdio.h>

void strcopy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
    ;
}

int main()
{
    int i = 3;    //定义int型变量i,分配内存空间,并赋值
    char a[] = "abcdefg";
    char *p;    //定义指针p,并为初始化指针的位置,在此程序中p默认指向了i的地址
    strcopy(p, a);
    printf("%d\n",i);
}

现在真相大白了,不过任然让我疑惑的在指针p被定义的时候,p的默认指向地址是否有规律可循呢?任旧是个疑问,还请看到这篇文章的各位童鞋指点一二。
不过这个程序本来就是写的有问题,C语言的内存分配果然很容易出错(⊙o⊙)…
我想正确的程序应该是这样的...
#include <stdio.h>

void strcopy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
    ;
}

int main()
{
    int i = 3;
    char a[] = "abcdefg";
    char *p = (char *)malloc(sizeof(a));    //给指针分配新的内存空间
    strcopy(p, a);
    printf("%d\n",i);
}

另外,搜索了下,函数malloc()和函数calloc() 的主要区别是前者不能初始化所分配的内存空间,而后者能。
  • 大小: 2.7 KB
  • 大小: 18.7 KB
  • 大小: 18.7 KB
分享到:
评论
8 楼 pujia12345 2011-06-27  
新手 小白吧

p你只定义了一个指针,没有分配变量空间,运行中无意占用了i的空间。

这都不清楚?

一般这样
char str[128];
char * p=str;
strcpy(p,a);
7 楼 ray_linn 2011-06-27  
RednaxelaFX 写道
ray_linn 写道
3. 改完了的结果还是错,有malloc就一定要有free,有new就要有delete否则就是退出,那内存就再不会被系统分配。

Quick overview of how processes exit on Windows XP
Raymond Chen 写道
Moral of the story: If you're getting a DLL_PROCESS_DETACH due to process termination,† don't try anything clever. Just return without doing anything and let the normal process clean-up happen. The kernel will close all your open handles to kernel objects. Any memory you allocated will be freed automatically when the process's address space is torn down. Just let the process die a quiet death.


呵,你总是比我有耐心啊。其实是这样的,it depends。“现代”OS的内存管理器是可以在process结束的时候回收这些内存,换句话说,free现在更多的是在process内释放内存,但是这不是每个os都是如此工作,在嵌入式里更是如此,有些os可能没办法正确回收这些内存导致奇怪的错误或者必须在一个时间周期里回收内存,在这之前这些内存仍是无法被分配,导致内存紧张。

一些我知道的不会free的OS,有dos, win98,老版本的netware等等。

所以在不确定OS怎么去做前,最好还是把这样的malloc/free对当成C/C++的铁律。
6 楼 ppgunjack 2011-06-27  
能否上传obj文件,gcc复现不了你说的问题,
O3编译倒是会出现尝试修改代码段的举动
默认编译,也没指令会体现出p的内容会是i的地址
5 楼 RednaxelaFX 2011-06-26  
ray_linn 写道
3. 改完了的结果还是错,有malloc就一定要有free,有new就要有delete否则就是退出,那内存就再不会被系统分配。

Quick overview of how processes exit on Windows XP
Raymond Chen 写道
Moral of the story: If you're getting a DLL_PROCESS_DETACH due to process termination,† don't try anything clever. Just return without doing anything and let the normal process clean-up happen. The kernel will close all your open handles to kernel objects. Any memory you allocated will be freed automatically when the process's address space is torn down. Just let the process die a quiet death.
4 楼 rokuan 2011-06-26  
ray_linn 写道
看都不用看,这个程序问题多得很。

1. s 一般表示source ,t表示target ,而写的时候source和target根本就是反的。

2. t根本就是未分配的地址,这样的拷贝根本随编译器的开心在任一地址中乱写。 微软vc的保护函数在这一方面做出了改进,但是可惜没有成为标准,否则用strcpy_s就能预防这种情况。glibc就比较陈旧了。

3. 改完了的结果还是错,有malloc就一定要有free,有new就要有delete否则就是退出,那内存就再不会被系统分配。

谢谢指点,第一条和第三条是看明白了,程序的确有问题,不过第二条有点糊涂,t根本就是未分配的地址是什么意思呢?还请这位哥们讲解一下啊
3 楼 ray_linn 2011-06-26  
看都不用看,这个程序问题多得很。

1. s 一般表示source ,t表示target ,而写的时候source和target根本就是反的。

2. t根本就是未分配的地址,这样的拷贝根本随编译器的开心在任一地址中乱写。 微软vc的保护函数在这一方面做出了改进,但是可惜没有成为标准,否则用strcpy_s就能预防这种情况。glibc就比较陈旧了。

3. 改完了的结果还是错,有malloc就一定要有free,有new就要有delete否则就是退出,那内存就再不会被系统分配。
2 楼 rokuan 2011-06-26  
liusondark 写道
为什么我用VC++运行不了

不太清楚,vc我不太会用,还是比较习惯gcc编译,C Free用的比较顺手
1 楼 liusondark 2011-06-26  
为什么我用VC++运行不了

相关推荐

    C语言指针练习填空和阅读程序题

    C语言指针练习填空和阅读程序题 本资源主要涵盖了C语言指针的相关知识点,包括指针的基本概念、指针运算、指针与数组的关系、指针与字符串的关系等。通过本资源的学习,可以帮助读者更好地理解和掌握C语言指针的...

    c语言指针c语言指针c语言指针c语言指针c语言指针

    c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针c语言指针...

    C语言指针详解.zip

    c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 c语言指针详解 ...

    c语言指针学习笔记

    本文将介绍C语言指针的基本概念、定义、初始化、运算以及与一维数组的关系。 首先,我们要理解内存地址的概念。在程序运行时,操作系统为代码和数据分配内存空间,每一个内存单元都有一个唯一的编号,称为内存地址...

    彻底搞定C语言指针————

    C语言指针是C语言中一个非常重要的概念,但它却是初学者最容易迷惑和混淆的部分。要真正搞定C语言指针,需要深入理解C语言变量的存储实质和内存空间的概念。 1. 变量的存储实质 内存空间可以看作是一个存放数据的...

    C语言指针函数和函数指针详细介绍.

    C语言指针函数和函数指针详细介绍 C语言中指针函数和函数指针是两个不同的概念,但它们之间存在着紧密的联系。本文将对C语言中的指针函数和函数指针进行详细的介绍。 一、指针函数 指针函数是指返回值为指针的...

    C语言指针课程PPT

    【C语言指针课程PPT】讲解了C语言中核心的指针概念,它是C语言高效编程的关键。指针允许程序直接访问内存地址,增强了代码的灵活性和性能。以下是关于指针的详细知识点: 1. **变量与内存地址**: - 当在C语言中...

    C语言指针题库

    C语言指针题库 本资源摘要信息是关于C语言指针的题库,涵盖了计算机等级二级考试中的相关内容。该资源包含选择题和编程题,旨在帮助考生和学习者提高C语言指针的知识和技能。 指针基本概念 在C语言中,指针是一种...

    指针详解——介绍C语言指针,看过这个,笔试无忧

    《指针详解——C语言指针完全解析》 在C语言的世界中,指针是一个强大的工具,也是理解和掌握C语言的关键。本文将深入探讨指针的概念、类型、运算及其在笔试中的重要性。 首先,我们要了解什么是指针。指针是一个...

    C语言指针详解 C语言指针详解

    本篇文章将深入探讨C语言指针的各个方面。 首先,我们需要了解指针的声明方式。在声明指针时,我们会指定指针所指向的数据类型。例如: 1. `int *p;` 这里,`p`是一个指针,它指向一个`int`类型的变量。`*`表示...

    c语言指针课件

    c语言 指针 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件 c语言指针课件

    C语言 指针问题 指针问题

    详细讲解了指针的用法和注意事项,指针是我们在学习C语言过程中的一个难点,所以就我个人的一点心得和大家分享一下

    C语言指针详解(通俗易懂).pdf

    C语言中的指针是一个非常核心和重要的概念,它提供了操作内存空间的能力,这对于理解C语言和编写高效的代码至关重要。以下是对文件中提到的知识点的详细解释。 首先,指针概念的基础在于理解变量在内存中的存储方式...

    C语言指针实现字符串的反转

    C语言指针实现字符串的反转 本文主要讨论了使用C语言指针实现字符串的反转的方法,并提供了两个不同的实现程序。 标题解释 "C语言指针实现字符串的反转"这个标题表明本文的主要内容是使用C语言中的指针来实现字符...

    c语言指针完整教程

    c语言指针完整教程 指针不会用 不敢用 你敢说自己会C吗

    C语言指针详解(让你不再惧怕指针)

    在C语言中,指针是一个变量,它存储的是另一个变量的内存地址。当我们声明一个指针变量时,需要指定它所指向的数据类型,例如`int *p;`表示`p`是一个指向整型变量的指针。 接下来是指针的初始化。未初始化的指针...

    精选C语言指针资料大全

    "精选C语言指针资料大全"集合了多种资源,旨在帮助初学者和深入研究者更好地理解和掌握这一核心概念。以下是对这些资源中可能包含的知识点的详细解释。 1. **C指针宝典**: - 指针基础:理解指针是什么,如何声明...

    c语言指针详解,10分钟学会指针用法

    C语言指针详解 C语言指针是一种关键的数据类型,想要学好C语言就必须掌握指针的用法。本篇文章将详细介绍C语言指针的基本概念、指针的声明和使用、数组指针的加减运算、指针之间的运算、指针之间的大小比较、数组...

Global site tag (gtag.js) - Google Analytics