目录
编写一个函数,生成10个随机数,并使用表示指针的数组名(一个数组元素的地址)来返回它们
- #include
-
- const int MAX = 3;//常量
- int main () {
- int var[] = {10, 100, 200}; // int 数组
- int i, *ptr; // ptr 是一个 int* 指针
-
- ptr = var; // ptr 指向了 var 数组的首地址
- for ( i = 0; i < MAX; i++) {
-
- printf("var[%d]的地址= %p \n", i, ptr );
- printf("存储值:var[%d] = %d\n\n", i, *ptr );
-
- ptr++;// ptr = ptr + 1(1个int字节数); ptr 存放值+4字节(int)
- }
- getchar();
- return 0;
- }
- int main () {
- int var[] = {10, 100, 200};
- int i, *ptr;
-
- ptr = var; // 将 var 的首地址 赋给 ptr
- ptr += 2; // ptr 的存储的地址 + 2个int的字节 (8个字节)
- printf("var[2]=%d \nvar[2]的地址=%p \nptr存储的地址=%p \nptr指向的值=%d",
- var[2], &var[2], ptr, *ptr);
-
- getchar();
- return 0;
- }
- const int MAX = 3;//常量
- int main () {
- int var[] = {10, 100, 200}; // int 数组
- int i, *ptr; // ptr 是一个 int* 指针
-
- /* 指针中最后一个元素的地址 */
- ptr = &var[MAX-1]; // &var[2]
- for ( i = MAX; i > 0; i--) {// 反向遍历
- printf("ptr存放的地址=%p\tvar[%d]的地址=%p\n", ptr,i,&var[i-1]);
- printf("存储值:var[%d] = %d\n\n", i-1, *ptr );
-
- ptr--; // ptr = ptr - 1(1个int的字节数 [4个字节])
- }
- getchar();
- return 0;
- }
- #include
-
- int main () {
- int var[] = {10, 100, 200};
- int *ptr;
- ptr = var;//ptr 指向var 首地址(第一个元素)
- if(ptr == var[0]) {//错误,类型不一样 (int *) 和 (int )
- printf("ok1");//不输出
- }
- if(ptr == &var[0]) { // 可以
- printf("\nok2"); //输出
- }
- if(ptr == var) { //可以
- printf("\nok3"); //输出
- }
- if(ptr >= &var[1]) { //可以比较,但是返回false
- printf("\nok4");//不会输出
- }
- getchar();
- return 0;
- }
- const int MAX = 3;
- int main () {
- int var[] = {10, 100, 200};
- int i, *ptr;
- ptr = var;
- i = 0;
- while ( ptr <= &var[MAX - 2] ){//&var[1]
- printf("Address of var[%d] = %x\n", i, ptr );//16进制输出
- printf("Value of var[%d] = %d\n", i, *ptr );
- ptr++;
- i++;
- } //会输出 10 , 100
- getchar();
- return 0;
- }
- #include
- const int MAX=3;
- int main (){
-
- //指针数组
- int var[] = {10, 100, 200};
- int i, *ptr[3];
-
- for ( i = 0; i < MAX; i++){
-
- ptr[i] = &var[i]; /* 赋的值为整数的地址 */
- }
- for ( i = 0; i < MAX; i++){ //指针数组来获取各个值
-
- printf("Value of var[%d] = %d \tptr[%d]本身的地址=%p\t ptr[%d]保存的地址=%p\t var[%d]的地址=%p\n",
- i, *ptr[i] , i, &ptr[i],i,ptr[i],i,&var[i]); // 10, 100, 200
-
- }
- getchar();
- return 0;
- }
(定义一个指针数组,该数组的每个元素,指向的是一个字符串)
- #include
-
- void main() {
-
- //定义一个指针数组,该数组的每个元素,指向的是一个字符串
-
- //当输出数组所指字符串直接是books[i]
- char *books[] = {
- "三国演义",
- "西游记",
- "红楼梦",
- "水浒传"
- };
- char * pStr = "abc";
-
- int strLen = sizeof(pStr);
-
- //遍历
- int i, len = 4;
- for(i = 0; i < len; i++) {
- printf("\nbooks[%d] 指向字符串 = %s,books[%d]的地址 = %p\n", i, books[i],i,&books[i]);
-
- printf("pStr指向的内容 = %s 地址 = %p\n\n",pStr,pStr);
-
- printf("pStr指针的长度为%d\n\n", strLen);
- }
- getchar();
-
- }
- 为什么books[]指针字符数组每一个地址长度都为4?
这是指针的长度,不是数组的长度
- 若求的是books[]的长度,则可以使用sizeof()函数中的形参为books.即sizeof(books)
指向指针的指针是一种多级间接寻址的方式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
int **ptr//ptr的类型是int **
- #include
-
- void main() {
- int var;
- int* ptr;
- int** pptr;
- var = 3000;
-
- ptr = &var;//var变量的地址赋给ptr
- pptr = &ptr;//将ptr的地址,赋给pptr
-
- printf("var的地址 = %p, var = %d\n\n", &var, var);
- printf("ptr的本身地址 = %p, ptr存放的地址 = %p, *ptr = %d\n\n", &ptr, ptr, *ptr);
- printf("pptr的本身地址 = %p, pptr存放的地址 = %p, **pptr = %d\n", &pptr, pptr, **pptr);
-
- getchar();
-
- }
- //指针传递给函数
- //数组默认也是指针传递
- #include
-
- void test2(int *p); //函数声明,接收int *
- void main() {
- int num=90;
- int *p = # //将 num 的地址赋给 p
-
- test2(&num); //传地址
- printf("\nmain() 中的num=%d", num); // num = 91
-
- test2(p); //传指针
- printf("\nmain() 中的num=%d", num);// num = 92
- getchar();
- }
- void test2(int *p) {
- *p += 1; //*p 就访问 num的值
- }
数组名本身就代表该数组首地址,因此传数组的本质就是传地址
- #include
-
-
- /* 函数声明 */
- double getAverage(int *arr, int size); //函数声明
- double getAverage2(int *arr, int size); //函数声明
- int main ()
- {
- /* 带有 5 个元素的整型数组 */
- int balance[5] = {1000, 2, 3, 17, 50};
- double avg;
- /* 传递一个指向数组的指针作为参数 */
- avg = getAverage( balance, 5 ) ;
- /* 输出返回值 */
- printf("Average value is: %f\n", avg );
- getchar();
- return 0;
- }
- //说明
- //1. arr 是一个指针,
- double getAverage(int *arr, int size){
-
- int i, sum = 0;
- double avg;
- for (i = 0; i < size; ++i){
- // arr[0] = arr + 0
- // arr[1] = arr + 1个int字节(4)
- // arr[2] = arr + 2个int字节(8)
- //...
- sum += arr[i];// arr[0] =>数组第一个元素的地址
- //此时函数的指针指向的地址(保存的地址)并不会改变,而是直接通过下标取值
- printf("\narr存放的地址=%p ", arr);
- }
- avg = (double)sum / size;
- return avg;
- }
- #include
-
-
- /* 函数声明 */
- double getAverage(int *arr, int size); //函数声明
- double getAverage2(int *arr, int size); //函数声明
- int main ()
- {
- /* 带有 5 个元素的整型数组 */
- int balance[5] = {1000, 2, 3, 17, 50};
- double avg;
- /* 传递一个指向数组的指针作为参数 */
- avg = getAverage2( balance, 5 ) ;
- /* 输出返回值 */
- printf("Average value is: %f\n", avg );
- getchar();
- return 0;
- }
- //说明
- //1. arr 是一个指针,
-
- double getAverage2(int *arr, int size){
-
- int i, sum = 0;
- double avg;
- for (i = 0; i < size; ++i){
-
- sum += *arr;
- printf("\narr存放的地址=%p ", arr);
- arr++; // 指针的++运算, 会对arr 存放的地址做修改
-
- }
- avg = (double)sum / size;
- return avg;
- }
如果在getVerage()函数中,通过指针修改了数组的值,那么main函数的balance数组也会发生相应变化。getVerage函数中的指针,指向的就是main函数的数组
C语言允许函数的返回值是一个指针(地址),这样的函数称为指针函数
- #define _CRT_SECURE_NO_WARNINGS
- #include
- #include
-
- char *strlong(char *str1, char *str2){ //函数返回的char * (指针)
- printf("\nstr1的长度%d str2的长度%d", strlen(str1), strlen(str2));
- if(strlen(str1) >= strlen(str2)){
- return str1;
- }else{
- return str2;
- }
- }
- int main(){
- char str1[30], str2[30], *str; // str 是一个指针类型,指向一个字符串
- printf("\n请输入第1个字符串");
- //gets(str1);//和scanf()函数的功能一致
- scanf("%s", str1);
- getchar();
- printf("\n请输入第2个字符串");
- gets(str2);
- str = strlong(str1, str2);
- printf("\nLonger string: %s \n", str);
- printf("\nstr指针本身的地址为: %p \n", &str);
- printf("\nstr指针指向的地址为: %p \n", str1);
- printf("\nstr1数组的地址为: %p \n", str1);
- printf("\nstr2数组的地址为: %p \n", str2);
- getchar();
- return 0;
- }
- #include
-
- int *func(){
- //int n = 100;//局部变量, 在func 返回时,就会销毁
-
- static int n = 100; // 如果这个局部变量是 static 性质的,那么n 存放数据的空间在静态数据区
- return &n;
- }
- int main(){
- int *p = func(); //func 返回指针
- printf("当前返回的指针指向的值为%d", *p);
-
- int n;
- //printf("okoook~~"); //可能是使用到 局部变量 int n = 100 占用空间
- //printf("okoook~~");
- //printf("okoook~~");
- n = *p;
- printf("\nvalue = %d\n", n);// 思考,当直接int n = 100时是否能够输出100? 不一定
- //当用static修饰时,就能直接输出100
- getchar();
- return 0;
- }
- #include
- #include
- #include
-
- //编写一个函数,返回一个一维数组
- int * f1() {
- static int arr[10]; //必须加上static ,让arr 的空间在静态数据区分配
-
- int i = 0;
- srand((unsigned)time(NULL));//随机数需要的,同时还有
头文件 -
- for (i = 0; i < 10;i++) {
- //arr[i] = rand();//伪随机数
-
- arr[i] = rand();//真正随机数
- }
-
- return arr;
- }
-
- void main() {
-
- int *p;
- int i;
- p = f1(); //p 指向是在 f1 生成的数组的首地址(即第一个元素的地址)
- for ( i = 0; i <10; i++) {
- printf("\n%d", *(p+i));
- }
- getchar();
- }
returnType (*pointerName)(param list);
returnType *pointerName (param list);
就成了函数原型,它表明函数的返回值类型为returnType *
- #define _CRT_SECURE_NO_WARNINGS
- #include
-
- //说明
- //1. max 函数
- //2. 接收两个int ,返回较大数
- int max(int a, int b){
- return a>b ? a : b;
- }
-
- int main(){
- int x, y, maxVal;
-
- //说明 函数指针
- //1. 函数指针的名字 pmax
- //2. 第一个int 表示 该函数指针指向的函数是返回int 类型
- //3. (int, int) 表示 该函数指针指向的函数形参是接收两个 int
- //4. 在定义函数指针时,也可以写上形参名 int (*pmax)(int x, int y) = max;
- int (*pmax)(int x, int y) = max; //pmax函数指针指向的就是max函数
-
- printf("Input two numbers:");
- scanf("%d %d", &x, &y);
- // (*pmax)(x, y) 通过函数指针去调用 函数max
- // 调用方式 2 pmax(x,y)
- //maxVal = pmax(x,y);同样可以输出正确
-
- maxVal = (*pmax)(x, y);
-
- printf("\nmax函数的首地址为%p\n", &max);
- printf("\nMax value: %d pmax保存的地址为%p pmax本身的地址=%p\n", maxVal, pmax, &pmax);
- getchar();
- getchar();
- return 0;
- }
函数指针变量可以作为某个函数的参数来使用,回调函数就是一个通过函数指针调用的函数
回调函数就是由别人的函数执行时调用自己传入的函数
- #include
- #include
-
-
- // 回调函数
- //1. int (*f)()
- //2. f 就是 函数指针 , 它可以接收的函数是 (返回 int ,没有形参的函数)
- //3. f 在这里被 initArray 调用,充当了回调函数角色
- void initArray(int *array, int arraySize, int (*f)()) {
- int i ;
- //循环10
- for ( i=0; i
- array[i] = f(); //通过 函数指针调用了 getNextRandomValue 函数
- }
- }
-
- // 获取随机值
- int getNextRandomValue() {
-
- return rand();//rand 系统函数, 会返回一个随机整数
- }
-
- int main() {
- int myarray[10],i; //定义一个数组和 int
-
- //说明
- //1. 调用 initArray 函数
- //2. 传入了一个函数名 getNextRandomValue (地址), 需要使用函数指针接收
- initArray(myarray, 10, getNextRandomValue);
-
- //输出赋值后的数组
- for(i = 0; i < 10; i++) {
- printf("%d\n", myarray[i]);
- }
- printf("\n");
- getchar();
- return 0;
- }
输出值为10个整数,也就是一个数组的形式
指针的注意事项和细节
- 指针变量存放的是地址,指针的本质就是地址
- 变量声明的时候,如果没有确切的地址赋值,为指针变量赋一个NULL值
- 赋为NULL值得指针被称为空指针,NULL指针是一个定义在标准库
中值为零的常量
int *p = NULL; // p 空指针