指针
来源:互联网 发布:php 序列化 编辑:程序博客网 时间:2024/06/09 16:39
1.指针类型:
整型指针和整型是不同的类型,不可以直接相互赋值,但是可以相互强制转换,需要注意转换的意义。如:
int icount = 18;
int *iptr = &icount; //定义指针
*iptr = &icount; //error:左边为整型,右边为整型地址,不可以转换
*iptr = 58;
*iptr = (int) &icount; //right:可以强制转换
32位机器上,整型和指针都是占用4个字节,内存表示都是二进制整型,但是就如上面说的,它们的类型不一样。
2.指针初始化:
指针在声明的时候最好先初始化,否则是很危险的。
如:
int icount=18;
int *iptr; //指针没有初始化,这里把18随意地赋值给内存 随机位置,可能会改写另一存储位置的数值,危险!!!
*iptr=icount;
3.指针运算:
指针可以进行加减的运算,指针的加减与指针的类型有关。
如:都是在32位机器上,整型占4位,char占1位,double占16位。
int icount1=0;
int *iptr1=&icount1;
iptr1++;
iptr1++表示地址加了4
0x00000000--->0x00000004
char icount2=1;
char *iptr2=&icount2;
*iptr2++;
iptr2++表示地址加了1
0x00000000--->0x00000001
0x00000000--->0x00000001
double icount3=2;
double *iptr3 =&icount3;
*iptr3++;
iptr1++表示地址加了16
0x00000000--->0x00000010
0x00000000--->0x00000010
4.指针和数组:
数组名是一个地址,可以用来初始化指针。
int a[10];
int *iptr=a;
第i个元素表示:a[i], *(a+i), iptr[i], *(iptr+i)
第i个元素地址:&a[i], a+i, &iptr[i], iptr+i
同时数组名是指针常量,区别于指针变量,所以不可以进行运算。
如:
a++; //error:数组名是指针常量,不做左值。
但如果数组作为参数传递过去,可以当指针用,这时候就可以作为左值。
例如:
#include <iostream>
using namespace std;
void main(){
int array[10]={1,2,3,4,5,6,7,8,9,10};
sum(array,10);
}
void sum(int array[],int n){ //数组array作为参数传递过去,可以作为指针,等价于void sum(int * array,int n) 或者void sum(int* array[],int n)
int sum=0; //为什么要给出数组的大小n呢??因为传递过来的是一个指针array,而不是数组array
那么占用的空间只是指针的大小,而不是数组的空间那么大,不能用sizeof(array)/sizeof(int)来求得数组元素个数n,
所以传递参数的时候,传过来的是指针和数组的大小(即元素个数n),仅仅传过来数组的指针是不可以的。
for(int i=0;i<n;i++){
sum+=*array;
array++; //由于array为指针,可以作为左值,那么可以进行运算
}
cout << sum<< endl;
}
using namespace std;
void main(){
int array[10]={1,2,3,4,5,6,7,8,9,10};
sum(array,10);
}
void sum(int array[],int n){ //数组array作为参数传递过去,可以作为指针,等价于void sum(int * array,int n) 或者void sum(int* array[],int n)
int sum=0; //为什么要给出数组的大小n呢??因为传递过来的是一个指针array,而不是数组array
那么占用的空间只是指针的大小,而不是数组的空间那么大,不能用sizeof(array)/sizeof(int)来求得数组元素个数n,
所以传递参数的时候,传过来的是指针和数组的大小(即元素个数n),仅仅传过来数组的指针是不可以的。
for(int i=0;i<n;i++){
sum+=*array;
array++; //由于array为指针,可以作为左值,那么可以进行运算
}
cout << sum<< endl;
}
5.指针常量和常量指针:
常量指针:指向常量的指针
const int icount1=0;
const int *iptr1=&icount1; //在前面加上const是说指向的对象是常量,那么它是常量指针
icount1=1; //error: 常量icount不可赋值
*iptr1=2; //error: 常量指针iptr1是指向常量的,同样不可以赋值
指针常量:指针是常量
int icount2=0;
int* const iptr2=&icount2;
icount2=1; //right: icount2不是常量,可以赋值
*iptr2=2; //right: 这里指针常量iptr2指向的不是常量,可以赋值
iptr2=0x00000000; //error: 指针常量iptr2是常量,其本身不可以被赋值。
6.字符指针:
字符串可分为两种,一种是相当于常量的字符串,另一种是字符数组。
char *iptr="hello";
// 相当于常量的字符串,不可以再赋值,如再有iptr="hi"; error
存放在const区域char buffer[10]="Hello";
// 字符数组 拥有一定的地址空间
若为全局变量,则放在data区的全局区若为局部变量,则放在stack区
由于每一个字符串都有自己的地址,那么相同的两个字符串是不可以“==”的。
同样,也不可以用字符串直接给另一个字符串赋值,而是应该用strcpy()函数,其原型为
char* strcpy(char* dest,const char* src)。
例如:
char * str1="hello";
char * str2="hello";
if(str1==str2)
cout << "equal." << endl;
else
cout << "not equal." << endl;
print: not equal.
再者:
str1=str2; // error,因为不可以直接赋值
strcpy(str1,str2); //right
总结:
字符串比较----strcmp()
原型: int strcmp(char* dest, const char* src ),相等返回0,(前者大于后者)大于返回正值,小于返回负值。
字符串赋值----strcpy()
原型:char* strcpy(char* dest, const char* src)
附加:还有可以使用函数memcpy()
原型:char* memcpy(char* dest, const char* src,size_t n),可以确切地赋值多少个字符
7.字符指针的输出:
字符指针存的是字符串的首地址。
输出字符指针-----即是输出整个字符串
输出字符指针的引用-----即是输出某一个字符
例如:
char *pc="hello" ;
cout<< pc<< endl; // 输出hello
cout<<*pc<<endl; //输出h
char buffer[] ="ABC";
pc=buffer;
cout << pc<<endl; //输出ABC
pc++;
cout<<*pc<<endl; //输出B
指针数组,二维数组,二级指针
char * pc[]={"hello","hi"};
char ** ppc=pc; // ppc为二级指针
8.指针函数与函数指针:
指针函数:返回指针的函数。
函数指针:指向函数地址的指针。
注意1:指针函数返回的指针不能为函数内部的局部变量,否则很容易出错。
例如:
int* fn(){
int icount=10;
return &icount;
}解释:最好不要这样用,因为icount是函数内部局部变量,返回它的地址到调用它的函数不可取,可能会被下次的调用所覆盖。int *geyInt(char* str){
int value=20
cout<< str<< endl;
return &value;
}
int somefn(char* str){
int a=40;
cout<< str<<endl;
}
int main(){
int *iptr=getInt("input a value."); //这里要注意,还因为getInt()结束的时候,栈中的变量value也会消失
因为它是函数内部的局部变量,第一次输出*pr的时候,指向20的地址所以输出20,
但是第二次输出*pr的时候,由于栈的该地址的内容已经被覆盖,那么输出的是一个
意料之外的i结果。
cout<<*pr<<endl;
somefn("after somefn:");
cout<<*pr<<endl;
}
print:
input a value.
20
after somefn:
4435500
int icount=10;
return &icount;
}解释:最好不要这样用,因为icount是函数内部局部变量,返回它的地址到调用它的函数不可取,可能会被下次的调用所覆盖。int *geyInt(char* str){
int value=20
cout<< str<< endl;
return &value;
}
int somefn(char* str){
int a=40;
cout<< str<<endl;
}
int main(){
int *iptr=getInt("input a value."); //这里要注意,还因为getInt()结束的时候,栈中的变量value也会消失
因为它是函数内部的局部变量,第一次输出*pr的时候,指向20的地址所以输出20,
但是第二次输出*pr的时候,由于栈的该地址的内容已经被覆盖,那么输出的是一个
意料之外的i结果。
cout<<*pr<<endl;
somefn("after somefn:");
cout<<*pr<<endl;
}
print:
input a value.
20
after somefn:
4435500
注意2:函数指针赋值的时候要注意类型的匹配。
例如:
函数:
int fn1(char* a,char* b);
int* fn2(char* a,char* b);
int fn3(int a);
函数指针:
int (*fp1) (char* a,char*b);
int (*fp2)(int a);
判断:
fp1=fn1; // right,参数一致,返回类型都是int整型
fp2=fn2; // error 参数不一致,不可为函数指针赋值。
fp1=fn2; // error 参数一致,但是返回类型不一致,fn2返回类型为int*整型指针,fp1的返回类型是int整型
fp2=fn3; // right 参数一致,返回类型都是int整型
9.函数指针可以作为参数传递。
例如:排序一个字符串数组,比较函数用的是compare();
#include <iostream>
#include <string>
#include <stdlib>
using namespace std;
int compare(const void* a, void* b);
char list[5][4]={"cat","car","cab","cap","can"};
void main(){
qsort((void*) list,5,sizeof(list[0]),compare);
for(int i=0;i<5,i++){
cout<<list[i]<<endl;
}
}
int compare(const void*a, const void* b){
return strcmp((char* *)a,(char* *) b);
}
print:
cab
can
cap
car
cat
qsort()的原型是:void qsort(void*, size_t nelem,size_t width,
int(*fcmp)(const void *, const void*))
这里qsort的第四个参数是函数指针,也就是说传递过去的是一个指向函数地址的指针。
在左边的例子中,实际参数为compare指针。
#include <string>
#include <stdlib>
using namespace std;
int compare(const void* a, void* b);
char list[5][4]={"cat","car","cab","cap","can"};
void main(){
qsort((void*) list,5,sizeof(list[0]),compare);
for(int i=0;i<5,i++){
cout<<list[i]<<endl;
}
}
int compare(const void*a, const void* b){
return strcmp((char* *)a,(char* *) b);
}
print:
cab
can
cap
car
cat
qsort()的原型是:void qsort(void*, size_t nelem,size_t width,
int(*fcmp)(const void *, const void*))
这里qsort的第四个参数是函数指针,也就是说传递过去的是一个指向函数地址的指针。
在左边的例子中,实际参数为compare指针。
10.函数指针可以构成指针数组。
typedef void (*menuFun);
void fn1(){cout<<"11111"<<endl;};
void fn2(){cout<<"22222"<<endl;};
void fn3(){cout<<"33333"<<endl;};
menuFun fn[]={fn1,fn2,fn3};
void main(){
int choice;
do{
cout<<"1 stand for 11111"<<endl;
cout<<"2 stand for 22222"<<endl;
cout<<"3 stand for 33333"<<endl;
cin>>choice;
switch(choice){
case 1:
fn[0]();
break;
case 1:
fn[1]();
break;
case 1:
fn[3]();
break;
default:
cout<< "you enter a wrong key." <<endl;
}while(choice)
}
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- 指针
- Qt入门-基于QMainWindow的窗体
- http://acm.hdu.edu.cn/showproblem.php?pid=1106&&排序
- 如何实现类的成员函数作为回调函数
- VS2003下载地址
- Ubuntu 修改myeclipse背景色
- 指针
- webview可以获取网页源码,进行重新排版吗
- RegistryBooster 2012 and SpeedUpMyPC 2012
- 申请和释放堆内存
- ubuntu11.10 下编译 opencv2.4 所遇到的问题总结
- 提高jQuery性能
- 综合实例:PIC单片机(PIC16F877A)万年历(温度闹钟年月日时分秒星期)
- MyEclipse下创建Maven Web Project
- php设计模式学习