C语言05指针基础

1 局部变量和全局变量

1.1 问题

分别定义一个局部变量和全局变量,测试生命期限和作用域。

1.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:局部变量和全局变量

代码如下所示:

  1. #include <stdio.h>
  2. /*auto*/ int x = 1000;
  3. void f1(int a)
  4. {
  5. a = 10;
  6. auto int x = 20;
  7. static int y = 30;
  8. y++;
  9. x++;
  10. printf("in f1(),a=%d,x=%d,y=%d\n",a,x,y);
  11. }
  12. void f2()
  13. {
  14. printf("in f2(),x=%d\n",x);
  15. x = 2000;
  16. }
  17. void f3()
  18. {
  19. printf("in f3(),x=%d\n",x);
  20. }
  21. int main()
  22. {
  23. int x = 30,b=100;
  24. f1(b);
  25. f1(b);
  26. printf("in main(),b=%d,x=%d\n",b,x);
  27. f2();
  28. f3();
  29. return 0;
  30. }

上述代码中,以下代码:

  1. /*auto*/ int x = 1000;

定义了一个全局变量x,该变量在所有函数中共享。

上述代码中,以下代码:

  1. void f1(int a)
  2. {
  3. a = 10;
  4. auto int x = 20;
  5. static int y = 30;
  6. y++;
  7. x++;
  8. printf("in f1(),a=%d,x=%d,y=%d\n",a,x,y);
  9. }

定义了一个函数f1,该函数没有返回值,有一个参数是一个整型变量a。该函数中以下语句:

  1. a = 10;

将参数a赋值为10,参数a是局部变量,只能用在f1函数中。该函数中以下语句:

  1. auto int x = 20;

定义了另一个局部变量x,也只能用在f1函数中。前面的auto关键字可有可无。该函数中以下语句:

  1. static int y = 30;

定义了一个static局部变量y,也只能用在f1函数中,但函数返回后该变量不会被释放,直到主函数退出时,它才会被释放。该函数中以下语句:

  1. y++;
  2. x++;

对局部变量x和y进行自增操作。

注意:在函数f1中,定义了局部变量x,而在该函数的上面还定义全局变量x,这样在函数f1中,有两个x,但C语言规定,在这种情况下,局部变量x将隐藏全局变量x,即全局变量x此时不起作用。

该函数中以下语句:

  1. printf("in f1(),a=%d,x=%d,y=%d\n",a,x,y);

使用函数printf输出局部变量a和x的值,以及静态局部变量y的值。

上述代码中,以下代码:

  1. void f2()
  2. {
  3. printf("in f2(),x=%d\n",x);
  4. x = 2000;
  5. }

定义了一个无参无返回值的函数f2。该函数中以下语句:

  1. x = 2000;

对全局变量x进行赋值。

上述代码中,以下代码:

  1. void f3()
  2. {
  3. printf("in f3(),x=%d\n",x);
  4. }

定义了一个无参无返回值的函数f2。该函数中以下语句:

  1. printf("in f3(),x=%d\n",x);

对全局变量x进行输出。

