文档库 最新最全的文档下载
当前位置:文档库 › c语言指针例子

c语言指针例子

c语言指针例子
c语言指针例子

深入理解c语言指针的奥秘

指针的概念

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。

先声明几个指针放着做例子:

例一:

(1)int*ptr;

(2)char*ptr;

(3)int**ptr;

(4)int(*ptr)[3];

(5)int*(*ptr)[4];

如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<如何理解c和c ++的复杂类型声明>>。

指针的类型

从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:

(1)int*ptr;//指针的类型是int*

(2)char*ptr;//指针的类型是char*

(3)int**ptr;//指针的类型是int**

(4)int(*ptr)[3];//指针的类型是int(*)[3]

(5)int*(*ptr)[4];//指针的类型是int*(*)[4]

怎么样?找出指针的类型的方法是不是很简单?

指针所指向的类型

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。

从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:

(1)int*ptr;//指针所指向的类型是int

(2)char*ptr;//指针所指向的的类型是char

(3)int**ptr;//指针所指向的的类型是int*

(4)int(*ptr)[3];//指针所指向的的类型是int()[3]

(5)int*(*ptr)[4];//指针所指向的的类型是int*()[4]

在指针的算术运算中,指针所指向的类型有很大的作用。

指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的"类型"这个概念分成"指针的类型"和"指针所指向的类型"两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。

指针的值,或者叫指针所指向的内存区或地址

指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为si zeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。

指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。

以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里?

指针本身所占据的内存区

指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。

指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。

指针的算术运算

指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:

例二:

1、chara[20];

2、int*ptr=a;

...

...

3、ptr++;

在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。

由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。

我们可以用一个指针和一个循环来遍历一个数组,看例子:

例三:

intarray[20];

int*ptr=array;

...

//此处略去为整型数组赋值的代码。

...

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

{

(*ptr)++;

ptr++;

}

这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,所以每次循环都能访问数组的下一个单元。

再看例子:

例四:

1、chara[20];

2、int*ptr=a;

...

...

3、ptr+=5;

在这个例子中,ptr被加上了5,编译器是这样处理的:将指针ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的ptr所指向的地址来说,向高地址方向移动了20个字节。在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。

如果上例中,ptr是被减去5,那么处理过程大同小异,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。

总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加了n乘sizeof(ptrold所指向的类型)个字节。就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向高地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。

一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值减少了n 乘sizeof(ptrold所指向的类型)个字节,就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。

运算符&和*

这里&是取地址运算符,*是...书上叫做"间接运算符"。

&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。

*p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。

例五:

inta=12;

intb;

int*p;

int**ptr;

p=&a;

//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。

*p=24;

//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。ptr=&p;

//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int **。该指针所指向的类型是p 的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。

*ptr=&b;

//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以用&b 来给*ptr赋值就是毫无问题的了。

**ptr=34;

//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。

指针表达式

一个表达式的最后结果如果是一个指针,那么这个表达式就叫指针表式。

下面是一些指针表达式的例子:

例六:

inta,b;

intarray[10];

int*pa;

pa=&a;//&a是一个指针表达式。

int**ptr=&pa;//&pa也是一个指针表达式。

*ptr=&b;//*ptr和&b都是指针表达式。

pa=array;

pa++;//这也是指针表达式。

例七:

char*arr[20];

char**parr=arr;//如果把arr看作指针的话,arr也是指针表达式

char*str;

str=*parr;//*parr是指针表达式

str=*(parr+1);//*(parr+1)是指针表达式

str=*(parr+2);//*(parr+2)是指针表达式

由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。

好了,当一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。

在例七中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是指针pa,既然pa已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。

数组和指针的关系

如果对声明数组的语句不太明白的话,请参阅我前段时间贴出的文章<<如何理解c和c++的复杂类型声明>>。

数组的数组名其实可以看作一个指针。看下例:

例八:

intarray[10]={0,1,2,3,4,5,6,7,8,9},value;

...

...

value=array[0];//也可写成:value=*array;

value=array[3];//也可写成:value=*(array+3);

value=array[4];//也可写成:value=*(array+4);

上例中,一般而言数组名array代表数组本身,类型是int[10],但如果把array看做指针的话,它指向数组的第0个单元,类型是int*,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。其它依此类推。

例九:

char*str[3]={

"Hello,thisisasample!",

"Hi,goodmorning.",

"Helloworld"

};

chars[80];

strcpy(s,str[0]);//也可写成strcpy(s,*str);

strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));

strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));

上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char*。

*str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,thisisasample!"的第一个字符的地址,即'H'的地址。str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char*。

*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向"Hi,goodmorning."的第一个字符'H',等等。

