博文

(转)关于指针及数组的基本概念问题(2006-07-28 03:44:00)

摘要:原贴: http://www.programfan.com/club/showbbs.asp?id=95120xiangyu138的答复 回答网友的问题:主题:关于指针及数组的基本概念问题1.请问如下的函数参数定义是不是相等的,用指针做参数有什么意义Node(double *xyz) { x = xyz[0]; y = xyz[1]; z = xyz[2]; }Node(double xyz[3]) { x = xyz[0]; y = xyz[1]; z = xyz[2]; }答:两者是相等的,而且第一种其实更标准,因为第二种也是转化为第一种。在函数形式参数里是没有数组的,都被转化为指针了。所以这时在函数里面没有办法通过像:sizeof(xyz)/sizeof(xyz[0])来取得数组元素的个数(因为根本就不是数组),所以一般还要传递一个数组元素个数的值,否则编这个函数的人不知道你原来的数组个数是多少。如:Node(double xyz[],int n) { x = xyz[0]; y = xyz[1]; z = xyz[2]; } 2.单看double *xyz 的定义,是不是数或数组都可以传递。但是看了{ x = xyz[0]; y = xyz[1]; z = xyz[2]; }这个具体实现所以才知道要传递一个数组过来?答:这个完全错,是看形式参数double *xyz 就知道要传递一个一次指针(一次地址)过来,你要是传数值就会出错的,而且不能传二次指针如:char **argv;的argv。 3.请问 main(int argc,char **argv)这里面的char **argv 具体是表示的是什么意思,传递参数进来时,是应该传递一个指针还是其他,谢谢!答:char **argv 是二次指针,也就是二次地址的意思,就是地址的地址(本身地址也是一个二进制数,它也需要一个地址来保存的哦)。可以传char *aa[];这个是指针数组(也就是数组的元素是指针),或者是二次指针char **a。 **************************1.那为什么我看大部分都喜欢用指针而不直接用数组呢?我觉得用数组定义的很清楚啊答:随便你了,没有所谓的大部分的,其实两者的速度差不多的。3.传 char* p[3] = { "abc", "1234567......

阅读全文(1737) | 评论:0

[转]const型指针变量(2006-07-28 03:43:00)

摘要:有三种不同的方法来说明const变量,其作用和含义都是不同的。 第一式:将const放在指针变量的类型之前。表示指针变量所指向的数据是一个常量,即不能改变指针变量所指向的数据值,但可以改变指针变量的值。   int x, y;    const int *p = &x;  *p = 24;     // ERROR  p = &y;     // OK 第二式:将const放在指针变量的*后。表示指针变量的值是一个常量,即不能改变指针的值,但可以改变指针变量所指向的数据值。     int n, i;    int *const p = &n;    *p = 25;   // ok    *p = &i;   // error 第三式:把一个const放在指针变量的类型之前,将另一个const放在指针变量的*后。表示指针变量的值是一个常量,指针变量所指向的数据也是一个常量。二者都不能改变。     int j, k;    const int *const pp = &j;    *pp = 25;  // error    pp = &k;   // error const类型的指针主要用做函数的参数,以限制在函数体内不能修改指针变量的值,或不能修改指针所指向的数据值。......

阅读全文(1901) | 评论:0

[转]关于指针的教程(2006-07-28 03:42:00)

摘要:什么是指针?   其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据。这是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表。 开始学习   如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名字前加上一个星号。我们来看一个例子:   下面这个程序定义了两个指针,它们都是指向整型数据。 int* pNumberOne; int* pNumberTwo;   你注意到在两个变量名前的“p”前缀了吗?这是程序员通常在定义指针时的一个习惯,以提高便程序的阅读性,表示这是个指针。现在让我们来初始化这两个指针: pNumberOne = &some_number; pNumberTwo = &some_other_number;   &号读作“什么的地址”,它表示返回的是变量在内存中的地址而不是变量本身的值。在这个例子中,pNumberOne 等于some_number的地址,所以现在pNumberOne指向some_number。 如果现在我们在程序中要用到some_number,我们就可以使用pNumberOne。 我们来学习一个例子:   在这个例子中你将学到很多,如果你对指针的概念一点都不了解,我建议你多看几遍这个例子,指针是个很复杂的东西,但你会很快掌握它的。   这个例子用以增强你对上面所介绍内容的了解。它是用C编写的(注:原英文版是用C写的代码,译者重新用C++改写写了所有代码,并在DEV C++ 和VC++中编译通过!) #include <iostream.h> void main() { // 声明变量: int nNumber; int *pPointer; // 现在给它们赋值: nNumber = 15; pPointer = &nNumber; //打印出变量nNumber的值: cout<<"nNumber is equal to :"<< nNumber<<endl; // 现在通过指针改变nNumber的值: *pPointer = 25; //证明nNumber已经被上面的程序改变 //重新打印出nNumber的值: cou......