上述代码中,以下代码:

  1. int main()
  2. {
  3. int x = 30,b=100;

在主函数中,定义了两个局部变量x和b,并分别初始化为30和100。这两个局部变量只能用在main函数中。

上述代码中,以下代码:

  1. f1(b);
  2. f1(b);

两次调用函数f1,并用局部变量b作为实参。

注意:两次调用中,函数f1中的静态局部变量y输出值不一样。因为static关键字使该变量在函数f1返回后并不释放,所以第二次调用时,其值会在上一次调用返回前的基础上发生变化。

上述代码中,以下代码:

  1. printf("in main(),b=%d,x=%d\n",b,x);

使用函数printf输出局部变量b和局部变量x的值。

注意:在函数main中,定义了局部变量x,而在该函数的上面还定义全局变量x,这样在函数main中,有两个x,但C语言规定,在这种情况下,局部变量x将隐藏全局变量x,即全局变量x此时不起作用。

上述代码中,以下代码:

  1. f2();
  2. f3();

调用函数f2和f3,从输出的值上可以看出,全局变量可以在所有函数中共享。

1.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. /*auto*/ int x = 1000;
  3. void f1(int a)
  4. {
  5. a = 10;
  6. auto int x = 20;
  7. static int y = 30;
  8. y++;
  9. x++;
  10. printf("in f1(),a=%d,x=%d,y=%d\n",a,x,y);
  11. }
  12. void f2()
  13. {
  14. printf("in f2(),x=%d\n",x);
  15. x = 2000;
  16. }
  17. void f3()
  18. {
  19. printf("in f3(),x=%d\n",x);
  20. }
  21. int main()
  22. {
  23. int x = 30,b=100;
  24. f1(b);
  25. f1(b);
  26. printf("in main(),b=%d,x=%d\n",b,x);
  27. f2();
  28. f3();
  29. return 0;
  30. }

2 指针的基本用法

2.1 问题

定义一个int类型的指针,指向一个整型变量,然后分别使用&和*取得地址或者数据。

2.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:指针的基本用法

代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a = 10;
  5. int *p;
  6. p = &a;
  7. printf("p = %p\n", p);
  8. printf("&a = %p\n", &a);
  9. printf("a = %d\n", a);
  10. printf("*p = %d\n", *p);
  11. return 0;
  12. }

上述代码中,以下代码:

  1. int a = 10;

定义了一个整型变量a,并初始化为10。

上述代码中,以下代码:

  1. int *p;
  2. p = &a;

定义了一个整型指针变量p,并使用取地址运算符&将整型变量a的地址赋值给p。

上述代码中,以下代码:

  1. printf("p = %p\n", p);
  2. printf("&a = %p\n", &a);

使用函数printf输出指针变量p的值和整型变量a的地址值。从输出结果可以看出,指针变量p中存放的就是整型变量a的地址值。

上述代码中,以下代码:

  1. printf("a = %d\n", a);

使用函数printf输出整型变量a的值。

上述代码中,以下代码:

  1. printf("*p = %d\n", *p);

使用函数printf输出指针变量p所指向的地址单元的值。由于指针变量p被赋值成了整型变量a的地址值,所以,p就指向a的地址,所以输出的就是a的值。

2.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a = 10;
  5. int *p;
  6. p = &a;
  7. printf("p = %p\n", p);
  8. printf("&a = %p\n", &a);
  9. printf("a = %d\n", a);
  10. printf("*p = %d\n", *p);
  11. return 0;
  12. }

3 指针的优势

3.1 问题

使用指针实现交换变量值的函数swap(),同时编写不使用指针交换失败的函数做对比。

3.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:指针的优势

代码如下所示:

  1. #include <stdio.h>
  2. void swap(int a, int b)
  3. {
  4. printf("in swap() a = %d, b = %d\n", a, b);
  5. int tmp = a;
  6. a = b;
  7. b = tmp;
  8. printf("in swap() a = %d, b = %d\n", a, b);
  9. }
  10. void swap1(int *a, int *b)
  11. {
  12. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  13. int tmp = *a;
  14. *a = *b;
  15. *b = tmp;
  16. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  17. }
  18. int main()
  19. {
  20. int x = 10, y = 20;
  21. printf("in main() x = %d, y = %d\n", x, y);
  22. swap(x, y);
  23. printf("in main() x = %d, y = %d\n", x, y);
  24. swap1(&x, &y);
  25. printf("in main() x = %d, y = %d\n", x, y);
  26. return 0;
  27. }

上述代码中,以下代码:

  1. void swap(int a, int b)
  2. {
  3. printf("in swap() a = %d, b = %d\n", a, b);
  4. int tmp = a;
  5. a = b;
  6. b = tmp;
  7. printf("in swap() a = %d, b = %d\n", a, b);
  8. }

定义了一个函数swap,该函数有两个参数,为整型变量a和b。在该函数中,以下语句:

  1. printf("in swap() a = %d, b = %d\n", a, b);

使用函数printf输出形参a和b从调用函数传入的值。在该函数中,以下语句:

  1. int tmp = a;
  2. a = b;
  3. b = tmp;

通过第三个变量tmp,将整型变量a和b的值进行交换。在该函数中,以下语句:

  1. printf("in swap() a = %d, b = %d\n", a, b);

使用函数printf输出形参a和b交换后的值。

上述代码中,以下代码:

  1. void swap1(int *a, int *b)
  2. {
  3. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  4. int tmp = *a;
  5. *a = *b;
  6. *b = tmp;
  7. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  8. }

定义了一个函数swap1,该函数有两个参数,为整型指针变量a和b。在该函数中,以下语句:

  1. printf("in swap1() *a = %d, *b = %d\n", *a, *b);

使用函数printf输出整型指针变量a和b指向的地址的值。在该函数中,以下语句:

  1. int tmp = *a;
  2. *a = *b;
  3. *b = tmp;

通过第三个变量tmp,将整型指针变量a和b指向的地址的值进行交换。在该函数中,以下语句:

  1. printf("in swap1() *a = %d, *b = %d\n", *a, *b);

使用函数printf输出整型指针变量a和b指向地址的值交换后的值。

