`
fuerbosi
  • 浏览: 466193 次
文章分类
社区版块
存档分类
最新评论

一个问题引起的思考

 
阅读更多

看了巨人网络招聘题目,感觉到自己的基础知识还是不够行。乡亲们,有病的治病,没病的也可强身健体。

#include <stdio.h>
#include<malloc.h>
#include<string.h>


void GetMemory( char *p )
{
    p = (char *) malloc( 100 );
}


void main( void )
{
    char *str = NULL;
    GetMemory( str );
    strcpy( str, "hello world" );
    printf( str );
}
问运行结果。。。

一开始没能明白什么意思,经过一番的探索,才渐渐。。。。。道声,,哦。、

其实我压根就没明白char *指针的真正含义,原来是这样的。

例:

char *s="abc";
char str[]="abccd";

1、char *s="abc";

看这个赋值:

右边,是"abc",是个字符串常量,存在于内存某处(我的机器上是ds:0x0046f034),程序员不知道,编译器安排的,也没必要知道(当然,这个赋值之后,程序员就知道并能控制这个串了)。字符串常量所在内存是只读的。

左边,字符指针s,赋值时候,把地址ds:0x0046f034的偏移地址("abc"所在),存放到指针变量s(其地址为 ds:0x0046f034)中。程序员能完全控制的内存只是指针变量所占据的这四个字节内存,只能改变该指针的指向,至于其指向的内存能不能写,那就看程序了,本程序是指向的只读内存,不能写!

2、char str[]="abccd";

再看这个赋值:

右边,和上面类似,是"abccd",也是个字符串常量,存在于内存某处(是ds:0x0046f02c),程序员不知道,编译器安排的(这个赋值之后,程序员还是不知道这个常量在哪里,因为并没有用指针指向这块内存,这和上面不同)。该字符串常量所在内存也是只读的。

左边,字符数组str,赋值时候,把地址ds:0x0046f02c("abccd"所在)所指内存中的内容,复制到字符数组str开始(其地址为 ds:0x0013ff74)的内存中,每复制一个字符都会开辟一个字节(char型变量占1字节)内存来存放这个字符(这也是实现了数组元素个数的动态确定)。从字符数组str开始的这部分存放这些字符的内存是程序员可以完全控制的,可读写,因此在这些内存写当然是没有问题的!

到这里,突然想到多年前看过的一本书《C和指针》(Kenneth A. Reek著,徐波 译,现在有第二版了¥65,第一版¥55,不便宜,但是是好书,值得研读,是研读哦,不是翻翻,当然翻翻也会有收获的)里面好像提到过这个问题,赶快拿来看看(字符数组的初始化一节),果然这样。

许多程序员对数组名和指针的区别不甚明了,他们认为数组名就是指针,而实际上数组名和指针有很大区别,在使用时要进行正确区分,其区分规则如下:


规则1 数组名指代一种数据结构,这种数据结构就是数组;
char str[10];
char *pStr = str;
cout << sizeof(str) << endl;
cout << sizeof(pStr) << endl;

输出结果为:
10
4
  这说明数组名str指代数据结构char[10]。


规则2 数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;
char str[10];
char *pStr = str;
str++; //编译出错,提示str不是左值 
pStr++; //编译正确

规则3 指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址;

规则4 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。


例如:
void arrayTest(char str[])
{
cout << sizeof(str) << endl;   //输出指针长度
    str++; //编译正确
}


int main(int argc, char* argv[])
{
 char str1[10] = "I Love U";
 arrayTest(str1);
return 0;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics