C学习笔记
——指针与数组
指针是一种
保存变量地址的
变量。本身也是一个变量。
指针即地址。
一、指针与地址
指针是能够
存放一个地址的
一组的存储单元。
其占内存大小取决于具体操作系统。
指向各种类型变量的指针长度均相同。( sizeof( int* ) = sizeof( char* ) = sizeof( float* ) =....)
对于
32位系统来说,指针长度为
4
Bytes
对于
64位系统来说,指针长度为
8
Bytes
取址运算符 &
:取一个对象的地址。只能应用于内存中的对象,即
变量及数组元素。不能用于表达式、常量或寄存器变量。
间接寻址(间接引用)符 ×
类型名
*变量名;
为指向
类型名的,名为
变量名的指针变量。
每个指针必须指向特定的数据类型(空类型例外)。
空类型指针
void*
可以存放任何类型的指针,但不能间接引用其自身。
int<span style="white-space:pre"> </span>ivar= 1;
int*<span style="white-space:pre"> </span>ivar_p=&ivar;
void*<span style="white-space:pre"> </span>vvar_p= ivar_p;
printf("%d\n",*vvar_p);非法
二、指针与函参
传值调用:
例:数值交换函数
void swap(int x, int y)<span style="white-space:pre"> </span>void swap(int* px, int* py)
{<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>int temp;<span style="white-space:pre"> </span>int*<span style="white-space:pre"> </span>temp;
<span style="white-space:pre"> </span>temp = x;<span style="white-space:pre"> </span>temp<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>px;
<span style="white-space:pre"> </span>x = y;<span style="white-space:pre"> </span>px<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>py;
<span style="white-space:pre"> </span>y = temp;<span style="white-space:pre"> </span>py<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>temp;
}<span style="white-space:pre"> </span>}
上述两种均无法实现数值交换,交换的仅仅是函数内的副本数据。而下述函数可以实现。
void swap(int* px, int* py)
{
<span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>temp;
<span style="white-space:pre"> </span>temp<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>*px;
<span style="white-space:pre"> </span>*px<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>*py;
<span style="white-space:pre"> </span>*py<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>temp;
}
三、指针与数组
数组名不能与变量名重复。
当把数组名传递给一个函数时,实际上传递的是该数组第一个元素地址。
传递数组可以写成:
int<span style="white-space:pre"> </span>a[10];
int*<span style="white-space:pre"> </span>p;
p<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>&a[0]; //p=a
函数中的数组形参:
f( int a[ ] )
或
f( int* s )
四、指针初始化
对指针有意义的初始化只能是
0(即NULL) 或者是
表示地址的表达式(初始化之前已定义过的具有适当类型的数据的地址)。
五、指针运算
以下情况可以进行指针的运算
- 相同指针类型之间的赋值。
- 指向同数组中元素的指针之间减法和比较。
- 指针可与整数进行加减。(注意,运算按p指向的对象长度进行;例int* p = &a(0000 0000H),int型变量在内存中占用4Bytes,则 p + 1 为0000 0000H + 1 * 4)
- 与0的赋值及比较。(当然加减也可以,但是没有意思)
六、字符指针与函数
一个字符串出现在程序中时,实际上是通过指针访问该字符串的。
char
string[ ]
=
"Hello World!";
定义一个数组
char*
pstring
=
"Hello world!";
定义一个指针;该过程并不是将整个数组复制,而只是首地址的赋值。C语言没有提供将整个字符串作为一个整体进行处理的运算符。
七、指向数组的指针及指向指针的指针
- char* pstr;定义一个指针
- char* pstr[n];定义一个指针数组,数组中每个元素是一个指针。优点在于,每个指针指向的字符串长度可以不同。
- char (*pstr)[n];定义一个数组指针。指向具有n个元素的一维数组。
int (* pstr)[n] = array;
*(* (pstr + i) + j) = array[i][j];
八、指向函数的指针
函数本身不是变量,但是可以定义指向函数的指针。
int (* fun)(void* , void* )是一个指向 fun 函数的指针; * fun是一个函数;返回值是一个整形对象。
int* fun(void* , void* )是一个指针函数; fun 是一个函数;返回值是一个整形指针。
复杂声明
1.char **p
<span style="white-space:pre"> </span>p : pointer to pointer to char
2.int ( * a )[ n ]
<span style="white-space:pre"> </span>a : pointer to array[ n ] of int
3.int *a[ n ]
<span style="white-space:pre"> </span>a : array[ n ] of pointer to int
4.void* comp()
<span style="white-space:pre"> </span>comp : function returning pointer to void
5.void (*comp)()
<span style="white-space:pre"> </span>comp : pointer to function returning void
6.char ( * ( * x () ) [ ] ) ()
<span style="white-space:pre"> </span>x : function returning pointer to array[] of pointer to function returning char
7.char ( * ( * x [ m ] ) () ) [ n ]
<span style="white-space:pre"> </span>x : array[ m ] of pointer to function returning pointer to array[ n ] of char