下面总结一下数组的数组名的问题。声明了一个数组TYPEarray[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE[n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。

在不同的表达式中数组名array可以扮演不同的角色。

在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数测出的是整个数组的大小。

在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第0号单元的值。sizeof(*array)测出的是数组单元的大小。

表达式array+n(其中n=0,1,2,....。)中,array扮演的是指针,故array+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。故sizeof(array+n)测出的是指针类型的大小。

例十:

intarray[10];

int(*ptr)[10];

ptr=&array;

上例中ptr是一个指针,它的类型是int(*)[10],他指向的类型是int[10] ,我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。

本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:

int(*ptr)[10];

则在32位程序中,有:

sizeof(int(*)[10])==4

sizeof(int[10])==40

sizeof(ptr)==4

实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。

指针和结构类型的关系

可以声明一个指向结构类型对象的指针。

例十一:

structMyStruct

{

inta;

intb;

intc;

}

MyStructss={20,30,40};

//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。

MyStruct*ptr=&ss;

//声明了一个指向结构对象ss的指针。它的类型是MyStruct*,它指向的类型是MyStruct。

int*pstr=(int*)&ss;

//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。

请问怎样通过指针ptr来访问ss的三个成员变量?

答案:

ptr->a;

ptr->b;

ptr->c;

又请问怎样通过指针pstr来访问ss的三个成员变量?

答案:

*pstr;//访问了ss的成员a。

*(pstr+1);//访问了ss的成员b。

*(pstr+2)//访问了ss的成员c。

虽然我在我的MSVC++6.0上调式过上述代码,但是要知道,这样使用pstr来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指针来访问数组的各个单元:

例十二:

intarray[3]={35,56,37};

int*pa=array;

通过指针pa访问数组array的三个单元的方法是:

*pa;//访问了第0号单元

*(pa+1);//访问了第1号单元

*(pa+2);//访问了第2号单元

从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。

所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个"填充字节",这就导致各个成员之间可能会有若干个字节的空隙。

所以,在例十二中,即使*pstr访问到了结构对象ss的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。因为成员a和成员b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,嘿,这倒是个不错的方法。

通过指针访问结构成员的正确方法应该是象例十二中使用指针ptr的方法。

指针和函数的关系

可以把一个指针声明成为一个指向函数的指针。

intfun1(char*,int);

int(*pfun1)(char*,int);

pfun1=fun1;

....

....

inta=(*pfun1)("abcdefg",7);//通过函数指针调用函数。

可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。

例十三:

intfun(char*);

inta;

charstr[]="abcdefghijklmn";

a=fun(str);

...

...

intfun(char*s)

{

intnum=0;

for(inti=0;i{

num+=*s;s++;

}

returnnum;

}

这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s 所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s 进行自加1运算,并不意味着同时对str进行了自加1运算。

指针类型转换

当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向的类型是一样的。

例十四:

1、floatf=12.3;

2、float*fptr=&f;

3、int*p;

在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的语句吗?

p=&f;

不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一个指针,指针的类型是float*,它指向的类型是float。两者不一致,直接赋值的方法是不行的。至少在我的MSVC++6.0

上,对指针的赋值语句要求赋值号两边的类型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了实现我们的目的,需要进行"强制类型转换":

p=(int*)&f;

如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*TYPE,那么语法格式是:(TYPE*)p;

这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都没有被修改。

一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结合过程中,也会发生指针类型的转换。

例十五:

voidfun(char*);

inta=125,b;

fun((char*)&a);

...

...

voidfun(char*s)

{

charc;

c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;

c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;

}

}

注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用语句中,实参&a的结果是一个指针,它的类型是int*,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针char*temp,然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。

我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象下面的语句:

unsignedinta;

TYPE*ptr;//TYPE是int,char或结构类型等等类型。

...

...

a=20345686;

ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制

ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制)

编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到了吗?不,还有办法:

unsignedinta;

TYPE*ptr;//TYPE是int,char或结构类型等等类型。

...

...

a=某个数,这个数必须代表一个合法的地址;

ptr=(TYPE*)a;//呵呵,这就可以了。

严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候,就会出现非法操作错误。

想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个整数当作一个地址赋给一个指针:

例十六:

inta=123,b;

int*ptr=&a;

char*str;

b=(int)ptr;//把指针ptr的值当作一个整数取出来。

str=(char*)b;//把这个整数的值当作一个地址赋给指针str。

现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针。

指针的安全问题

看下面的例子:

例十七:

chars='a';

int*ptr;

ptr=(int*)&s;

*ptr=1298;

指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。

让我们再来看一例:

例十八:

1、chara;

2、int*ptr=&a;

...

...

3、ptr++;

4、*ptr=115;

该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。

在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例十七来想一想,应该会明白的。

如何透彻理解C语言中指针的概念

如何透彻理解C语言中指针的概念 强大的指针功能是C语言区别于众多高级语言的一个重要特征。C语言指针的功能强大,使用灵活多变,可以有效地表示复杂的数据结构、动态分配内存、高效地使用数组和字符串、使得调用函数时得到多个返回值。而它的应用远不限于此。初学者对于指针的概念总是感到无所适从,有时觉得“自己懂了,为什么编译器就是不懂呢”,常有茫然和无助的感觉。 学好指针的关键在于深入了解内存地址的空间可以理解为一个一维线性空间,内存的编址和寻址方法,以及指针在使用上的一些规定。事实上,指针就是方便我们对内存地址直接进行操作的,是为程序员服务的,我们只要抓住指针想要帮助我们解决什么问题这个核心,就可以轻松地理解它的工作原理。 什么是指针,指针有什么作用 指针就是指向一个特定内存地址的一个变量。简化了的内存空间模型是按照从0到某一个数(比如1048575=1M-1)的一维线性空间,其中的每一个数对应一个存储单元,即1个字节。指针有两个属性:指向性和偏移性。指向性指的是指针一定要有一个确定的指向,偏移性则是体现指针重要应用的方面,即指针可以按程序员的要求向前或向后偏移。 指针的应用往往与数组联系在一起,为了方便说明问题,不妨从数组开始解释指针的偏移。数组就是许多的变量,它的一个重要特征就是在内存空间中连续地存放,而且是按下标顺序存放。比如我们定义一个有100个变量的一维整型数组,它一定从内存的某一个存储单元开始按数组下标顺序存放,连续占用100*4=400字节。当我们定义一个数组时,系统就会自动为它分配一个指针,这个指针指向数组的首地址。(在本文剩余部分的论述中,不加区分地使用“指向数组的首地址”与“指向数组的第一个元素”这两种说法,事实上这两种说法也是一致的。) 为了让系统了解每一次指针偏移的单位,也为了方便程序员进行指针偏移(让程序员记住一个整形变量占用4字节,一个字符型变量占用1字节……等等是很麻烦的),不用每次去计算要偏移多少个字节,C语言引入了指针的基类型的概念。基类型的作用就是让系统了解某个指针每次偏移的字节数。比如,对于一个字符型指针,它每次偏移(比如ptr=ptr+1)所起到的作用就是让指针偏移1字节;而对于一个整型指针,它每次偏移就应该是4字节。这样操作数组时就带来了方便。比如对于一个指向某个整型数组起始存储单元(称为首地址)的指针ptr,ptr=ptr+1就表示将该指针指向这个数组的下一个元素的存储单元,即向后移动4字节,而不仅仅是移动一个存储单元(即移动1字节)。 &()、*()、和[ ]运算符的意义 在本文中,将&()、*()和[ ]都看成是运算符。这样可以方便理解这三个概念。简单地说,&()将某个标识符(比如变量)转化为其在内存空间中的地址,而*()是产生一个对应于某个地址的标识符,[ ]就更复杂一点,ptr[i]表示

C语言入门学习-C上机实验九要求

上机实验九函数综合练习一 【实验八参考答案见后】 目的和要求: (1)熟练掌握参数传递的要领; (2)掌握全局变量的使用要领; (3)了解静态局部变量的特点。 实验内容: 一、完善程序题 1.求10! 【提示:本程序利用静态局部变量保留每次调用函数的结果。】 #include #define N 10 ________________________________; main() {int i; long f; for(i=1;i<=N;i++) f=____________________________; printf("%d!=%ld\n",N,f); } long JC(int n) {______________________________; jc=jc*n; return jc; } 2.以下程序中的trap函数是一个用梯形法求定积分的通用函数,梯形法求定积分s的公式为: ∑-=+ + + = 1 n 1 i h * h)) *i f(a f(b))/2 ((f(a) s, n b a h - = 其中n为积分小区间数,以下程序调用trap函数求定积分,被积函数是:f(x)=x*x+3*x+2,且n=1000,a=0,b=4。(程序运行结果参考:53.333344)#include #include double mypoly(double x) {return(x*x+3.0*x+2.0); } double trap(double a,double b) {double t,h; int i,n=1000; t=0.5*(mypoly(a)+mypoly(b)); h=______________/(double)(n);

c语言结构体用法(转载)

C语言,结构体(struct) 用法 结构(struct) 结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。 结构中可以使用不同的数据类型。 1. 结构说明和结构变量定义 在T urbo C中, 结构也是一种数据类型, 可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。 定义结构变量的一般格式为: struct 结构名 { 类型变量名; 类型变量名; ... } 结构变量; 结构名是结构的标识符不是变量名。 类型为第二节中所讲述的五种数据类型(整型、浮点型、字符型、指针型和 无值型)。 构成结构的每一个类型变量称为结构成员, 它象数组的元素一样, 但数组中 元素是以下标来访问的, 而结构是按变量名字来访问成员的。

下面举一个例子来说明怎样定义结构变量。 struct string { char name[8]; int age; char sex[2]; char depart[20]; float wage1, wage2, wage3, wage4, wage5; } person; 这个例子定义了一个结构名为string的结构变量person, 如果省略变量名 person, 则变成对结构的说明。用已说明的结构名也可定义结构变量。这样定义 时上例变成: struct string { char name[8]; int age; char sex[2]; char depart[20]; float wage1, wage2, wage3, wage4, wage5; }; struct string person; 如果需要定义多个具有相同形式的结构变量时用这种方法比较方便, 它先作 结构说明, 再用结构名来定义变量。 例如: struct string T ianyr, Liuqi, ...; 如果省略结构名, 则称之为无名结构, 这种情况常常出现在函数内部, 用这 种结构时前面的例子变成:

C语言基础知识(详细版)

C语言程序的结构认识 用一个简单的c 程序例子,介绍c 语言的基本构成、格式、以及良好的书写风格,使小伙伴对 c 语言有个 初步认识。 例1:计算两个整数之和的c 程序: #include main() { int a,b,sum; /* 定义变量a,b ,sum 为整型变量*/ a=20; /* 把整数20 赋值给整型变量a*/ b=15; /* 把整数15 赋值给整型变量b*/ sum=a+b; /* 把两个数之和赋值给整型变量sum*/ printf( “ a=%d,b=%d,sum=%d\n” ,a,b,sum); /* 把计算结果输出到显示屏上*/ } 重点说明: 1、任何一个c 语言程序都必须包括以下格式: main() { } 这是c 语言的基本结构,任何一个程序都必须包含这个结构。括号内可以不写任何内容,那么该程序将不执行任何结果。 2、main() - 在c 语言中称之为“主函数” ,一个c 程序有且仅有一个main 函数,任何一个c 程序总是从 main 函数开始执行,main 函数后面的一对圆括号不能省略。 3、被大括号{ }括起来的内容称为main 函数的函数体,这部分内容就是计算机要执行的内容。 4、在{ }里面每一句话后面都有一个分号(; ),在c 语言中,我们把以一个分号结尾的一句话叫做一个 c 语 言的语句,分号是语句结束的标志。 5、printf( “ a=%d,b=%d,sum=%d\n” ,a,b,sum); 通过执行这条c 语言系统提供给我们直接使用的屏幕输出 函数,用户即可看到运行结果,本程序运行后,将在显示器上显示如下结果: a=20,b=15,sum=35 6、#include 注意:(1)以#号开头 (2)不以分号结尾这一行没有分号,所以不是语句,在c 语言中称之为命令行,或者叫做“预编译处理命令” 。 7、程序中以/* 开头并且以*/ 结尾的部分表示程序的注释部分,注释可以添加在程序的任何位置,为了提高程序的可读性而添加,但计算机在执行主函数内容时完全忽略注释部分,换而言之就是计算机当做注释部分不存在于主函数中。 C程序的生成过程 C程序是先由源文件经编译生成目标文件,然后经过连接生成可执行文件。 源程序的扩展名为.c ,目标程序的扩展名为.obj , 可执行程序的扩展名为.exe 。

C语言中不同的结构体类型的指针间的强制转换详解

C语言中不同类型的结构体的指针间可以强制转换,很自由,也很危险。只要理解了其内部机制,你会发现C是非常灵活的。 一. 结构体声明如何内存的分布, 结构体指针声明结构体的首地址, 结构体成员声明该成员在结构体中的偏移地址。 变量的值是以二进制形式存储在内存中的,每个内存字节对应一个内存地址,而内存存储的值本身是没有整型,指针,字符等的区别的,区别的存在是因为我们对它们有不同的解读,param的值就是一个32位值,并且存储在某个内存单元中,通过这个32位值就能找到param所指向的结构的起始地址,通过这个起始地址和各个结构所包含变量离起始地址的偏移对这些变量进行引用, param->bIsDisable只是这种引用更易读的写法,只要param是指向 PAINT_PARAM的指针,那么param的值就肯定存在,param存在,偏移量已知,那么param->bIsDisable就肯定存在,只是要记住,param->bIsDisable只是代表了对param一定偏移地址的值。 不是说某个地址有那个结构体你才能引用,即使没有,你也能引用,因为你已经告诉了编译器param变量就是指向一个PAINT_PARAM结构体的变量并且指明了param的值,机器码的眼中是没有数据结构一说的,它只是机械的按照 指令的要求从内存地址取值,那刚才的例子来说,peg->x,peg->y的引用无论 0x30000000是否存在一个eg结构体都是合法的,如果0x30000000开始的8 个字节存在eg结构体,那么引用的就是这个结构体的值,如果这个位置是未定义的值,那么引用的结果就是这8个字节中的未定义值,内存位置总是存在的,而对内存中值的引用就是从这些内存位置对应的内存单元取值。 举个例子: typedefstruct_eg { int x; int y; }eg;

C语言中一个关于指针传递的问题

C语言中一个关于指针传递的问题 李云 UTStarcom通讯有限公司 E-Box Team 2005-06-22 摘要 指针在C语言中扮演着极为重要的角色,它的存在为C语言提供了极大的灵活性,当然,不少问题也是由指针所引起的(双刃剑)。本文通过分析一个由指针传递所引起的错误,从而使得我们更加重视指针在编程中的传递问题。 关键词 C语言指针传递 缩略语 Significant Byte 最低有效字节 Least LSB MCI Management & Control Interface 管理控制接口 Byte 最高有效字节 MSB Most Significant 1 问题的提出 指针因为灵活使得我们在编程时有意识的利用这一特性,从而使得我们的设计也更加的灵活,如函数指针等等。在很多情况下,我们需要从被调用函数返回结果。这可以通过两种方法来实现,一是通过函数的返回值,二是通过将指针作为参数传递给被调用函数。 图 1.1就是一个例子。 00001:S32 mci_module_id_from_name(S8* name, U16* module_id) 00002:{ 00003:mci_module_t *module; 00004:U16 index = 0; 00005: 00006:if(name == NULL || module_id == NULL) 00007:return ERR_MCI_INV_PRARAM; 00008: 00009:for(;index <= g_mci_last_module_id; index ++) 00010:{ 00011:module = g_mci_module_array[index]; 00012: 00013:if(module == NULL) 00014:continue; 00015: 00016:if(strcmp(module->name, name) == 0) 00017:{ 00018:*module_id = index;

C语言结构体(struct)常见使用方法

C语言结构体(struct)常见使用方法 基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量。 结构体定义: 第一种:只有结构体定义 [cpp]view plain copy 1.struct stuff{ 2.char job[20]; 3.int age; 4.float height; 5.}; 第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义 [cpp]view plain copy 1.//直接带变量名Huqinwei 2.struct stuff{ 3.char job[20]; 4.int age; 5.float height; 6.}Huqinwei; 也许初期看不习惯容易困惑,其实这就相当于: [cpp]view plain copy 1.struct stuff{ 2.char job[20]; 3.int age;

4.float height; 5.}; 6.struct stuff Huqinwei; 第三种:如果该结构体你只用一个变量Huqinwei,而不再需要用 [cpp]view plain copy 1.struct stuff yourname; 去定义第二个变量。 那么,附加变量初始化的结构体定义还可进一步简化出第三种: [cpp]view plain copy 1.struct{ 2.char job[20]; 3.int age; 4.float height; 5.}Huqinwei; 把结构体名称去掉,这样更简洁,不过也不能定义其他同结构体变量了——至少我现在没掌握这种方法。 结构体变量及其内部成员变量的定义及访问: 绕口吧?要分清结构体变量和结构体内部成员变量的概念。 就像刚才的第二种提到的,结构体变量的声明可以用: [cpp]view plain copy 1.struct stuff yourname; 其成员变量的定义可以随声明进行: [cpp]view plain copy 1.struct stuff Huqinwei = {"manager",30,185}; 也可以考虑结构体之间的赋值: [cpp]view plain copy

C语言指针教学中的知识点分析与总结-最新教育文档

C语言指针教学中的知识点分析与总结 C语言是一门重要的计算机基础课程,指针是C语言的精华。 而指针应用范围广、使用灵活等特点时常让初学者感到困惑。 用指针可以访问各种类型的数据,能够实现动态存储分配,提高编程效率,加深对数据存储方式的理解。本文从指针的基本概念,指针在数组、函数、字符串、动态存储分配等方面的应用入手,剖析指针与各部分基础知识相结合时的教学重点和难点。利用对比的方法指出初学者在学习指针过程中易混的概念及注意事项,有利于初学者对指针的理解和掌握。 1指针基本概念的理解 指针学习首先应掌握其基本概念。指针即地址、地址即指针。 程序运行过程中,变量、数组、函数等都存放在内存的存储单元中,每个存储单元都有地址。使用变量、数组、函数既可以直接访问,又可以利用其存储单元地址进行间接访问,这种间接访问便是借助指针来完成的。 1.1对指针类型的理解 理解指针概念要从指针类型入手,教师在教学中应着重讲述 指针类型的含义,以及与普通变量类型的区别。指针定义时的类型称为指针的基础类型,理解上应区别于普通变量的类型。如定义: 由上表可以看出,普通变量的数据类型决定了其占用内存单 元的字节数以及存放数值的范围。而指针变量不论其基础类型为何种类型,均占用4 个字节的存储空间。并且指针变量与普通变量最大的区别在于,指针变量存地址值,而普通变量存数值。 1.2指针运算符的理解 1.2.1对取地址符“ &”的理解 指针变量定义后应为其赋一个有效地址值,让它指向有效的存储空间。未赋值的指针变量称为“悬空”指针,使用悬空指针非常危险,可能会导致系统崩溃。为指针变量赋值时常要用到取地址运算符“ &”。令

c语言指针例子

深入理解c语言指针的奥秘 指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。 先声明几个指针放着做例子: 例一: (1)int*ptr; (2)char*ptr; (3)int**ptr; (4)int(*ptr)[3]; (5)int*(*ptr)[4]; 如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<如何理解c和c ++的复杂类型声明>>。 指针的类型 从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型: (1)int*ptr;//指针的类型是int* (2)char*ptr;//指针的类型是char* (3)int**ptr;//指针的类型是int** (4)int(*ptr)[3];//指针的类型是int(*)[3] (5)int*(*ptr)[4];//指针的类型是int*(*)[4] 怎么样?找出指针的类型的方法是不是很简单? 指针所指向的类型

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。 从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如: (1)int*ptr;//指针所指向的类型是int (2)char*ptr;//指针所指向的的类型是char (3)int**ptr;//指针所指向的的类型是int* (4)int(*ptr)[3];//指针所指向的的类型是int()[3] (5)int*(*ptr)[4];//指针所指向的的类型是int*()[4] 在指针的算术运算中,指针所指向的类型有很大的作用。 指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的"类型"这个概念分成"指针的类型"和"指针所指向的类型"两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。 指针的值,或者叫指针所指向的内存区或地址 指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为si zeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。 指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。 以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里? 指针本身所占据的内存区 指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。 指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。

C语言结构指针

C语言结构指针 这篇文章是九九年写的,这篇文章适合中级程序员。有不明白之处不要紧,多看几遍,然后花些时间上机操作及认真思考每个问题。遇到难题要研究、解决,难题出现于哪里?该用什么方式来解决?为什么要选择这个方式解决?有其它的解决方法吗?这样的解决方案完美吗?其实做个程序员这些基本的思考心得是要掌握的。记住;遇问题不要逃避,要面对现实、勇于挑战,仔细研究难题的所在,这样相信你会成功的! 指针结构与指针的关系亦有两重:其一是在定义结构时,将指针作为结构中的一个成员;其二是指向结构的指针(称为结构指针)。前者同一般的结构成员一样可直接进行访问,后者是本节讨论的重点。 结构指针说明的一般形式是: struct 结构类型名称* 结构指针变量名; 例如:struct date * pdate, today; 说明了两个变量,一个是指向结构date的结构指针pdate,today是一个date结构变量。语句: pdate = &today; pdate today (struct date) year month day 通过结构变量today访问其成员的操作,也可以用等价的指针形式表示: today.year = 2001;等价于(*pdate).year = 2001;

由于运算符"*"的优先级比运算符"."的优先级低,所以必须有"( )"将*pdate括起来。若省去括号,则含义就变成了"*(pdate.year)"。 在C语言中,通过结构指针访问成员可以采用运算符"->"进行操作,对于指向结 构的指针,为了访问其成员可以采用下列语句形式: 结构指针->成员名; 这样,上面通过结构指针pdate访问成员year的操作就可以写成: pdate->year = 2001; 如果结构指针p指向一个结构数组,那么对指针p的操作就等价于对数组下标的操作。 结构指针是指向一种结构类型的指针变量,它是结构在内存中的首地址,结构指针具有一般指针的特性,如在一定条件下两个指针可以进行比较,也可以与整数进行加减。但在指针操作时应注意:进行地址运算时的放大因子由所指向的结构的实际大小决定。 例11-7:用结构指针改写加密程序。 #include "stdio.h" struct table { char input, output; } ; struct table translate[ ]= { 'a', 'd', 'b', 'w', 'c', 'k', 'd', ';' , 'e', 'i', 'i', 'a', 'k', 'b', ';', 'c', 'w', 'e' }; /* 建立加密对照表*/ main( ) { char ch; struct table *p, *pend; /* p和pend为指向结构table的指针*/ pend = & translate[ sizeof(translate)/sizeof(struct table)-1 ]; /* pend指向结构数组translate的最后一个元素*/ while ( (ch=getchar( )) != '\n')

C语言基础测试题

C语言基础测试题 一选择题(每题2分) 1. C语言程序的基本单位是( A )。 A. 函数 B. 过程 C. 语句 D. 子程序 2. 对于whil e语句,错误的说法是( C )。 A.用条件控制循环体的执行次数 B.循环体至少要执行一次 C.循环体有可能一次也不执行 D.循环体中可以包含若干条语句 3. 定义语句int a=3;则执行语句a+=a-=a*a后,变量a的值是(C)。 A.3 B.0 C.9 D.-12 4. 关于局部变量和全局变量的叙述中,错误的是(A)。 A.全局变量的重复赋值不会影响局部变量的使用。 B.主函数中定义的变量在整个程序中都是有效的 C.形式参数也是局部变量。 D.不论是局部变量还是全局变量,都以最近的一次赋值为准。 5. 已知:int a=13;那么:printf("%02d",a)结果是(A)。 A.13 B.013 C.01 D.03 6. 在main函数中调用scanf给变量a赋值的方法是错误的,原因是()。 int *p,a; p=&a; printf("input a:"); scanf("%d",*p); A. *p表示的是指针变量p的地址 B. *p表示的是变量a 的值,而不是变量a的地址 C. *p表示的是指针变量p的值 D. *p只能用来说明p是一个指针变量 7.若有以下定义,则对a数组元素地址的正确引用是()。 A.a+5 B.*a+1 C.&a+1 D.&a[0] 8. 若int k=4,a=3,b=2,c=1;则kb); A. 1,3 B. 1,4 C. 2,3 D. 2,4 二.填空题。(每空3分) 1.写一个宏MIN,这个宏输入两个参数并返回较小的一个_________。2.main函数中:for(int i=0; i<3; i++){printf("%d",i);}输出结果是_________。3.设int a=9,b=20;则printf("%d,%d",a--,--b);的输出结果是_________。

C语言指针详解

C语言指针详解 1 程序如何运行 当我们打开电脑中的任何一个程序运行时,我们的操作系统会将该程序存在硬盘的所有数据装载到内存中,然后有CPU 进行读取内存中的数据并进行计算,并将计算的结果返回给我们的操作系统,然后操作系统将相应的动作交付给相应的硬件来完成。如:将声音数据交给声卡,最后有音响输出来,将图像交给显卡最后有显示器输出…… 但是还会有一部分数据会返回给内存,以供程序下面的语句继续使用。 我们都知道内存的容量有很大,如:4G,8G, 16G,有时候我们会打开很多的程序,所有的程序的数据都存放到我们的内存中,那么CPU是如何正确的读取我们的不同程序的数据并加以计算的哪? 2 内存的假设设计 为了让我们的CPU 可以很好的读取内存中的数据,内存必须做优化设计,于是给内存设定了集合设计,将我们的内存分成很多大小相同的方格(盒子),所有的数据将放入这些小盒子中,将不同的程序的数据放入到不同的小盒子中,这样就出现的模块化的内存,当我执行程序的一个命令时,CPU就会从相应的盒子读数据然后计算,由于我们硬件所能访问或计算的最小单位是字节,所以内存中的这样的一个小盒子的大小就给他规定一个字节。 3 地址和指针 一般我们声明一块内存空间的时候,会给他取一个名字,为的是我们在编写程序的时候方便使用空间中存放的值,但是CPU 读数据的时候会忽视这个名字,因为CPU无法理解这样的数据,CPU 只能执行0,1代码,那么CPU是如何知道从什么地方读取数据,又到什么地方地址数据的读取的那,所以必须对内存做2次设计,就是将内存中分成的很多小盒子下面标注一些顺序的序号,例如:从第一个盒子开始,标注1,2,3,4,5,6,7,……每一个数字

C语言指针在教学中的基础应用-最新教育资料

C语言指针在教学中的基础应用 C Language Pointer in the Teaching of Basic Application CHEN Jing-yan1 , CHEN Yue-bin2 (1.Medical College of Shantou University, Shantou 515041, China; 2.Zengcheng College of South China Normal University, Guangzhou 511363, China) :It can be said that the pointer is the soul of the C language, familiar and flexible use of the pointer, you can effectively represent complex data structures; dynamic memory; the use of string; arrays are very effective. Beginners often an error, how to enable students to acquire and in-depth learning pointer is a difficult and often requires some time. The following combination of experience, discuss and summarize the pointer problem. C语言是一种计算机程序设计语言,是目前最广泛使用的计 算机语言之一,也是各高校专业与非专业主要的计算机教学语 指针是C语言中最为复杂的一个部分,使用起来非常灵活, 因而学习时常出错,必须小心,多思考,多比较,在实践中把其掌握好。 1指针概念 指针变量简称指针,其实它也是变量,只不过里面存放的内

C语言复习题指针结构体

C语言复习题_指针&结构体 一、选择 1、若有以下定义:char s[20]="programming",*ps=s; 则不能代表字符'o'的表达式是A。 A) ps+2 B) s[2] C) ps[2] D) ps+=2,*ps 2、若有以下定义和语句: int a[10]={1,2,3,4,5,6,7,8,9,10},*p=a;则不能表示a数组元素的表达式是B。 A) *p B) a[10] C) *a D) a[p-a] 3、已知int *p,a; p=&a; 这里的运算符& 的含义D。 A) 位与运算B) 逻辑与运算C) 取指针内容D) 取变量地址 4、定义结构体如下: struct student { int num; char name[4]; int age; }; 则printf(“%d”,sizeof(struct student))的结果为: 12。 5、若有定义如下:int i=3,*p=&i; 显示i的值的正确语句是B。 A) printf(“%d”,p); B) printf(“%d”,*p); C) printf(“%p”,*p); D) printf(“%p”,p); 6、在定义结构体时,下列叙述正确的是A。 A) 系统不会分配空间 B) 系统会按成员大小分配空间 C) 系统会按最大成员大小分配空间 D) 以上说法均不正确 7、指针是一种D。 A) 标识符B) 变量C) 运算符D) 内存地址 8、定义struct s {int x; char y[6];} s1;,请问正确的赋值是C。 A) s1.y=”abc”; B) s1->y=”abc”; C) strcpy(s1.y,”abc”); D) s1.strcpy(y,”abc”); 9、已知定义“int x =1, *p”,则合法的赋值表达式是A。 A) p =&x B) p = x C) *p =&x D) *p =*x

