开始好好学习C语言啦,指针是C语言比较难的地方,但是非常重要,所以单独在此记录一下。有执念的人最可怕,一定要好好学习哇!!!
str+i == p+i
str[i] == p[i] == *(str+i) == *(str+i)
str[i][j] == str[i][j] == *(str[i]+j) == *(str[i]+j) == ((str+i)+j) == ((str+i)+j)
int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];
int (*p2)[5]; //二维数组指针,不能去掉括号
const char *names[] = {
"Zara Ali",
"Hina Ali",
};
//等同于:
char str[]={
"Zara Ali",
"Hina Ali",
};
const char*names[4];
*names[0]=&str[0]=names;
names[0]=str[0]=*names;
names[1]=str[1]=*(names+1);
void getSeconds(unsigned long *par);
int main ()
{
unsigned long sec;
getSeconds( &sec );//传地址,sec的值会随之变化
/* 输出实际值 */
printf("Number of seconds: %ld\n", sec );//12
return 0;
}
void getSeconds(unsigned long *par)
{
/* 获取当前的秒数 */
*par = 12;
return;
}
#include
double avg1(int *arr,int size);
int main(int argc, char const *argv[])
{
int str[]={1,2,3,4};
double re=avg1(str,4);//传入数组,调用函数
priintf("平均值:%f\n",re);
return 0;
}
double avg1(int *arr,int s){
int i=0;
double avg;
int sum=0;
for ( i = 0; i < s; ++i)
{
sum+=(*arr++);//在这个地方,要注意指针所指向的是什么
//也可以这样写:sum+=arr[i]; *arr就是arr[0],也是str[0]
}
avg=(double)sum/s;
return avg;
}
int fun1(int,int);
int fun1(int a, int b){
return a+b;
}
int main(){
int (*pfun1)(int,int);
pfun1=fun1;//这里&fun1和fun1的值和类型都一样,用哪个无所谓
int a=(*pfun1)(5,7); //通过函数指针调用函数。
//也可以这样调用:pfun1(5,7);
}
//现在有四个函数去处理文件,
void open();
void read();
void write();
void close();
typedef void (*PF) ();//定义一个函数指针类型的别名
//把上面的四种操作取地址放进一个数组中
PF file_options[]={
&open,&read,
&write,&close
};
//file_options就是&file_options[0]也就是ip,因为ip指向file_options[0]。
int *ip = file_options
//此时通过指针ip就可以来调用这四个操作了;
//要注意的是:ip[1]的含义就和*(ip+1)一样,即为第二个函数read();
类比一下数组指针去理解:
int ia[4] = {0, 1, 2, 3};
int *ip = ia;//ip=&ia[0],*ip=ip[0]=ia[0],*(ip+1)=ip[1]=ia[1]
你自己——>主函数,物品名称就是回调函数的名称 代购——>调用主函数的函数(中间函数)`在这里插入代码片` 买物品——>回调函数
#include
#include
//回调函数
int real_back(void)
{
return rand();
}
//用来调用回调函数的函数
int use_back(int *a,int (*fun2) (void) )
{
*a=fun2();//在此调用回调函数
return 0;
}
int main(void)
{
int a;
//此时我们把回调函数real_back作为参数传入use_back函数
use_back( &a, real_back);
printf("%d \n",a);
return 0;
}
定 义 | 含 义 |
---|---|
int *p; | p 可以指向 int 类型的数据,也可以指向类似 int arr[n] 的数组。 |
int **p; | p 为二级指针,指向 int * 类型的数据。 |
int *p[n]; | p 为指针数组。[ ] 的优先级高于 *,所以应该理解为 int *(p[n]); |
int (*p)[n]; | p 为二维数组指针。 |
int *p(); | p 是一个函数,它的返回值类型为 int *。 |
int (*p)(int,int); | p 是一个函数指针,指向原型为 int func(int,int) 的函数。 |
>指针学的差不多了,下面用几道比较经典的题目来看看掌握的如何吧!
#include
int main(){
char str[20] = "c.biancheng.net";
char *s1 = str;
char *s2 = str+2;
char c1 = str[4];
char c2 = *str;
char c3 = *(str+4);
char c4 = *str+2;
char c5 = (str+1)[5];
int num1 = *str+2;
printf(" s1 = %s\n", s1);
printf(" s2 = %s\n", s2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
printf(" c4 = %c\n", c4);
printf(" c5 = %c\n", c5);
printf("num1 = %d\n", num1);
return 0;
}
//运行结果:
s1 = c.biancheng.net
s2 = biancheng.net
c1 = a
c2 = c
c3 = a
c4 = e
c5 = c
num1 = 101
//如果全部正确,那就稍微得意一下下吧,学的还是挺不错的,如果不是,就还需要努努力!
1) str 既是数组名称,也是一个指向字符串的指针;指针可以参加运算,加 1 相当于数组下标加 1。
printf() 输出字符串时,要求给出一个起始地址,并从这个地址开始输出,直到遇见字符串结束标志\0。
s1 为字符串 str 第 0 个字符的地址,s2 为第 2 个字符的地址,所以 printf() 的结果分别为 c.biancheng.net 和 biancheng.net。
(注意:C语言标准规定,当数组名作为数组定义的标识符(也就是定义或声明数组时)、sizeof 或 & 的操作数时,它才表示整个数组本身,在其他的表达式中,数组名会被转换为指向第 0 个元素的指针(地址)。)
2) 指针可以参加运算,str+4 表示第 4 个字符的地址,c3 = *(str+4) 表示第4个字符,即 'a'。
3) 其实,数组元素的访问形式可以看做 address[offset],address 为起始地址,offset 为偏移量:
c1 = str[4]表示以地址 str 为起点,向后偏移4个字符,为 'a';
c5 = (str+1)[5]表示以地址 str+1 为起点,向后偏移5个字符,等价于str[6],为 'c'。
4) 字符与整数运算时,先转换为整数(字符对应的ASCII码)。
num1 与 c4 右边的表达式相同,对于 num1,*str+2 == 'c'+2 == 99+2 == 101,
即 num1 的值为 101,对于 c4,101 对应的字符为 ‘e’,所以 c4 的输出值为 'e'。
#include
int main(){
char *lines[5] = {
"COSC1283/1284",
"Programming",
"Techniques",
"is",
"great fun"
};
char *str1 = lines[1];
char *str2 = *(lines + 3);
char c1 = *(*(lines + 4) + 6);
char c2 = (*lines + 5)[5];
char c3 = *lines[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
return 0;
}
//运行结果:
str1 = Programming
str2 = is
c1 = f
c2 = 2
c3 = E
把代码改成下面这种形式,更加容易去理解:
#include
int main(){
char *string0 = "COSC1283/1284";
char *string1 = "Programming";
char *string2 = "Techniques";
char *string3 = "is";
char *string4 = "great fun";
char *lines[5];
lines[0] = string0;
lines[1] = string1;
lines[2] = string2;
lines[3] = string3;
lines[4] = string4;
char *str1 = lines[1];
char *str2 = *(lines + 3);
char c1 = *(*(lines + 4) + 6);
char c2 = (*lines + 5)[5];
char c3 = *lines[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
return 0;
}
首先我们要明白,char *lines[5]定义了一个指针数组,它的每个元素的类型都是char 。
在表达式中使用 lines 时,它会转换为一个类型为char **的指针,这样*lines就表示一个指向字符的指针,而**lines表示一个具体的字符,这一点很重要,一定要好好理解!
上面的题目中:
1)、lines[1]:它是一个指针,指向字符串string1,即 string1 的首地址。
*(lines + 3):lines + 3 为数组中第 3 个元素的地址,*(lines + 3) 为第 3 个元素的值,它是一个指针,指向字符串 string3。
2)、 *(*(lines + 4) + 6):*(lines + 4) + 6 == lines[4] + 6 == string4 + 6,
表示字符串 string4 中第 6 个字符的地址,即 f 的地址,所以 *(*(lines + 4) + 6) 就表示字符 f。
3)、(*lines + 5)[5]:*lines + 5 为字符串 string0 中第 5 个字符的地址,即 2 的地址,
(*lines + 5)[5]等价于*(*lines + 5 + 5),表示第10个字符,即 2。
4)、*lines[0] + 2:lines[0] 为字符串 string0 中第 0 个字符的地址,即 C 的地址;
*lines[0]也就表示第 0 个字符,即字符 C。字符与整数运算,首先转换为该字符对应的 ASCII 码,
然后再运算,所以 *lines[0] + 2 = 67 + 2 = 69,69 对应的字符为 E。