C语言ggg是什么函数指针,指针

指针的概念

指针就是把地址作为数据处理,用于

提供间接访问

允许函数之间共享内存空间

实现动态变量

指针变量:存储地址的变量。

变量的指针:当变量A存储变量B的地址时,那么A就是B的指针。

定义指针变量要告诉编译器该变量中存放的是一个地址,同时也需要知道指针指向的单元的数据类型。故指针的定义为:

类型标识符 *指针变量;

如何让指针指向某一变量?

用地址运算符 & 解决。如表达式 &x 返回的是变量 x 的地址,则有intp = &x;

& 运算符后面不能跟常量或表达式。如 &2 是没有意义的,&(m * n + p )也是没有意义的。

如何通过指针变量处理和改变它所指向的单元的值?

用引用运算符 * 解决。如 *intp 表示的是 intp 指向的这个单元的内容。如:*intp = 5 等价于 x = 5

在对 intp 使用引用运算之前,必须先对 intp 赋值。

指针在使用前必须初始化,没有初始化的指针可能指向任意地址,对这些指针作操作可能会导致程序错误。

NULL是一个特殊指针值,称为空指针。它的值为0。它可被用来初始化一个指针,表示不指向任何地址。

指针运算和数组

数组名可以看成是常量指针,对一维数组来说,数组名是数组的起始地址,也就是第0个元素的地址,如执行了p=array,则p与array是等价的,对该指针可以进行任何有关数组下标的操作。

指针保存的是一个地址,地址是一个整型数,因此可以进行各种算术运算,但仅有加减运算是有意义的。

int a[10], *p;

p=a;

// solution1

for (int i=0; i<10; i++)

cout << p[i];

// solution2

for (int i=0; i<10; ++i)

cout << *(p+i);

// solution3

