解读:《C语言解惑》中的难解的指针

       在C语言中,指针和数组有着千丝万缕的关系,也是很核心的内容之一,同时也是最难理解的部分。在 《C语言解惑》一书中有一道关于指针的题目,作者说只要能正确地解答之,便说明已经全面地掌握了C语言中指针的用法。

让我们先看看源代码:

int main()  
{    
    char * c[] = {  
        "ENTER",  
        "NEW",  
        "POINT",  
        "FIRST"  
    };  
      
    char ** cp[] = { c + 3, c + 2, c + 1, c };  
    char *** cpp = cp;  
  
    printf("%s  \n",* * ++cpp );  
    printf("%s  \n",* -- * ++cpp + 3 );       
    printf("%s \n",* cpp[ -2 ] + 3 );  
    printf("%s  \n", cpp[ -1 ][ -1 ] +1 );  
  
    int i;  
    scanf("%d",&i);  
  
    return 0;  
}  

在看结果之前,最好能够静下心来做一做。

运行结果:



为了能够较为明了地分析,将源代码改为如下:


#include<stdio.h>  
  
char * c[] = {  
        "ENTER",  
        "NEW",  
        "POINT",  
        "FIRST"  
    };  
      
    char ** cp[] = { c + 3, c + 2, c + 1, c };  
    char *** cpp = cp;  

int main()  
{  
  
        printf( "------------START_111----------\n");  
    Printf();    //    输出一  
    printf( "------------END_111----------\n");  
      
     ++ cpp;  
       printf("  %s  \n",* *cpp );  
  
     printf( "------------START_222----------\n");  
     Printf();    //输出二  
     printf( "------------END_222----------\n");      
      
    ++cpp;  
  
     printf( "------------START_333----------\n");  
     Printf();   //输出三  
     printf( "------------END_333----------\n");  
  
     -- * cpp;  
  
       printf("  %s  \n",* * cpp + 3 );  
  
     printf( "------------START_444----------\n");  
     Printf();  //输出四  
     printf( "\n------------END_444----------\n");  
      
      
     printf("\n\ncpp[ - 2 ] = %x  ,  * cpp[ -2 ] = %x, * cpp[ -2 ] + 3 = %x\n",  
                cpp[ - 2 ],  * cpp[ -2 ], * cpp[ -2 ] + 3 );  
    printf("* cpp[ -2 ] + 3  =  %s \n",* cpp[ -2 ] + 3 );  
  
    printf("\n\ncpp[ - 1 ] = %x  ,  cpp[ -1 ][ - 1] = %x, cpp[ -1 ][ - 1] + 1 = %x\n",  
                cpp[ - 1 ],  cpp[ -1 ][ - 1], cpp[ -1 ][ - 1] + 1 );  
    printf(" cpp[ -1 ][ -1 ] +1 = %s  \n", cpp[ -1 ][ -1 ] +1 );  
    int i;  
    scanf("%d",&i);  
  
    return 0;  
}  


其中Printf函数代码如下:


void Printf()
{

	printf( "cpp =  %x;        &cpp = %x;        *cpp = %x ;\n\n",  cpp , &cpp, *cpp );

	printf( "cp =  %x;         &cp = %x;         *cp = %x; \n\n",  cp , &cp, *cp );

	printf( "cp+1 =  %x;       &cp+1 = %x;       *(cp+1) = %x; \n\n",  
		    cp + 1 ,  &cp + 1 , * ( cp + 1 ) );
	printf( "cp+2 =  %x;       &cp+2 = %x;       *(cp+2) = %x; \n\n",  
		    cp + 2 ,  &cp + 2 , * ( cp + 2 ) );
	printf( "cp+3 =  %x;       &cp+3 = %x;       *(cp+3) = %x; \n\n",  
		    cp + 3 ,  &cp + 3 , * ( cp + 3 ) );

	printf( "c =  %x;          &c = %x;          *c = %x; \n\n",  
		    c ,  &c , *c );
	printf( "c+1 =  %x;       &c+1 = %x;        *(c+1) = %x; \n\n",  
		    c + 1 ,  &c + 1 , * ( c + 1 ) );
	printf( "c+2 =  %x;       &c+2 = %x;        *(c+2) = %x; \n\n",  
		    c + 2 ,  &c + 2 , * ( c + 2 ) );
	printf( "c+3 =  %x;      &c+3 = %x;         *(c+3) = %x; \n\n",  
		    c + 3 ,  &c + 3 , * ( c + 3 ) );
	
	printf("ENTER  :  %x  :  %s  \n", c[ 0 ], c[ 0 ] );
	printf("NEW    :  %x  :  %s  \n", c[ 1 ], c[ 0 ] );
	printf("POINT  :  %x  :  %s  \n", c[ 2 ], c[ 2 ] );
	printf("FIRST  :  %x  :  %s  \n", c[ 3 ], c[ 3 ] );

}



改变为以上形式是为了清楚地看到地址。

运行结果如下图:

截图一:



截图二




截图三:




截图四:




为了对比方便,故以以上方式截图。

图的说明:

    共有四个输出位于START_111和END_111,START_222和END_222,START_333和END_333,START_444和END_444之间。为了对比方便,在截图一中的START_222和END_222间的内容与截图二中的START_222和END_222间的内容完全一样,只不过在截图时对START_222和END_222间的内容截了两次,截图二与截图三中的START_333和END_333的内容也一样。

为了更精确地说明,画如下包含地址的图:

START_111和END_111的内容如下图:





START_222和END_222的内容如下图:





START_333和END_333的内容如下图:





START_444和END_444的内容如下图:




说明:

    上面的图中,cpp表示变量名,用 int i = 0;来类比,cpp相当于i,cpp的地址78020相当于&i,而其中的内容78018(对于地址图四)相当于0;但是cp和c不同,它们都是数组名,是常量。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页