上述代码中,以下代码:

  1. int main()
  2. {
  3. int x = 10, y = 20;

在主函数中定义两个整型变量x和y,并将它们初始化为10和20。

上述代码中,以下代码:

  1. printf("in main() x = %d, y = %d\n", x, y);

使用函数printf输出变量x和y的初始值。

上述代码中,以下代码:

  1. swap(x, y);
  2. printf("in main() x = %d, y = %d\n", x, y);

首先,调用函数swap。

然后,使用函数printf输出整型变量x和y在调用函数swap后的变化情况。从输出结果可以看出,没有发生变化。因为swap函数定义的参数是整型变量,这时,实参到形参的传递过程是值传递,即仅将实参x和y的值传递给形参a和b,而形参a和b在函数swap中发生的变化并不会传回给实参。

上述代码中,以下代码:

  1. swap1(&x, &y);
  2. printf("in main() x = %d, y = %d\n", x, y);

首先,调用函数swap1。

然后,使用函数printf输出整型变量x和y在调用函数swap1后的变化情况。从输出结果可以看出,确实发生了变化。因为swap1函数定义的参数是整型指针变量,实参将变量x和y的地址传给了形参a和b,在函数swap1中使用*a和*b操作的是指针a和b指向的地址单元的值,即变量x和y的值。

3.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. void swap(int a, int b)
  3. {
  4. printf("in swap() a = %d, b = %d\n", a, b);
  5. int tmp = a;
  6. a = b;
  7. b = tmp;
  8. printf("in swap() a = %d, b = %d\n", a, b);
  9. }
  10. void swap1(int *a, int *b)
  11. {
  12. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  13. int tmp = *a;
  14. *a = *b;
  15. *b = tmp;
  16. printf("in swap1() *a = %d, *b = %d\n", *a, *b);
  17. }
  18. int main()
  19. {
  20. int x = 10, y = 20;
  21. printf("in main() x = %d, y = %d\n", x, y);
  22. swap(x, y);
  23. printf("in main() x = %d, y = %d\n", x, y);
  24. swap1(&x, &y);
  25. printf("in main() x = %d, y = %d\n", x, y);
  26. return 0;
  27. }

4 指针的优势(续1)

4.1 问题

使用指针做参数取函数的返回值,写一个函数,找出一个数组中的最大值和最小值。

4.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:指针的优势(续1)

代码如下所示:

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. void maxAndMin(int data[], int size, int *max, int *min)
  5. {
  6. *max = data[0];
  7. *min = data[0];
  8. for (int i = 0; i < size; i++)
  9. {
  10. if (*max < data[i])
  11. *max = data[i];
  12. if (*min > data[i])
  13. *min = data[i];
  14. }
  15. }
  16. int main(int argc, const char * argv[])
  17. {
  18. int data[10];
  19. srand((unsigned)time(0));
  20. for (int i = 0; i < 10; i++)
  21. data[i] = rand() % 100;
  22. printf("数组中的数据为:");
  23. for (int i = 0; i < 10; i++)
  24. printf("%d ", data[i]);
  25. printf("\n");
  26. int max;
  27. int min;
  28. maxAndMin(data, 10, &max, &min);
  29. printf("最大值为:%d\n", max);
  30. printf("最小值为:%d\n", min);
  31. return 0;
  32. }

上述代码中,下面代码行:

  1. void maxAndMin(int data[], int size, int *max, int *min)

是自定义函数的函数头,该函数为无返回值函数,函数名为maxAndMin,函数有四个形参,第一个形参为一个数组,在此数组中找到最大值和最小值;第二个形参为数组的长度;第三个形参是一个指针变量,此参数用于将数组中的最大值带回主函数;第四个形参也是一个指针变量,此参数用于将数组中的最小值带回主函数。

上述代码中,下面代码行:

  1. *max = data[0];
  2. *min = data[0];

首先假定数组的最大值与最小值都是数组的第一个元素。

上述代码中,下面代码行:

  1. for (int i = 0; i < size; i++)
  2. {
  3. if (*max < data[i])
  4. *max = data[i];
  5. if (*min > data[i])
  6. *min = data[i];
  7. }

遍历数组,逐个元素与最大值和最小值对比,如果比最大值大,替换最大值;如果比最小值小,则替换最小值。

上述代码中,下面代码行:

  1. int main(int argc, const char * argv[])
  2. {
  3. int data[10];

在主函数中,定义数组data,有10个元素。

上述代码中,下面代码行:

  1. srand((unsigned)time(0));
  2. for (int i = 0; i < 10; i++)
  3. data[i] = rand() % 100;
  4. printf("数组中的数据为:");
  5. for (int i = 0; i < 10; i++)
  6. printf("%d ", data[i]);
  7. printf("\n");

首先,为每个数组元素赋值成一个0~99之间的随机数。

然后,将数组中数据显示出来。

上述代码中,下面代码行:

  1. int max;
  2. int min;

定义两个变量,分别用于存储数组中的最大值和最小值。

上述代码中,下面代码行:

  1. maxAndMin(data, 10, &max, &min);

调用maxAndMin函数,数组data作为第一个实参,第二个实参是数组data的长度,第三个实参是变量max的地址,这样可以将最大值带回来,第四个实参是变量min的地址,它用于带回最小值。

4.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. void maxAndMin(int data[], int size, int *max, int *min)
  5. {
  6. *max = data[0];
  7. *min = data[0];
  8. for (int i = 0; i < size; i++)
  9. {
  10. if (*max < data[i])
  11. *max = data[i];
  12. if (*min > data[i])
  13. *min = data[i];
  14. }
  15. }
  16. int main(int argc, const char * argv[])
  17. {
  18. int data[10];
  19. srand((unsigned)time(0));
  20. for (int i = 0; i < 10; i++)
  21. data[i] = rand() % 100;
  22. printf("数组中的数据为:");
  23. for (int i = 0; i < 10; i++)
  24. printf("%d ", data[i]);
  25. printf("\n");
  26. int max;
  27. int min;
  28. maxAndMin(data, 10, &max, &min);
  29. printf("最大值为:%d\n", max);
  30. printf("最小值为:%d\n", min);
  31. return 0;
  32. }

5 指针的算术运算

5.1 问题

测试不同类型的指针的算术运算。

5.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:指针的算术运算

代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a;
  5. int *pa = &a;
  6. printf("pa = %p, pa + 1 = %p\n", pa, pa + 1);
  7. short s;
  8. short *ps = &s;
  9. printf("ps = %p, ps + 1 = %p\n", ps, ps + 1);
  10. long l;
  11. long *pl = &l;
  12. printf("pl = %p, pl + 1 = %p\n", pl, pl + 1);
  13. char c;
  14. char *pc = &c;
  15. printf("pc = %p, pc + 1 = %p\n", pc, pc + 1);
  16. float f;
  17. float *pf = &f;
  18. printf("pf = %p, pf + 1 = %p\n", pf, pf + 1);
  19. double d;
  20. double *pd = &d;
  21. printf("pd = %p, pd + 1 = %p\n", pd, pd + 1);
  22. return 0;
  23. }

上述代码中,以下代码:

  1. int a;
  2. int *pa = &a;
  3. printf("pa = %p, pa + 1 = %p\n", pa, pa + 1);

首先,定义了一个整型变量a。

然后,定义了一个整型指针变量pa,并初始化为整型变量a的地址。

最后,使用函数printf输出指针pa的值和pa+1的值。从输出结果可以看出,整型指针变量加1时,相当于加了1*sizeof(int),即4个字节。

上述代码中,以下代码:

  1. short s;
  2. short *ps = &s;
  3. printf("ps = %p, ps + 1 = %p\n", ps, ps + 1);

首先,定义了一个短整型变量s。

然后,定义了一个短整型指针变量ps,并初始化为短整型变量s的地址。

最后,使用函数printf输出指针ps的值和ps+1的值。从输出结果可以看出,短整型指针变量加1时,相当于加了1*sizeof(short),即2个字节。

上述代码中,以下代码:

  1. long l;
  2. long *pl = &l;
  3. printf("pl = %p, pl + 1 = %p\n", pl, pl + 1);

首先,定义了一个长整型变量l。

然后,定义了一个长整型指针变量pl,并初始化为长整型变量l的地址。

最后,使用函数printf输出指针pl的值和pl+1的值。从输出结果可以看出,长整型指针变量加1时,相当于加了1*sizeof(long),即8个字节。

上述代码中,以下代码:

  1. char c;
  2. char *pc = &c;
  3. printf("pc = %p, pc + 1 = %p\n", pc, pc + 1);

首先,定义了一个字符型变量c。

然后,定义了一个字符型指针变量pc,并初始化为字符型变量c的地址。

最后,使用函数printf输出指针pc的值和pc+1的值。从输出结果可以看出,字符型指针变量加1时,相当于加了1*sizeof(char),即1个字节。

上述代码中,以下代码:

  1. float f;
  2. float *pf = &f;
  3. printf("pf = %p, pf + 1 = %p\n", pf, pf + 1);

首先,定义了一个浮点型变量f。

然后,定义了一个浮点型指针变量pf,并初始化为浮点型变量f的地址。

最后,使用函数printf输出指针pf的值和pf+1的值。从输出结果可以看出,浮点型指针变量加1时,相当于加了1*sizeof(float),即4个字节。

上述代码中,以下代码:

  1. double d;
  2. double *pd = &d;
  3. printf("pd = %p, pd + 1 = %p\n", pd, pd + 1);

首先,定义了一个双精度浮点型变量d。

然后,定义了一个双精度浮点型指针变量pd,并初始化为双精度浮点型变量d的地址。

最后,使用函数printf输出指针pd的值和pd+1的值。从输出结果可以看出,双精度浮点型指针变量加1时,相当于加了1*sizeof(double),即8个字节。

5.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a;
  5. int *pa = &a;
  6. printf("pa = %p, pa + 1 = %p\n", pa, pa + 1);
  7. short s;
  8. short *ps = &s;
  9. printf("ps = %p, ps + 1 = %p\n", ps, ps + 1);
  10. long l;
  11. long *pl = &l;
  12. printf("pl = %p, pl + 1 = %p\n", pl, pl + 1);
  13. char c;
  14. char *pc = &c;
  15. printf("pc = %p, pc + 1 = %p\n", pc, pc + 1);
  16. float f;
  17. float *pf = &f;
  18. printf("pf = %p, pf + 1 = %p\n", pf, pf + 1);
  19. double d;
  20. double *pd = &d;
  21. printf("pd = %p, pd + 1 = %p\n", pd, pd + 1);
  22. return 0;
  23. }

