指针与指针数组
#include <stdio.h> void zz1(){ char *ss = "wa ka ka"; printf("%s ",ss); } void zz2(){ char *ss[] = {"luo bo","bai cai"}; int i =0; for(i =0; i<2; i++){ printf("ss[%d]=%s ",i,ss[i]); } } void zz3(){ int nn = sizeof("wa ka ka"); printf("%d ",nn); //9 } void zz4(){ int i = 99; int *ptr = &i; printf("%p ",ptr); //0x7ffc9bce8354 printf("%d ",*ptr); //99 } int main(void){ zz1(); zz2(); zz3(); zz4(); }
"wa ka ka"是一眼看去是8个字符,C语言却认为它是9个字符,C语言的字符串的结尾有个默认的结束符,用于计算机判断该字符串结束。
char *ss = "wa ka ka";
ss是一个变量,指针类型的变量,指向了字面量"wa ka ka"的首地址,指针从首地址向下移动,遇到结束符自动结束,所以直接输出指针就输出了整个字符串。
而对于整数类型,ptr就是指针变量,存储的值为整数类型的地址,*是取地址中的值,*ptr就取出了整数99;一个整数一个存储地址足以,它不像字符串是由多个字符组成,每个字符本身就占了一个存储单元,需要指针不断地移动才能输出所有字符。
指针内容是全局常量
这是相对于字符数组来说的,因为数组形式的字符串是局部变量
#include <stdio.h> #include <stdlib.h> #include <string.h> char* zz5(){ char *ss = "wa ka ka"; return ss; } /* char* zz6(){ char ss[9] = "wa ka ka"; printf("%s ",ss); return ss; //这里报错,warning: function returns address of local variable [-Wreturn-local-addr] } */ int main(void) { char *ss = zz5(); printf("%s ",ss); return 0; }
zz5方法中,字符串指针ss指向字面量"wa ka ka",这是一个全局的常量,ss是局部变量,它返回的地址是指向全局常量的,所以其他程序仍能访问其地址;
而zz6中的ss指向的是局部变量,ss同样是返回地址,但它指向的局部变量在方法结束时已经不存在了,所以程序报错。
函数指针
/* ============================================================================ Name : c01.c Author : tanpf Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> int add(int a) { return a+1; } void testp1(){ int (* p)(int) = &add; puts("请输入一个int"); int a,b; scanf("%d",&a); b = p(a); printf("res:%d ",b); } void testp2(){ int (* p)(int) = add; puts("请输入一个int"); int a,b; scanf("%d",&a); b = p(a); printf("res:%d ",b); } void testFunc(){ printf("addr :%x ",&add); //addr :4005ed printf("addr :%x ",add); //addr :4005ed int var[] = {1,2,3}; printf("addr first arr:%x ",&var); //addr first arr:b396ed40 printf("addr first arr:%x ",var); //addr first arr:b396ed40 printf("addr first ele:%x ",&var[0]); //addr first arr:b396ed40 printf("addr first ele:%x ",&var[1]); //addr first ele:b396ed44 } int main(void) { testFunc(); testp2(); return 0; }
testp1方法与testp2方法的输出结果完全一致;这是因为add本身就指向方法入口地址,&add一样是取add的入口地址;对指针来说,只需要指向访问的入口即可,所以它们的结果一致;数组同样如此。
也就是说,要将一个函数赋予“函数指针”的话,直接写函数名称或&取地址后再赋值都是可以的。