for (;p

cout << *p ;

// 下面这种不行,因为a是常量,不能++

for (int i=0; i<10; ++i)

{

cout << *a ;

++a;

}

动态内存分配

动态内存分配与回收

type *p;

运算符new用于进行内存分配:

申请动态变量:p = new type;

申请动态数组:p = new type[size];

申请动态变量并初始化:p = new type(初值);

运算符delete释放分配的内存:

释放动态变量:delete p;

释放动态数组:delete [] p;

动态分配的检查

new操作的结果是申请到的空间的地址;当系统空间用完时,new操作可能失败;new操作失败时,返回空指针。

//动态分配检查

int main()

{ int *p;

p = new int;

if(!p) {

cout << "allocation failure\n";

return 1;

}

// 或者使用assert宏

// assert宏在标准头文件cassert中;

//assert()有一个参数,表示断言为真的表达式,预处理器产生测试该断言的代码。如果断言不是真,则在发出一个错误消息后程序会终止。

// assert (p != 0);

*p = 20; cout << *p;

delete p; return 0;

}

内存分配的进一步介绍

静态变量:对全局变量和静态变量,编译器为它们分配空间,这些空间在整个程序运行期间都存在

自动变量:函数内的局部变量空间是分配在系统的栈工作区。当函数被调用时,空间被分配;当函数执行结束后,空间被释放

动态变量:在程序执行过程中需要新的存储空间时,可用动态分配的方法向系统申请新的空间,当不再使用时用显式的方法还给系统。这部分空间是从被称为堆的内存区域分配。

字符串与指针

char *String;

String = “abcde”;

字符串常量存储在内存中数据段的区域里;将存储字符串”abcde”的内存的首地址赋给指针变量String;不能将String作为strcpy或strcat的第一个参数。

可以通过下标读取字符串中的字符,但不可以通过下标变量赋值。

可以直接作为字符串操作函数的参数。但必须注意,如果该指针指向的是一个字符串常量时,则使用是受限的。如不能作为strcpy的第一个参数。

char *String, ss[ ] =“abcdef”;

String = ss;

将字符数组ss的起始地址存入String

char *String;

String = new char[10];

strcpy(String, “abc”);

动态变量存储在堆工作区 ;将存储字符串”aaa”的内存的首地址赋给指针变量String。

指针与函数

指针作为函数参数

用指针作为参数可以在函数中修改主调程序的变量值,即实现变量传递。

例如交换值函数

void swap(int *a, int *b){

int c;

c=*a; *a= *b; *b=c;

}

// 调用函数

swap(&x, &y);

利用指针参数作为输出

#include

#include

using namespace std;

int func(double a, double b, double c, double *x1, double *x2){

double delt = b*b-4*a*c;

if (delt>0){

double sdelt = sqrt(delt);

*x1 = (-b+sdelt)/(2*a);

*x2 = (-b-sdelt)/(2*a);

return 2;

}

else if(delt==0){

*x1 = -b/(2*a);

*x2=*x1;

return 1;

}

else{

return 0;

}

}

int main()

{

double px1,px2;

int result = func(2, 4, 2, &px1, &px2);

switch (result){

case 0:

cout<

break;

case 1:

cout<

break;

case 2:

cout<

break;

}

return 0;

}

数组名作为函数参数

数组传递的本质是地址传递,因此形参和实参可以使用数组名,也可以使用指针。

如果传递的是数组

type func(type arr[], int size);

如果传递的是普通的指针

type func(type *p, int size);

C++将数组名作为参数传递处理成指针的传递。

//利用分治法获得数组最大值和最小值

#include

#include

using namespace std;

void func(int a[], int n,int *max_value, int *min_value){

switch (n){

case 1:

*min_value = *max_value = a[0];

return;

case 2:

if (a[0]>a[1]){

*max_value = a[0];

*min_value = a[1];

return;

}

else{

*max_value = a[1];

*min_value = a[0];

return;

}

default:

int max1,min1,max2,min2;

func(a, n/2, &max1, &min1);

func(a+n/2, n-n/2, &max2, &min2);

if (max1>max2){

*max_value = max1;

}

else{

*max_value = max2;

}

if (min1

*min_value = min1;

}

else{

*min_value = min2;

}

return;

}

}

int main()

{

int a[]={1,9,8,2,3,7,6,4,5,0};

int in,ax;

func(a, 10, &in, &ax);

cout<

return 0;

}

返回指针的函数

当函数的返回值是指针时,返回地址对应的变量不能是局部变量。

//获取子字符串

#include

#include

#include

using namespace std;

char *subString(char *s, int start, int end)

{

int len = strlen(s);

if (start < 0 || start >= len || end < 0 || end >= len || start > end) {

cout << "起始或终止位置错" << endl;

return NULL;

}

char *sub = new char[end - start + 2];

strncpy(sub, s + start, end - start +1);

sub[end - start +1] = '\0';

return sub;

}

int main()

{

char *s="hello, world!";

char *ss;

ss=subString(s, 1,3);

cout<

return 0;

}

引用与函数

引用的定义:给一个变量取一个别名,使一个内存单元可以通过不同的变量名来访问。

//j是i的别名,i与j是同一个内存单元。

int i;

int &j=i;

引用使用的注意事项:

定义引用时必须立即对它初始化,不能定义完成后再赋值。

为引用提供的初始值可以是一个变量或另一个引用。

引用不可重新赋值,不可使其作为另一变量的别名。

C++引入引用的主要目的就是将引用作为函数的参数。

指针参数

void swap(int *m, int *n)

{ int temp;

temp=*m;

*m=*n; *n=temp;

}

调用:swap(&x, &y)

引用参数

void swap(int &m, int &n)

{ int temp;

temp=m;

m=n; n=temp;

}

调用:swap(x, y)

注意:实参必须是变量,而不能是一个表达式。

C++中,函数参数一般都采用引用传递,好处是减少函数调用时的开销。如果在函数内不许改变参数的值,则参数用const限定,对非const的参数,实际参数不能是常量或临时量。

返回引用的函数是将函数用于赋值运算符的左边,即作为左值。

#include

#include

#include

using namespace std;

int &index(int a[], int n){

return a[n];

}

int main()

{

int a[]={1,2,3};

index(a,1)=5;

cout<

return 0;

}

指针数组与多级指针

指针数组

一个数组,如果他的元素均为指针,则称为指针数组。

一维指针数组的定义形式:

类型名 *数组名[数组长度];

字符串可以用一个指向字符的指针表示,一组字符串可以用一个指向字符的指针数组来表示。

用二分法查找某一个城市在城市表中是否出现

int binarySearch(char *cityTable[], int lh, int rh, char *cityName){

int mid, result;

if (lh <= rh){

mid =(lh+rh)/2;

result= strcmp(cityTable[mid], cityName);

if (result == 0){

return mid;

}

else if (result > 0){

return binarySearch(cityTable, lh, mid-1, cityName);

}

else{

return binarySearch(cityTable, mid+1, rh,cityName);

}

}

return -1; //没有找到

}

int main()

{

char *string[10] = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii","jjj"};

char tmp[10];

while (cin >> tmp){

cout << binarySearch(string, 0, 9, tmp) << endl;

}

return 0;

}

main函数参数

main函数有二个形式参数:int argc, char *argv[]

argc:参数的数目(包括命令名本身)

argv[]:指向每个参数的指针,是一个指向字符串的指针数组

int main(int argc, char *argv[]){

...

}

多级指针

指针指向的内容还是一个指针,称为多级指针。

如有定义:char *string[10];,string是一个数组,数组元素可以通过指针来访问。如果p是指向数组string的某一个元素,那么p指向的内容是一个指向字符的指针,因此p就是一个多级指针。string也是一个多级指针,不过是一个常指针。

// 按顺序输出指针数组元素

int main()

{

char *city[] = {"aaa", "bbb", "ccc", "ddd", "eee"};

char **p;

for (p=city; p

cout << *p << endl;

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值