阅读全文(1150) | 评论:0

[转]关于指针(2006-07-28 03:41:00)

摘要:  不可否认,指针是C的精华,也是C的难点。每一个学C的人,当年应该都是在“漆黑”中摸过来的。我现在编程序时用指针用得很多,可以说绝大多数值与是通过指针来传递的,而struct、class的实例等则是完全用指针或引用来传递的。  我不敢说我是什么高手,也不敢说我对指针有多了解,对于网上的一大堆提问,我不敢说我能很好地回答。但是,我想:我把自己的一点点感悟写出来,多多少少会给读者一点启示。写得不到之处,请读者朋友们斧正。 一、指针就是变量:  虽然申明指针的时候也提类型,如:  char *p1;  int *p2;  float *p3;  double *p4;  .....  但是,这只表示该指针指向某类型的数据,而不表示该指针的类型。说白了,指针都是一个类型:四字节无符号整数。 二、指针的加减运算很特殊:  p++、p--之类的运算并不是让p这个“四字节无符号整数”加一或减一,而是让它指向下一个或上一个存储单元,它实际加减的值就是它所指类型的值的size。  比如:  char *型指针,每次加减的改变量都是1;  float *型的指针,每次加减的改变量都是4;  void *型指针无法加减。  还要注意的是:指针不能相加,指针相减的差为int型。  正是因为指针有着不同于其它变量的运算方式,所以,在任何时候用到指针都必须明确“指针的类型”(即指针所指的变量的类型)。这就不难理解为什么函数声明时必须用“int abc(char *p)”而调用的时候却成了“a = abc(p);”这样的形式了。 三、用指针做参数传递的是指针值,不是指针本身:  要理解参数传递,首先必须把“形参”与“实参”弄明白。  函数A在调用函数B时,如果要传递一个参数C,实际是在函数B中重新建立一个变量C,并将函数A中的C值传入其中,于是函数B就可以使用这个值了,在函数B中,无论有没有修改这个C值,对于函数A中的C都没有影响。函数B结束时,会将所有内存收回,局部变量C被销毁,函数B对变量C所做的一切修改都将被抛弃。  以上示例中,函数A中的变量C称为“实参”,函数B中的变量C被称为“形参”,调用函数时,会在B函数体内建立一个形参,该形参的值与实参的值是相同的,但是形参的改变不影响实参,函数结束时,形参被销毁,实参依然没有发生变化。  指针也是一个变量,所以它也符合以上的......

阅读全文(1770) | 评论:0

[转]指针本质论(2006-07-28 03:40:00)

摘要: 指针本质论   指针是一个变量,是用来存储地址的变量。这就是指针的本质。  有人可能很纳闷,指针为什么一定要定义成某类型(int, char)呢,不能就是“指针类型”吗?接触过汇编的就容易理解为什么。存储单元的单位是字节,对一个地址进行操作(读取或赋值)就要指明是对单个字节、两个字节、还是双字(四字节)。同样,指针是存储地址的,说白了,指针就是一个地址,自然也要说明了;而且,这个类型还关乎指针自加自减时真正加减的字节数。    顺便说一下,数组名也是指针,数组在申请空间时数组名存储该存储空间的首地址,注意数组名存储的是地址,因此也是指针,只是该指针一旦赋值后就不能修改,即所谓常指针。***************************  如下函数希望为指针p申请空间,但不能达到目的,为什么呢?void GetMemory(char *p){    char *s=NULL;    s= (char*)malloc(100*sizeof(char));     p=s;}  归根结底,C函数形参实参之间只是“值传递”:当形参是普通变量时,传递的是实参的值;当形参是指针时,传递的是指针变量的值,即某变量的地址,这样,可以通过指针成功的改变其所指单元的值,但自身的改变不会传回给实参。上例可改为:void GetMemory(char **p){    char *s=NULL;    s= (char*)malloc(100*sizeof(char));     *p=s;}注意这样修改后,调用时实参应该是指针的“地址”(或指向指针的指针)。  见下例,Test函数可以成功修改a[0]的值,尽管形参a的值发生了变化,但不会改变实参a的值,这就说明指针形参的改变不影响指针实参的改变,但通过形参指针修改了其所对应的存储单元的值是,这改变将影响到实参。#include <iostream>using namespace std;void Test(int *a){ *(a++) = 5; //该函数真正所做的修改:将a所指存储空间的值赋为5,并将a值加1 cou......