C语言基础及指针

C语言基础及指针 我们知道, Android系统是基于linux开发,采用的是linux内核,Android APP开发大部分也要和系统打交道,只是Android FrameWork 帮我们屏蔽了系统操作,我们从Android 系统的分成结构可以看出, Android FrameWork是通过JNI与底层的C/C++库交互,例如:FreeType ,OpenGL ,SQLite ,音视频等等。 做Android为什么需要学习C/C++ ? 1. 企业需要,现在大部分招聘,基本上都会要求会JNI 2. 进阶需要,如果想要研究Android源码,那么不会C/C++ ,行不通 3. 音视频时代到来 (直播) ,音视频处理,很大部分都需要C/C++完成(音视频编解码) 那么下面就一起开始学习C吧 ! let's go C语言中的变量 编写C的时候 , 首先我们需要引入头文件,就像我们写JAVA的时候,需要引入包一样,但C语言他不会帮你自动引入,所有头文件,必须你自己手动引入,最常用的两个头文件是 #include #include C语言中的xxx.h的头文件,里面只有函数声明,没有函数实现,函数实现都在xxx.c里面。 在学习一门语言的时候,我们最先了解的就是变量,变量的定义,变量所占大小,下面我们看看C语言中的变量类型,和变量大小。和JAVA 不同的是, C语言变量的大小,是随着操作系统变化而变化的,不同的操作系统,变量的大小可能不一样。 下面我们来查看C语言的变量类型和变量类型的大小: void main() { int i = 90; printf("int 所占字节:%d\n", sizeof(int)); printf(" i 的值:%d\n", i);