6 const的使用

6.1 问题

定义const的普通变量和const指针的三种方式,验证一下效果。

6.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:const的使用

代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i1=5;
  5. const int i2 = 10;
  6. //i2 = 6;
  7. //i2++;
  8. i1 = i2;
  9. i1 = 100;
  10. printf("i2=%d\n",i2);
  11. const int *p1 = &i2;
  12. //*p1 = 200;
  13. p1 = &i1;
  14. int * const p2 = &i2;
  15. *p2 = 200;
  16. //p2 = &i1;
  17. printf("i2=%d\n",i2);
  18. return 0;
  19. }

上述代码中,以下代码:

  1. int i1=5;

定义了一个整型变量i1,并初始化为5。

上述代码中,以下代码:

  1. const int i2 = 10;

定义了一个const整型变量i2,并初始化为10。const是一个C语言的关键字,它限定变量i2不允许被改变,如以下代码:

  1. //i2 = 6;
  2. //i2++;

是错误的,如果不注释,将报编译错误。但以下代码:

  1. i1 = i2;
  2. i1 = 100;

是正确的,因为变量i1未被const关键字修饰。

上述代码中,以下代码:

  1. const int *p1 = &i2;

使用关键字const修饰了一个整型指针变量。由于关键字const在*号的左边,所以此时限定不能改变的是指针p1指向的地址的值,如以下语句:

  1. //*p1 = 200;

