zoukankan      html  css  js  c++  java
  • 承诺c指针 (1)指针是地址

                             (1)是地址

    首先明白一个观点:指针就是地址。这是理解指针的起始一步。

    直观感受下。变量的地址

    int main()
    {
    	int foo;
    	int *foo_p;
    	foo = 5;
    	foo_p = &foo;
    	printf("   foo...%d
    ", foo);
    	printf("*foo_p...%d
    ", *foo_p);
    	printf("  &foo...%p
    ", &foo);
    	printf(" foo_p...%p
    ", foo_p);
    	printf("&foo_p...%p
    ", &foo_p);
    	return 0;
    }
    执行


    几点说明:

    1. %p中的p是pointer(指针)的意思。专门用于打印指针变量中的内容。
    2. 有时看到用%x打印指针的。尽管结果一样,但含义全然不同。

      %p:用合适的方式(通常是十六进制)输出指针变量中存放的还有一个变量的地址;%x:用十六进制的方式打印出变量的值。而且在我的环境中使用%x打印指针变量的话,会省略前面的0。

    指针变量的示意图

    左上角是变量名。右上角是变量地址。中间是变量存储的内容。
    能够这样来理解指针:指针是一种特殊的语言机制,它存放的是其他变量的地址,而且能够通过解引用操作符*,来获取该地址的内容。这也造成了一种指向的关系,如上图 foo_p->foo。


    高阶指针
    如二级指针:指向指针的指针。
    int main()
    {
    	int foo = 5;
    	int *foo_p = &foo;
    	int **foo_pp = &foo_p;
    	printf("     foo...%d
    ", foo);
    	printf("   &foo...%p
    ", &foo);
    	printf("  foo_p...%p
    ", foo_p);
    	printf(" &foo_p...%p
    ", &foo_p);
    	printf("  *foo_p...%d
    ", *foo_p);
    	printf(" foo_pp...%p
    ", foo_pp);
    	printf("&foo_pp...%p
    ", &foo_pp);
    	printf("*foo_pp...%p
    ", *foo_pp);
    	printf("**foo_pp...%d
    ", **foo_pp);
    	return 0;
    }
    执行

    由执行结果,画出内存示意图:

    各变量的类型推导。foo_p是指针。且指向int,故foo_p的类型是int*。也就是在'*'前加入int;foo_pp也是指针,且指向foo_p。故foo_pp的类型是int**,也就是在'*'前加入int*。
    更高阶的指针类型。以此类推。

    看看在我的环境中各基本类型分配的内存大小
    int main()
    {
    	printf("sizeof(char)...%d
    ", sizeof(char));
    	printf("sizeof(int)...%d
    ", sizeof(int));
    	printf("sizeof(float)...%d
    ", sizeof(float));
    	printf("sizeof(double)...%d
    ", sizeof(double));
    	printf("sizeof(int*)...%d
    ", sizeof(int*));
    	return 0;
    }
    执行

    在我的环境中,指针类型分配的大小是 sizeof(int*)=4;也就是说用4个字节的大小来存储变量的地址,这也是眼下大多数环境下的结果。以后讨论基于这个结果。

    至于在c标准中,没有规定指针类型的大小,详细大小依靠详细的环境。

    关于 sizeof

    首先必须指出:sizeof是操作符,而不是函数。

    被误解为函数,可能是大多数情况下。我们都这样使用它:sizeof()。事实上这样用 sizeof 类型,如sizeof int也是能够的。

    正确的使用是:假设Type是类型名。则sizeof(Type);假设Type是变量,则加不加括号,都能够。

    探讨几个问题
    (1)居然指针存放的是变量的地址,而在同一环境中地址是同种类型的整数,如4字节大小的,那为何还有指针类型的说法?
    int main()
    {
    	int foo;
    	int *int_p = &foo;
    	//在c中以下这句代码会给出警告,但可执行;而在c++中是会直接报错的
    	double *dou_p = &foo;
    	foo = 5;
    	printf("foo...%d
    ", foo);
    	printf("int_p...%p
    ", int_p);
    	printf("dou_p...%p
    ", dou_p);
    	printf("*int_p...%d
    ", *int_p);
    	printf("*int_p...%f
    ", *int_p);
    	printf("*dou_p...%d
    ", *dou_p);
    	printf("*dou_p...%f
    ", *dou_p);
    	return 0;
    }
    执行


    这个结果非常让人凌乱!

    为什么会出现这样的情况。关键在于:不同类型的变量有不同的存储方式。

    如4字节的int和相同4字节的float,所分配的空间大小一样,但能够表示的数据范围有非常大差距。详细存储方式,大家可查下。

    这就说明。在进行解引用时,必须指出相应的类型方式,才可正确获取变量值。
    指针是派生类型,它的类型依靠它所指向的对象。
    两个概念
    指针的类型、指针所指向的类型
    用实例说明:int *p;
    (i)p是指针,它的类型是 int*
    (ii)p是指针。它所指向的类型是 int
    还有一个实例:int **p;
    (i)p是指针。它的类型是 int**(二级指针,它的使用方法以后会讲到)
    (ii)p是指针,它所指向的类型是 int*
    方法非常easy:是不是指针类型,就看声明中有没有*;指针的类型就是去掉变量名后。剩下的部分;指针所指向的类型就是去掉变量名和离它近期的*。剩下的就是。
    相同提醒我们:不可忽视编译器的警告!


    (2)空指针类型:void*
    在ANSI C中提供了一种,能够接受不论什么类型的指针类型:void*(空指针类型)
    int foo = 5;
    void *p = &foo;   //这句话是不会报错的
    printf("*p...%d ", *p);   //这句话无法通过编译
    不能通过编译的原因:假设只知道变量的内存地址,但却不知道变量的类型。编译器也就不知道怎样对这段地址上的内容进行解析,也就是无法解引用。

    (3)printf()函数
    printf(格式控制,输出表);
    功能:依照规定格式输出指定数据。
    “格式控制”是用双引號括起来的格式控制转换字符串。“输出表”中的数据能够是合法的常量、变量和表达式,要与“格式控制”中的格式字符一一相应。
    几个格式输出符
    %d —— 以带符号的十进制形式输出整数
    %o —— 以无符号的八进制形式输出整数
    %x —— 以无符号的十六进制形式输出整数
    %u —— 以无符号的十进制形式输出整数
    %c —— 以字符形式输出单个字符
    %s —— 输出字符串
    %f —— 以小数点形式输出单、双精度实数
    %e —— 以标准指数形式输出单、双精度实数
    %g —— 选用输出宽度较小的格式输出实数


    专栏文件夹:


    版权声明:本文博主原创文章,转载,转载请注明出处。

  • 相关阅读:
    一个好的时间函数
    Codeforces 785E. Anton and Permutation
    Codeforces 785 D. Anton and School
    Codeforces 510 E. Fox And Dinner
    Codeforces 242 E. XOR on Segment
    Codeforces 629 E. Famil Door and Roads
    Codeforces 600E. Lomsat gelral(Dsu on tree学习)
    Codeforces 438D The Child and Sequence
    Codeforces 729E Subordinates
    【ATcoder】D
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4907541.html
Copyright © 2011-2022 走看看