c语言结构体指针初始化===

c语言结构体指针初始化 今天来讨论一下C中的内存管理。 记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面 我说所有指针使用前都必须初始化,结构体中的成员指针也是一样 有人反驳说,不是吧,以前做二叉树算法时,他的左右孩子指针使用时难道有初始化吗 那时我不知怎么的想不出理由,虽然我还是坚信要初始化的 过了几天这位同事说他试了一下,结构体中的成员指针不经过初始化是可以用(左子树和右子树指针) 那时在忙着整理文档,没在意 今天抽空调了一下,结论是,还是需要初始化的。 而且,不写代码你是不知道原因的(也许是对着电脑久了IQ和记性严重下跌吧) 测试代码如下 1.#include 2.#include 3.#include 4. 5.struct student{ 6.char *name; 7.int score; 8.struct student* next; 9.}stu,*stu1; 10. 11.int main(){ 12. https://www.wendangku.net/doc/5514028878.html, = (char*)malloc(sizeof(char)); /*1.结构体成员指针需要初始化*/ 13. strcpy(https://www.wendangku.net/doc/5514028878.html,,"Jimy"); 14. stu.score = 99; 15. 16. stu1 = (struct student*)malloc(sizeof(struct student));/*2.结构体指针需要初始化*/ 17. stu1->name = (char*)malloc(sizeof(char));/*3.结构体指针的成员指针同样需要初始化*/ 18. stu.next = stu1; 19. strcpy(stu1->name,"Lucy"); 20. stu1->score = 98; 21. stu1->next = NULL; 22. printf("name %s, score %d \n ",https://www.wendangku.net/doc/5514028878.html,, stu.score); 23. printf("name %s, score %d \n ",stu1->name, stu1->score); 24. free(stu1); 25.return 0; 26.} #include #include #include struct student{ char *name; int score; struct student* next; }stu,*stu1; int main(){ https://www.wendangku.net/doc/5514028878.html, = (char*)malloc(sizeof(char)); /*1.结构体成员指针需要初始化*/ strcpy(https://www.wendangku.net/doc/5514028878.html,,"Jimy"); stu.score = 99; stu1 = (struct student*)malloc(sizeof(struct student));/*2.结构体指针需要初始化*/ stu1->name = (char*)malloc(sizeof(char));/*3.结构体指针的成员指针同样需要初始化*/ stu.next = stu1; strcpy(stu1->name,"Lucy"); stu1->score = 98; stu1->next = NULL; printf("name %s, score %d \n ",https://www.wendangku.net/doc/5514028878.html,, stu.score);