阅读全文(1547) | 评论:0

[转帖]C语言中数组和指针的互操作(2006-07-28 03:40:00)

摘要:C语言中数组和指针的互操作    曾听好多朋友说,C是一种怀旧的语言,因为它的历史很久远,然而自从各种面向对象的编程语言的相续出现让它的影响力日减。当然了,这是无可非议的,但是C的高效性其他语言无妨比拟的,所以我们有必要把握其中的精华与奥妙,也就有必要知道其中的基本的数据结构的比如数组,稍微有点深度的堆栈、列表、结构体等的操作和实现。指针也是C语言中的一个很优秀灵活的结构,对它的了解也是必不可少的。    我们一般都认为数组是一维的数据存储结构,因为二位数组或者说矩阵都可以看作是多个一维数组的组合结构,定义在其上的数据存储访问方式是一样的。所以一维数组是其中最基础的最重要的部分,只有理解了此类数据结构的本质才能触类旁通了。    数组(array)是若干同类变量的聚合,允许通过统一的名字饮用其中的变量。所以数组也就是一个同一类型的数据的有限集合。可以通过下表来访问数组中的某一/些数组元素。在C语言中数组都由连续的内存区域构成(有时候,不一定是这样),最低地址对应首元素,数组的下标是从0开始的,所以首元素也就是数组下标为0的元素,最高的地址对应最末的元素,即第N-1个元素(如果我们定义的数组为N元)。数组的定义方式:    在C语言中允许在声明数组的时候同时对其进行初始化,也可以把声明和定义放在不同的位置,初始化的一般的类似于如下的表达式:type_specifier array_name[size1]...[sizeN] = {value_list};其中vlaue_list是由逗号(,)分隔的常量表,常量表必须和type_specifier兼容。最后由分号与下一个语句分隔。由此可见一维数组的定义方式为:type_specifier array_name[size] = {value_list};如下:char hello[12] = {'H','e','l','l','o',',',' ','w','o','r','l','d','\0'};     注意:字符数组是一"'\0'"收尾的,这是C标准的一部分。因为在操作字符数组的时候是以'\0'作为结束判断的标志。当然......

阅读全文(1389) | 评论:0

[转]动态申请的问题(2006-07-28 03:39:00)

摘要:前几天写一个函数,需要一个不定长的数组,又由于是在函数中需要修改的,就做了下边的定义: PointStruct *pPoint=new PointStruct[]; pPoint[0].x=0; pPoint[1].x=1; ………… 想通过这样实现动态添加元素,后来发现只能申请到3个,pPoint[3]就不能被赋值了,编译没有出错提示,但一运行就报错。 之后又改为pPointStruct *pPoint=new PointStruct{1,2,3,4,……,n};之后再赋值pPoint[n+1]=n+1;pPoint[n+2]=n+2;……后来发现只能赋值到pPoint[2n+1],当再给pPoint[2n+2]赋值时,就又会出现编译没有错误,一运行就报错的情况。 总结:用pPointStruct *pPoint=new PointStruct{1,2,3,4,……,n};的形式申请了n个存储空间,但实际上还有另外n+1个空间,作为备用的,所以在申请n个之后还能继续添加,直到n+1个,再往后就不行了.至于PointStruct *pPoint=new PointStruct[];的形式为什么会有那样的结果,我也想不出来^_^,也许那本身就是一个错误的语句吧! 这些都是个人想的,不知道是否真的像我想的那样,希望各位有不同见解能说出来. 关于指针动态申请2 还是有关指针的动态申请空间的问题. 定义了PointStruct* pPointxy;      pPointxy=new PointStruct [4]; fun(x1,y1,x2,y2,pPointxy); 在程序中fun函数共执行了10次,每次执行之后都将pPointxy的每个元素赋给另外一个数组接收,调试发现最后一次执行fun函数的时候,pPointxy的最后一个元素的值就出现了异常. 仔细查找后发现很奇怪的现象,在fun前设置一个断点,在fun之后设置一个断点,当执行到第一个断点的时候,pPointxy的各个元素的值都正常,但当到下一个断点的时候,pPointxy的最后一个元素的值竟然发生了改变!我是在紧接着fun之后设的断点,两个断点之间根本就没有对pPontxy修改的语句.也就是说只在fun函数中被修改的pPointxy在函......