是错误的,因为*p1代表指针p1指向的地址的值。但以下代码:

  1. p1 = &i1;

是正确的。因为关键字const在*号的左边并未限定指针p1本身不能改变。

上述代码中,以下代码:

  1. int * const p2 = &i2;

同样使用关键字const修饰了一个整型指针变量。但由于关键字const在*号的右边,所以此时限定不能改变的是指针p1本身的值,如以下语句:

  1. *p2 = 200;

是正确的。因为关键字const在*号的右边并未限定指针p1指向的地址的值。但以下代码:

  1. //p2 = &i1;

是错误的,由于关键字const在*号的右边,所以此时指针p1本身的值不能改变。

6.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i1=5;
  5. const int i2 = 10;
  6. //i2 = 6;
  7. //i2++;
  8. i1 = i2;
  9. i1 = 100;
  10. printf("i2=%d\n",i2);
  11. const int *p1 = &i2;
  12. //*p1 = 200;
  13. p1 = &i1;
  14. int * const p2 = &i2;
  15. *p2 = 200;
  16. //p2 = &i1;
  17. printf("i2=%d\n",i2);
  18. return 0;
  19. }

7 指针和数组

7.1 问题

定义一个数组,然后赋值给指针,然后互相用对方的方式进行操作。

7.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:指针和数组

代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int arr[5] = {10, 20, 30, 4, 5};
  5. int *po = arr;
  6. for(int i = 0; i < 5; i++)
  7. {
  8. printf("arr=%d\n",*(arr+i));
  9. printf("po=%d\n",*(po+i));
  10. printf("arr[i]=%d\n",i[arr]);//*(arr+i)
  11. }
  12. printf("*po=%d\n",*po++);
  13. printf("*po=%d\n",(*po)++);
  14. printf("%d\n",*po);
  15. po++;
  16. printf("*po=%d\n",*po);
  17. //arr = arr+1;//arr++;
  18. //printf("*arr=%d\n",*arr);
  19. return 0;
  20. }

上述代码中,以下代码:

  1. int arr[5] = {10, 20, 30, 4, 5};

定义了一个整型数组arr,数组中有5个元素,并对数组进行了初始化。

上述代码中,以下代码:

  1. int *po = arr;

定义了一个整型指针变量po,并初始化为数组名arr,这种赋值是合法的,因为数组名就是数组第一个元素arr[0]的地址。