C语言指针习题及答案

指针习题及答案 一.选择题 1.变量的指针,其含义是指该变量的 B 。 A)值B)地址C)名D)一个标志 2.已有定义int k=2;int *ptr1,*ptr2;且ptr1和ptr2均已指向变量k,下面不能正确执行的赋值语句是 B 。 A)k=*ptr1+*ptr2 B)ptr2=k C)ptr1=ptr2 D)k=*ptr1*(*ptr2) 3.若有说明:int *p,m=5,n;以下程序段正确的是 D 。 A)p=&n ; B)p = &n ; scanf(“%d”,&p); scanf(“%d”,*p); C)scanf(“%d”,&n); D)p = &n ; *p=n ; *p = m ; 4.已有变量定义和函数调用语句:int a=25;print_value(&a);下面函数的输出结果是 D 。 void print_value(int *x) { printf(“%d\n”,++*x); } A)23 B)24 C)25 D)26 5.若有说明:int *p1, *p2,m=5,n;以下均是正确赋值语句的选项是 C 。 A)p1=&m; p2=&p1 ; B)p1=&m; p2=&n; *p1=*p2 ; C)p1=&m; p2=p1 ; D)p1=&m; *p1=*p2 ; 6.若有语句:int *p,a=4;和p=&a;下面均代表地址的一组选项是 D 。 A)a,p,*&a B)&*a,&a,*p C)*&p,*p,&a D)&a,&*p,p 7.下面判断正确的是 C 。 A)char *a=”china”; 等价于char *a; *a=”china” ; B)char str[10]={“china”}; 等价于char str[10]; str[ ]={“china”;} C)char *s=”china”; 等价于char *s; s=”china” ; D)char c[4]=”abc”,d[4]=”abc”; 等价于char c[4]=d[4]=”abc” ; 8.下面程序段中,for循环的执行次数是 C 。 char *s=”\ta\018bc” ; for ( ; *s!=?\0? ; s++) printf(“*”) ; A)9 B)7 C)6 D)5 9.下面能正确进行字符串赋值操作的是 C 。 A)char s[5]={“ABCDE”}; B)char s[5]={…A?,?B?,?C?,?D?,?E?}; C)char *s ; s=”ABCDE” ; D)char *s; scanf(“%s”,s) ; 10.下面程序段的运行结果是 C 。 char *s=”abcde” ; s+=2 ; printf(“%d”,s); A)cde B)字符?c?C)字符?c?的地址D)不确定 11.设p1和p2是指向同一个字符串的指针变量,c为字符变量,则以下不能正确执行的赋值语句是 B 。 A)c=*p1+*p2 B)p2=c C)p1=p2 D)c=*p1*(*p2) 12.设有程序段:char s[ ]=”china”; char *p ; p=s ;则下面叙述正确的是 D 。A)s和p完全相同 B)数组s中的内容和指针变量p中的内容相等