阅读全文(1729) | 评论:0

《彻底搞定C指针》第7篇 函数名与函数指针(2006-07-28 03:36:00)

摘要:第7篇 函数名与函数指针 白云小飞 一 通常的函数调用    一个通常的函数调用的例子://自行包含头文件void MyFun(int x);    //此处的申明也可写成:void MyFun( int );int main(int argc, char* argv[]){   MyFun(10);     //这里是调用MyFun(10);函数      return 0;}void MyFun(int x)  //这里定义一个MyFun函数{   printf(“%d\n”,x);}    这个MyFun函数是一个无返回值的函数,它并不完成什么事情。这种调用函数的格式你应该是很熟悉的吧!看主函数中调用MyFun函数的书写格式:MyFun(10);    我们一开始只是从功能上或者说从数学意义上理解MyFun这个函数,知道MyFun函数名代表的是一个功能(或是说一段代码)。    直到——    学习到函数指针概念时。我才不得不在思考:函数名到底又是什么东西呢?    (不要以为这是没有什么意义的事噢!呵呵,继续往下看你就知道了。)二 函数指针变量的申明    就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也以存储在某个函数指针变量里的。这样,我就可以通过这个函数指针变量来调用所指向的函数了。    在C系列语言中,任何一个变量,总是要先申明,之后才能使用的。那么,函数指针变量也应该要先申明吧?那又是如何来申明呢?以上面的例子为例,我来申明一个可以指向MyFun函数的函数指针变量FunP。下面就是申明FunP变量的方法:void (*FunP)(int) ;   /......

阅读全文(1144) | 评论:0

《彻底搞定C指针》第6篇 指向另一指针的指针(2006-07-28 03:35:00)

摘要: 第六篇 指向另一指针的指针 白云小飞 一. 回顾指针概念:早在本系列第二篇中我就对指针的实质进行了阐述。今天我们又要学习一个叫做指向另一指针地址的指针。让我们先回顾一下指针的概念吧!当我们程序如下申明变量:short int i;char a;short int * pi;程序会在内存某地址空间上为各变量开辟空间,如下图所示。内存地址→6     7      8     9     10     11    12    13     14    15-------------------------------------------------------------------------------------…  |     |      |      |      |      |       |      |      |      |   -------------------------------------------------------------------------------------   ......

阅读全文(1115) | 评论:0

《彻底搞定C指针》-——第5篇:函数参数的传递(下) (2006-07-28 03:34:00)

摘要: 《彻底搞定C指针》-——第5篇:函数参数的传递(下) 白云小飞 三. 函数参数传递方式之二:地址传递继续——地址传递的问题!看题二的代码:Exchg2(int *px, int *py){  int tmp=*px;  *px=*py;  *py=tmp;  print(“*px=%d,*py=%d\n”,*px,*py);}main(){  int a=4;  int b=6;      Exchg2(&a,&b);      Print(“a=%d,b=%d\n”, a, b);}它的输出结果是:  *px=6,*py=4  a=6,b=4    看函数的接口部分:Exchg2(int *px,int *py),请注意:参数px,py都是指针。    再看调用处:Exchg2(&a, &b);    它将a的地址(&a)代入到px,b的地址(&b)代入到py。同上面的值传递一样,函数调用时作了两个隐含的操作:将&a,&b的值赋值给了px,py。px=&a;py=&b;    呵呵!我们发现,其实它与值传递并没有什么不同,只不过这里是将a,b的地址值传递给了px,py,而不是传递的a,b的内容,而(请好好地在比较比较啦)    整个Exchg2函数调用是如下执行的:   px=&a;   //  py=&b;   //请注意这两行,它是调用Exchg2的隐含动作。  int tmp=*px;  *px=*py;  *py=tmp;&......

阅读全文(1308) | 评论:1