上述代码中,以下代码:

  1. printf("arr=%d\n",*(arr+i));

数组名arr是数组第一个元素arr[0]的地址。当i为0时,*(arr+i)等效于*arr,即数组第一个元素arr[0]。当i为1时,arr+1是数组第二个元素arr[1]的地址,*(arr+i)即数组第二个元素arr[1]。依次类推。

上述代码中,以下代码:

  1. printf("po=%d\n",*(po+i));

使用函数printf输出指针po+i指向的地址的值,当i为0时,指针po+0就是数组名arr的值,而arr又是数组第一个元素arr[0]的地址,所以*(po+0)就是arr[0]。当i为1时,指针po+1就是数组名arr+1的值,而arr+1又是数组第二个元素arr[1]的地址,所以*(po+1)就是arr[1]。依次类推。

上述代码中,以下代码:

  1. printf("arr[i]=%d\n",i[arr]);

i[arr]是一种不推荐使用的方法。i[arr]与arr[i]是等价的,在编译时分别被编译成*(i+arr)和*(arr+i),而它们是一回事。

上述代码中,以下代码:

  1. printf("*po=%d\n",*po++);

由于*po++左右有两个运算符*和++,它们是同优先级的,结合性是自右向左,所以先计算++,但又由于++是后置,所以该语句等效于以下语句:

  1. printf("*po=%d\n",*po);
  2. po = po + 1;

即输出为*po=10;

上述代码中,以下代码:

  1. printf("*po=%d\n",(*po)++);

同样是因为++是后置的,所以该语句等效于以下语句:

  1. printf("*po=%d\n",*po);
  2. *po = *po + 1;

即输出为*po=20;不是10的原因是上次等效时,进行了po = po + 1运算。

上述代码中,以下代码:

  1. printf("%d\n",*po);

输出为*po=21,是因为上次等效时,进行了*po = *po + 1运算。

上述代码中,以下代码:

  1. po++;
  2. printf("*po=%d\n",*po);

输出为*po=30,因为po++再次改变了po的值。

上述代码中,以下代码:

  1. //arr = arr+1;//arr++;
  2. //printf("*arr=%d\n",*arr);

为错误的。因为数组名是一个常量,虽然它是数组第一个元素arr[0]的地址,但它不能改变。

7.3 完整代码

本案例的完整代码如下所示:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int arr[5] = {10, 20, 30, 4, 5};
  5. int *po = arr;
  6. for(int i = 0; i < 5; i++)
  7. {
  8. printf("arr=%d\n",*(arr+i));
  9. printf("po=%d\n",*(po+i));
  10. printf("arr[i]=%d\n",i[arr]);//*(arr+i)
  11. }
  12. printf("*po=%d\n",*po++);
  13. printf("*po=%d\n",(*po)++);
  14. printf("%d\n",*po);
  15. po++;
  16. printf("*po=%d\n",*po);
  17. //arr = arr+1;//arr++;
  18. //printf("*arr=%d\n",*arr);
  19. return 0;
  20. }
时间: 2024-11-10 01:22:41

C语言05指针基础的相关文章

C语言之指针基础概念

开通博客园以来第一次写随笔,就写一下关于C语言指针的一些感想吧. 很多同学都搞不懂指针,我一开始也云里雾里没看懂指针,而且老师又把指针说得很难的样子.其实主要是把指针”*“的作用给弄混了,不用畏惧,细心点看就可以了. 首先简介一下指针的概念好了.指针本身也是一个变量,只不过这个变量的值比较特殊,它不是常规的整型数或者浮点数,而是指向另一个变量地址的值.通过指针的值可以知道另一个变量的地址以及存在该地址中的具体数值(该数值可以是整型,浮点型,结构体,甚至也可以是一个指针),通过指针得到另一个变量的

C语言--&gt;(十)指针基础