C语言数据结构与指针(4)

你想是怎样的人,你就是怎样的人;你想成为怎样的人,你就会离这个目标不会太远。 数据结构【第四次】实验报告 学院: 班级: 学号: 姓名: 实验四 (一)实验名称:C语言数据结构与指针 (二)实验目的:巩固复习前期所学C语言的函数参数传递、指针和结构体等知识点加强学习数据结构语言基础 (三)实验内容: 1) 学生信息的显示 具体要求如下: ???定义一个结构体描述学生信息(学号 姓名 性别 年龄 住址); ???设计一个函数 用于显示单个学生信息 函数的参数为前面定义的结构体类型; ???设计一个主函数 在主函数中输入学生的信息 并调用前面定义的函数进行显示(学生人数不少于5人)

2) 输入若干个整数作为数组元素值然后按输入时顺序的就地逆置排序最后打印出逆置后的元素值 要求用指针和动态内存分配方法实现例如输入:10 2 30 4 5 逆置后显示为:5 4 30 2 10 (四)源代码: #define MAXSIZE 100 #include #include typedef int ElemType; typedef struct { ElemType data[MAXSIZE]; int length; } SqList; SqList l; void InitList(SqList &L) { L.length = 0; } void CreatSqlist(SqList &L int n) { printf("请输入节点"); int i; for(i=0;i

