首页 > 代码库 > 数组和指针

数组和指针

一,指针
<1>指针的类型,指针所指向的类型和指针指向的内存区(指针的值)  32位
 
指针的类型
指针所指向的类型
sizeof(*ptr)说明
int *ptr; 
int *
int 
4
 
int **ptr;
int **
int * 
4
 
int (*ptr)[3];
int(*)[3] 
 int()[3] 
12
指向有3个int型元素的数组
int (*ptr)(int);
int (*)(int)
 int ()(int)
 
指向函数的指针,该函数有一个整型参数并返回一个整型数
指针数组:
int *a[3];    //一个有3个指针的数组,该指针是指向一个整型数的。sizeof(a)=12,sizeof(*a)=4
int (*a[10])(int);  //一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
 
a,指针的类型:是指指针本身所具有的类型。把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。
b,指针所指向的类型:当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。
    把指针声明语句中的指针名字和名字左边的指针声明符 *去掉,剩下的就是指针所指向的类型。

c,指针的值是指针本身存储的数值,这个值将被编译器当作一个地址。在32位程序里,所有类型的指针的值都是一个32位整数。

    指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。
    指针本身所占据的内存是sizeof(指针的类型)或sizeof(ptr),对于一个32位的系统,其值是4。
 
指针所指向的类型和指针所指向的内存是不同的,一个指针被定义时,指针所指向的类型已经确定,但由于指针未初始化,它所指向的内存区是不存在的
 

<2>指针的强制类型转换

a,新指针的类型是TYPE*:  ptr1=(TYPE*)ptr2

如果sizeof(ptr2的类型)大sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。

b,调用地址为0x30008000的函数
void (*p)(int *, char *);//定义函数指针
p=(void (*)(int *,char *))0x30008000;
将100赋给地址为0x804a008
*((int *)0x804a008) = 100;
c,
char *p
p= (char *)malloc(sizeof(char));
malloc()返回void型的指针
 
<3>函数指针
void (*pf)(char *);  pf是指向void,参数是char* 的类型的函数的指针。
void *pf(char *);   pf是返回一个指针的函数
 
char name[20]="hello";void fun(char *);fp=fun;
调用方法:
(*fp)(name);
fp(name);
ANSI C支持这两种;unix支持第二种;K&R C支持第一种。
 
二,数组
1.一维数组:
<1>指定初始化项目(C99):int date[4] = {[0]=1,[5]=5};  其他项为0。
<2>数组名是该数组首元素的地址:date==&date[0],是一个指向int型的常量指针
<3>对指针加1,等价于对指针的值加上它指向的对象的字节大小:date+2==&date[2]   *(date+2)==date[2]
<4>保护数组的内容:int sum(const int ar[],int n);
<5>数组做函数形参: int sum(int *ar,int n);int sum(int ar[],int n);

 

2.指针和多维数组

<1>二维数组初始化:date={{1,2,3},{4,5,6}} 也可以省去{}。

<2>int zippo[4][2];

 int (*pz)[2]; 

//pz指向包含两个int值的数组,即是指向一二维数组,该二维数组有2列。使用该类型指针时注意不要超过二维数组的行数的范围

pz=zippo;  

zippo==&zippo[0]; zippo[0]==&zippo[0][0]; zippo==&(&zippo[0][0]);

*(zippo+2)==zippo[2]==&zippo[2][0]第三个元素,即包含2个int值的数组

*(*(zippo+2)+1)==zippo[2][1]

指针兼容

int **p1;int *p2[2];

p1=pz;(非法)//pz是指向int[2]型的指针。p1是指向int *的指针

p1=p2;(合法)

函数和多维数组

void fun(int (*pz)[2]);

void fun(int pz[][2]);

 

3.指针变量作为函数参数
<1>实参变量和形参变量之间数据传递是单向的。不可能通过函数调用来改变实参指针变量的值,但可以改变实参指针变量所指变量的值
void swap(int *p1,int *p2){int temp;temp=*p1;*p1=*p2;*p2=temp;}    //a,b(*pp1,*pp2)的值可以互换
void main(){int a=1, b=2;  int *pp1=&a,*pp2=&b;  swap(pp1,pp2)}      
 
void swap(int *p1,int *p2){int * temp;temp=p1;p1=p2;p2=temp;} 
//只是改p1,p2的地址,pp1,pp2不能改变,*p1,*p2(*pp1,*pp2)的值没有改变。因此不能交换a,b
<2>如果想要改变的是指针变量p的值,就要传递p的地址。
void getmemory(char *p, int num)
{
    p = (char *)malloc(sizeof(char)*num);
}
void test()
{
    char *str = NULL;
    getmemory(str, 100);   //此时str仍为NULL
    strcpy(str, "hello");       //出现段错误
}
正确写法:
a种方法
void getmemory(char **p, int num)                        
{
    *p = (char *)malloc(sizeof(char)*num);
}
void test()
{
    char *str = NULL;
    getmemory(str, 100);   
    strcpy(str, "hello");
    free(str);      
}
b种方法
char* getmemory( int num)                        
{
    return (char *)malloc(sizeof(char)*num);   //返回的指针指向堆区
}
void test()
{
    char *str = NULL;
    str = getmemory(100);   
    strcpy(str, "hello");
    free(str);      
}
 

注意

<1>int days[]={....},sizeof days是整个数组的大小;sizeof day[0]是一个元素的大小(以字节为单位)

<2>C并不检查你是否使用了正确的下标,例如:int a[10];a[10]=12;编译器不会发现这样的错误。当程序运行时,这些语句把数据放在可能由其他数据使用的位置,因而可能破坏程序的结果甚至使程序崩溃。

<3>在返回指针变量时,注意不要用return返回指向栈内存中的指针。否则,函数返回后该指针指向的内存被释放。

<4>当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。因此在使用指针之前,必须给它赋予一个分配的内存。(可用malloc或把一已存在的变量地址赋给指针)。

数组和指针