知识点: 1.指针基础 2.指针和函数(地址传递) ======================================= 指针是C中的一个重要的概念,也是C的一个重要特色.掌握指针的应用,可以使程序简洁.紧凑.高效. 指针的概念比较复杂,使用也比较灵活,因此初学时会常出错,我们要理解每一个概念的本质,多加练习,在实践中掌握它. 程序使用指针和没有没有使用指针的代码是两个档次. ========================================指针基础 [地址概念] 1.生

awk程序设计语言之-awk基础

awk程序设计语言之-awk基础 1 http://man.linuxde.net/ 2 7 8 常用工具命令之awk命令 9 awk是一种编程语言,用于在Linux/Unix下对文本和数据处理.数据可以来自标准输入(stdin).一个或多个文件,或其他命令的输出.它支持用户自定义函数和动态正则表达式 10 等先进功能,是Linux/unix下的一个强大编程工具.它在命令行中使用,但更多是作为脚本来使用,awk有很多内建功能,比如数组.函数等,这是它和c语言的相同之处,灵活性 11 是awk最大

黑 马 程 序 员_视频学习总结&lt;C语言&gt;----05 结构体

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.什么是结构体 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名.年龄.身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型.为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的. 二.结构体的定义 结构体内部的元素,也就是

c语言中指针悬空

Windows编程基础 创建一个Win32应用程序Ex_SDK,在程序中构造一个编辑框控件和一个按钮.编辑框用于输入一元二次方程的系数,各系数之间用逗号分隔,当单击"计算"按钮,获取方程系数,然后将求得的根通过TextOut显示在窗口客户区中. 实验准备和说明 (1)具备知识:简单的SDK编程基础. (2)准备本次上机所需要的程序. (3)创建本次实验工作文件夹"-\网络编程实验\实验1" 实验内容和步骤 1.启动Visual C++ 6.0 打开计算机,启动Vis

C#委托与C语言函数指针及函数指针数组

C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用的时候通过指针访问这个函数. 在C语言中函数指针的申明如下: //可以理解为申明一个指着变量 Func ,它的类型是 返回Type(可以为 void )类型的参数,接收 (Type one,Type two,...)类型的//参数(可以不接受参数). Type *Func(Type one,Type

20_Shell语言———VIM编辑器基础知识三之窗口属性定制、配置文件及查找替换功能

Vim编辑器可以让用户按照需求来定制一些使用属性. 一.窗口属性定义 1)显示行号 行号不是内容,只是用来帮助用户确认文本所在的行.在vim编辑器中,如果要显示行号,可以在末行模式下输入: set number 如果想关闭,则可以在功能名称前面加上no,即: set nonumber 命令可以被简写,如set number 可以简写为 set nu:set nonumber 可以简写为 set nonu. 注意,上述设定仅对当前vim的进程有效,一旦当前进程关闭,这些设定就会失效,如果要使设定永

C语言的指针变量

C语言的指针变量 在C语言中,变量是固定范围的存储空间,它存储的是赋给他的值, 比如: int a = 12; /* 这里是定义一个整型变量a,并把12这个值存储在a的地址空间上 这个地址空间是系统随机分配的,对用户是透明的不用关心 */ 指针变量存储的是变量的地址, 比如: int a = 12 , *b; b = &a; /*如上,定义了一个整型变量a并赋值12,一个整型指针变量b 然后 用 & 取值运算符 取到变量a的地址空间值,存储到指针变量b中 此时变量b中存储的是变量a中的地址

Boost智能指针-基础篇

简介 内存管理一直是 C++ 一个比较繁琐的问题,而智能指针却可以很好的解决这个问题,在初始化时就已经预定了删除,排解了后顾之忧.1998年修订的第一版C++标准只提供了一种智能指针:std::auto_ptr(现以废弃),它基本上就像是个普通的指针:通过地址来访问一个动态分配的对象.std::auto_ptr之所以被看作是智能指针,是因为它会在析构的时候调用delete操作符来自动释放所包含的对象.当然这要求在初始化的时候,传给它一个由new操作符返回的对象的地址.既然std::auto_pt