C语言入门_nisy

C语言入门 Nisy 著

有不少人问,学C语言需要什么基础?我想说,你有兴趣吗?你有时间吗?如果两个都准备好了,就可以开始了。数学不太好能学好C语言吗?关系不大,就跟婴儿学说话前是否需要具备数学知识一个道理。 本书是写给C语言初学者的。文中对C语言的语法部分没有过多阐述,因为其他C语言书上已经对C标准讲的很详细了。而是侧重对C语言中一些司空见惯的内容重新进行了剖析,如对C语言的思考、程序是什么的思考、教学顺序的思考、对变量是什么的思考、对模块化程序设计的思考、对递归函数的思考、对指针的思考等。虽没有太多的语法内容,但本书还是拥有一个完整的C语言框架的,对C基础知识有一些了解的朋友可能读起来会更轻松一些。 写这个东西的目的很单纯,就是把自己对C的理解以及C教学方法的一些心得和大家做一个交流。C语言的书籍很多,大都将“Hello,World!”作为见面礼,本书中的第一节内容是先让学习者建立一个内存环境模型,因为我觉得一个C程序员脑海中若没有对内存环境建模是一件很荒唐的事情,C的精髓在于指针,连空间模型都模糊,谈指针又何必。由于时间等原因,书中对一些知识点没有详细讲述,如switch…case…和一维数组的应用等,几句话很难讲透彻,但又不影响初学者对C语言的理解,故本书没有详细阐述。 在本书的阅读上,建议大家还是顺序来读,从第一章开始读,就如同看一幅画,只看局部是没有什么意思的。写这个东西就是一个纯交流,若大家在阅读时发现文中的错误,还望不吝赐教。关于致谢部分,能完成这个文档,我需要感谢的人很多,由于担心文章质量可能会影响到他们的声誉,故这里不再一一写明,只在心中默默感谢。

相关文档