C语言指针问题

1.指针的变量声明中方式与易错点

C语言允许形式的自由性。即以下两种声明方式效果相同

1 int main(void)
2 {
3     int* p;
4     int *k;
5     return 0;
6 } 
 1 int main(void)  //同时声明多个指针变量   
 2 {  3 // 声明三个指针变量
4 // 每个变量分开加入* 5 int *p, *a, *b; 6 7 // 仅p为指针变量,a与b为普通变量 8 int *p, a, b; 9 return 0; 10 }

 

2.指针常量和指向常量的变量

      

1 int main(void)
2 {
3     int const *p;
4     const int *p;
5     int * const p=0;
6     return 0;
7 }

      

 

注:如果需要更加理解这个问题  需要参考一下C语言运算符的结合性

        

3  int const *p   等价于   const int *p;  指针常量,原因,根据运算符结合性, *属于双目运算符由右至左结合可以得之,*p 是一个常量能修改指针本身的值,但是不能修改其指向的值

4  const int *p;  能修改其指向的整型的值,但是不能修改指针本身的值。从变量标识符开始(即从右向左),const修饰p,表示p是常量 ,即不能修改p本身,但p指向的值可以修改。

int main(void)
{
    int const *p;
    int a = 5;
    int b = 2;
    p = &a; // 可以改变p的地址 但是不可以对*p 赋值。
    printf("&a的值向是= %d\n", *p);
    p = &b;
    printf("&b的值向是= %d\n", *p);


    int * const k =&a; // 初始化的时候就需要进行赋值
    printf("%d \n", *k);
    *k = 9;  /*可以改变指针p 指向的值*/
    printf("%d \n", *k);

}

    

3.关于指针和数组若干关系

int main(void)
{
    int a[10];
    int *p = a;

    //单独的数组名a相当于第一个元素的地址,即&a[0]

    // 单独的数组的首元素地址。

    printf("&a[0]的地址 = %p\n", &a[0]);
    printf("a的地址     = %p\n", a);
        return 0

}


 

 

       

4.关于a[0]和&a 的区别

 这里&a[0]和&a 到底有什么区别呢?a[0]是一个元素,a 是整个数组,虽然&a[0]和&a的值一样,但其意义不一样。前者是数组首元素的首地址,

而后者是数组的首地址。举个例子:湖南的省政府在长沙,而长沙的市政府也在长沙。两个政府都在长沙,但其代表的意义完全不同。这里也是同一个意思。

 

5.关于指针加 “1”的问题

      

1 int main(void)
2 {
3     int *p = (int*)5;
4     printf("%p\n",p);
5     p++;
6     printf("%p\n",p);
    
    char *q = (char*)5;
  q++;
  printf("%d", q);
7 }

              

(ps: q的结果为6)结果显示为 我们可以猜测到  指针加 “1”相当于加一个其指向的字节数。 

6.深入

int main(void)
{
    int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int *p;
    for (int i = 0; i < 10; i++)
    {
        printf("&a[%d]的地址=%p\n",i, &a[i]);
    }

    p = a;

    for (int i = 0; i < 10; i++)
    {
        printf("*(p+%d)的值 = %d--------a[%d] = %d\n",i, *(p + i),i,a[i]);
        printf("*(p+%d)的值 = %d--------a[%d] = %d\n", i, *p + i, i, a[i]);  //结果同上
    }
}

 

         

 

        

int main(void)
{
    int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("a[3]     = %d\n", a[3]);
    printf("*(a + 3) = %d\n", *(a + 3));
    printf("3[a]     = %d\n", 3[a]);
    printf("*(3 + a) = %d\n",*(3+a));
    return 0;
}

 

                    

通过这个例子我觉得大家能能猜到点什么 。OK 了 我觉得大致借个问题解决了。  放松一下来点嘻唰唰。  我caca   忘记了 还有一个 指针和数组的

附录A

分析指针,可以从变量名处起,根据运算符优先级结合,一步一步分析.

int p; //这是一个普通的整型变量

int *p; //首先从P处开始,先与*结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为int 型.所以 P是一个返回整型数据的指针

int p[3]; //首先从P处开始,先与[]结合,说明P 是一个数组,然后与int结合,说明数组里的元素是整型的,所以 P是一个由整型数据组成的数组

int *p[3]; //首先从P处开始,先与[]结合,因为其优先级比*高,所以P是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与 int结合,说明指针所指向的内容的类型是整型的,所以是一个由返回整型数据的指针所组成的数组

 

int main(void)
{
    int  *p[5];
    int a = 0;
    int b;
    int c;

    p[0] = &a;
    p[1] = &b;
    p[2] = &c;

    *p[0] = -1;
    printf("%ld,%ld\n",sizeof(p),sizeof(int * [5]) );
    printf("a = %d\n", a);

    int *k[10];
        printf("%ld,%ld\n", sizeof(k), sizeof(int *[10]));
        return 0;
}
    
int main() {
    void printf(char *name[], int n);
    char *name[] = {
        "beijing", "Tian jing", "Shanghai"
    };
    printf(name, 3);
    return 0;
}

void printf(char *name[], int n) {
    int i = 0;
    for (; i<n; i++) {
        printf("%s\n", name[i]);
    }
}

学习的过程中突然意识到,这种表达方式的意义。单纯的char [] ="Hello World";   但是你要存储多个,这个就比较有意思的了。 这种到时一个比较好的表达方式。

int (*p)[3]; //首先从P处开始,先与*结合,说明P是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P是一个指向由整型数据组成的数组的指针

int **p; //首先从 P开始,先与*结合,说明P是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与 int结合,说明该指针所指向的元素是整型数据. 所以P是一个返回指向整型数据的指针的指针

int p(int); //从P处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据.所以P是一个有整型参数且返回类型为整型的函数。

int (*p)(int,int); //从P处开始,先与指针结合,说明P是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针

#include <stdio.h>
int main()
 {int max(int,int);
  int a,b,c;
  printf("please enter a and b:");
  scanf("%d,%d",&a,&b);
  c=max(a,b);
  printf("a=%d\nb=%d\nmax=%d\n",a,b,c);
  return 0;
}

int max(int x,int y)
 {int z;
  if(x>y)  z=x;
  else     z=y;
  return(z);
 }

 

#include <stdio.h>
int main()
 {int max(int,int);
  int (*p)(int,int);                           // 定义指向函数的指针变量p
  int a,b,c;
 p=max;                                     // 使p指向max函数
  printf("please enter a and b:");
  scanf("%d,%d",&a,&b);
  c=(*p)(a,b);                                 // 通过指针变量调用max函数
  printf("a=%d\nb=%d\nmax=%d\n",a,b,c);
  return 0;
}

int max(int x,int y)                            // 定义max函数
  {int z;
   if(x>y)  z=x;
   else     z=y;
   return(z);
  }                                                               

int **p; //首先从 P开始,先与*结合,说明P是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与 int结合,说明该指针所指向的元素是整型数据. 所以P是一个返回指向整型数据的指针的指针

通过这个例子我们做出一些解释:(实例来自老谭的c语言)

    (1) 上述的函数只能指向在定义时指定类型的函数, int(*p)(int,int);表示指针变量p只能指向函数返回值为整型且有两个整数的函数。

    (2) 调用函数,其实类似于 数组将首地址付给指针变量P; p = max;

    (3) 用函数指针变量调用函数时,需要将(*p) 代替函数名即可,调用方式为 c = (*p)(a,b);

 1 #include <stdio.h>
 2 int main()
 3  {int max(int,int);
 4   int min(int,int);
 5   int add(int,int);
 6   void fun(int x,int y, int (*p)(int,int));
 7   int a=34,b=-21,n;
 8   printf("please choose 1,2 or 3:");
 9   scanf("%d",&n);
10   if (n==1) fun(a,b,max);
11   else if (n==2) fun(a,b,min);
12   else if (n==3) fun(a,b,add);
13   return 0;
14  }
15
16 void fun(int x,int y,int (*p)(int,int))
17  {int resout;
18   resout=(*p)(x,y);
19   printf("%d\n",resout);
20  }
21
22 int max(int x,int y)
23   {int z;
24    if(x>y)z=x;
25    else z=y;
26    printf("max=" );
27    return(z);
28   }
29
30 int min(int x,int y)
31 {int z;
32  if(x<y)z=x;
33  else z=y;
34  printf("min=");
35  return(z);
36 }
37
38 int add(int x,int y)
39 {int z;
40  z=x+y;
41  printf("sum=");
42  return(z);
43 }

int *(*p(int))[3]; //从 P开始,先与()结合,说明P是一个函数,然后进入()里面,与int结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P是一个参数为一个整数且返回一个指向由整型指针变量组成的数组的指针变量的函数

posted @ 2015-08-17 10:32  吉吉熊  阅读(235)  评论(0编辑  收藏  举报
.catelog-title {margin-left:0}