C 入门 第八节 指针

void changeValue(int num1,int num2)
{
    int temp = num1;
    num1 = num2;
    num2 = temp;
}
//指针作为函数的参数进行传递,可以实现形参的改变作用到实参

void changeValue2(int *p1,int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

//字符指针作为形参
void func2(int *a,int count)
{
    for (int i = 0; i < count; i ++)
    {
        printf("%d ",*(a+i));
    }
    printf("\n");
}

int main(int argc, const char * argv[]) {
   
/*
    1. 程序运行时,系统会为税局分配内存单元,存储数据.
    2. 内存是由多个连续的内存单元组成
       内存单元用于存储数据,每个内存单元占一个字节,一个字节==八个二进制位
       内存单元地址:内存单元的编号,连续的.便于访问内存单元,就像门牌号一样.(图2)
    3. 数据如何存储(图3)
    4. 访问数据的两种方式;
       (1) 直接访问.定义变量存储数据,通过变量名访问数据/
    int a = 10;
    int b = a; //通过变量a访问内存中的数据
    
       (2) 间接访问/通过内存单元地址,访问内存中的数据,任何数值都是存储在内存中的存储单元中.
    5. 内存单元的地址被称为指针
        指针变量: 存储指针(地址)的变量
        定义一个指针变量
    int*p = NULL;
    float *q = NULL;
    char *r = NULL;
    NULL 是空指针;相当于0.NULL是给指针变量赋值的
    定义指针变量的语法
    类型修饰符 *指针变量名 = 初始值(地址)
    * 表示:定义的变量是一个指针变量,存储的内容是地址.
    类型修饰符表示:地址指向的存储单元中数据的类型(即通过地址找到的数据的类型)
    指针变量的类型:类型修饰符 *    指向某种类型数据的指针类型
    p的类型 int *    指向整型数据的指针类型
    q的类型 float *  指向浮点型数据的指针类型
    r的类型 char *   指向字符型数据的指针类型
    指针变量通常被称为指针
    p 整型指针
    q 浮点型指针
    r 字符型指针
    
    通过指针访问存储单元,必须先获取存储单元的地址
    取地址运算符 & 获取变量的地址
    输出地址 %p
    int a = 100;
    printf("变量a的存储单元地址:%p\n",&a);
    float b = 1.5;
    printf("变量b的存储单元地址:%p\n",&b);
    char c = ‘a‘;
    printf("变量c的存储单元地址:%p\n",&c);
    printf("-----------------------------\n");
//    定义指针存储地址
//    要求:指针的类型修饰符 和 指针指向的变量的类型必须一致
    int *p = &a;
//   (int *)p = &a; 指针p指向变量a的存储单元(指针p中存储的地址是变量a的存储单元地址)
    
    printf("指针p中存储的地址:%p\n",p);
    float *q = &b;// * 在定义指针的时候,只起到修饰作用,说明,我定义的是一个指针变量
    printf("指针q中存储的地址:%p\n",q);
    char *o = &c;
    printf("指针o中存储的地址:%p\n",o);
    printf("-----------------------------\n");
    
//    通过指针访问存储单元
//    访问变量的存储单元的值
    printf("%d\n",*p); // *p 获取p指向的 内存地址中的值
    
    int i = *p;    // i = a;
    float j = *q;  //j = b;
    char k = *o;   //k = c;
    
    printf("i = %d j = %.2f k = %c\n" ,i ,j ,k);
    
//使用修改数
    a = 200;
    b = 2.5;
    c = ‘b‘;
    printf("a = %d *p = %d \n",a ,*p);

// 使用指针修改
    *p = 300;
    *q = 3.5;
    *o = ‘c‘;
    
    printf("b = %.2f *q = %.2f \n",b ,*q);
 
//    & 和 * 是配套使用的,互为逆运算
//  & 获取变量存储单元地址
//  * 通过地址访问变量的存储单元

// 练习
    int x = 0;
    int y = 0;
    int *m = NULL; //指针m 指向空指针位置
    m = &x; //指针m 重新 指向变量x
    *m = 10; // *m 通过 m  存储的地址访问变量x的存储单元,读取x的值
    printf("%d ",*m);
    
    m = &y;
    *m = 20;
    printf("%d ",*m);
    
//指针的存储空间与操作系统有关
//32位操作系统中占4个字节,64位操作系统中占8个字节
    printf("%lu\n",sizeof(m));

// 区分指针中的 * 的作用
    1. 如果是在定义指针变量的时候, int *p = NULL; 这个 * 代表的是p是一个指针变量.
    2. 如果定义完成再使用*p的时候,*表示的是取出p指向的地址里面的数据.是取值运算符
 
    指针的运算
    指针只有加减运算
    定义指针时的类型决定指针移到几个字符

第一种: p + n
    表示: 从p指向的存储单元向高位偏移n个数据类型的字节数(n * 数据类型的字节数)
    p的指向没有改变

int a = 100;
    int *p = &a;
    printf("%p ",p);
    printf("%p ",p + 1);
    printf("%p \n",p + 2);
    
    //第二种: p - n
    表示: 从p指向的存储单元向低位偏移n个数据类型的字节数(n * 数据类型的字节数)
    
    第三种: p ++ 或者 ++ p
    指针向高地址移动,移动的距离是指针指向数据类型所占的字节数
    p的指向改变了

int a = 200;
    int *p = &a;
    printf("%p ",p);
    //printf("%p ",p ++);
    printf("%p ",++ p);
*/
/*
     //    1. 定义一个数组
     int a[5] = {1,2,3,4,5};
     //    2. 访问数组元素 数组名[下标]
     a[0] = 10;
     printf("%d\n",a[0]);
     //    3. 计算数组元素个数
     printf("%lu\n",sizeof(a));
     printf("%lu\n",sizeof(int));
     printf("%lu\n",sizeof(a[0]));
     printf("%lu\n",sizeof(a)/sizeof(int));
     printf("%lu\n",sizeof(a)/sizeof(a[0]));
     //    4. 数组名是常量,表示数组首元素的地址 a = &a[0]
     
     #pragma mark --------指针与数组------------
     
     指针可以指向变量,读取变量存储单元中的值
     指针可以指向数组元素,数组在内存中是一段连续的存储空间,每个元素都占有相应的存储单元.
     数组元素的指针即数组元素的地址
     
     访问数组元素可以使用数组名或者指向数组的指针
     访问数组元素的两种方式: 下标法 , 指针法
     
     1. 下标法
     
     int a[5] = {1,2,3,4,5};
     int *p = a; //数组名是常量,表示数组首元素的地址 &a[], 此时,p指向数组的第一个元素的存储单元,表示首元素地址.
     
     //   使用数组名
     
     printf("%d %d\n",a[0],a[1]);
     
     printf("%d %d\n",p[0],p[1]);
     
     
     
     // 使用指针
     for (int i = 0; i < 4; i ++)
     {
     for (int j = 0; j < 4 - i; j ++)
     {
     if (p[j] < p[j + 1])
     {
     int c = 0;
     c = a[j];
     p[j] = p[j + 1];
     p[j + 1] = c;
     }
     }
     }
     for (int i = 0; i <5; i ++)
     {
     printf("%d ",p[i]);
     
     }
     
     2. 修改指针指向,不能使用数组名,只能使用指针;
     
     printf("%d \n",*p); //指向a[0]
     
     // 修改 等价
     int b[5] = {1,2,3,4,5};
     int *q = b;
     b[1] = 20;
     q[1] = 30;
     *(q + 1) = 10;
     *(b + 1) = 20;
     for (int i = 0; i <5; i ++)
     {
     printf("%d ",b[i]);
     }
     
     指针和数组的区别
     指针和数组都可以通过下标法和指针法访问数组元素
     
     1. 指针可以修改指向
     数组名 是常量,表示首元素的地址,不能改变
     
     2. 指针的存储空间;4/8字节
     数组的存储空间: 元素个数*元素的存储空间
     
     3. sizeof (数组名) 得到的是数组的存储空间
     sizeof (指针)得到的是4/8字节,不管指针指向的存储空间存储的是哪种数据.
     char a[3] = {‘a‘,‘b‘,‘c‘};
     char *f = a;
     printf("%lu\n",sizeof(f));
     
     指针类型和数组元素类型不匹配会怎样
     
     short a[4] = {6,7,8};
     int *p = a;
     printf("%d\n",*p);
*/
#pragma mark ----------指针与字符串-----------
/*
    //    定义字符数组存储字符串,str在栈区中存放,常量字符串拷贝的副本存储在字符数组中,数组中的元素是可以改变的
    char str[] = "hello";
    char *p = str;
    //  使用指针取修改数组元素
    *p = ‘a‘;
    //使用指针放问数组元素
    for (int i = 0; i < 6; i ++)
    {
        printf("%c ",*(p+i));
    }
    printf("\n");
    //使用指针操作字符串
    printf("%s\n",p);
 
    
    定义字符指针指向字符串
    ""常量字符串 , 存储在常量区,只能访问不能修改
    定义指针指向常量区的字符串常量的首地址,指针p中只是存储地址

char *p = "hello";
 //   *p = ‘a‘;
    可以访问字符和字符串
    printf("%s\n",p);
    printf("%c\n",*p);

//总结: 指向数组的指针可以访问和修改数组元素;指向常量字符串的指针只能访问不能修改.
    
//练习 : 通过指针计算字符串长度
    char str[] = "iphone";
    char *p = str;
    int n = 0;
    while (p[n] != ‘\0‘) // *(p+n)!=‘\0‘
    {
        n ++;
    }
    printf("%d\n",n);
*/
    
#pragma mark -------------指针数组---------------
/*
//  二维数组存储 字符串 数组的数组
    char strs[3][5] = {"ios","ipad","imac"};
//  strs存储的数组元素是字符数组(字符数组中存储的是字符串,常量字符串的副本)
    printf("%s\n",strs[0]); //strs[0]第一个字符数组的首元素地址.可以访问字符数组
    strcpy(strs[0], "mac");
    printf("%s\n",strs[0]);
// 指针数组 数组中的元素都是指针
    char *strs[3] = {"iOS","iPad","iMac"};

strs本质是一维数组
    strs存储的数组元素是字符指针(字符指针指向常量字符串)
    strs[0]第一个字符指针,指向常量区的"iOS"
    strs[1]第二个字符指针,指向常量区的"iPad"
    strs[2]第三个字符指针,指向常量区的"iMac"

char *strs[3] = {"iOS","iPad","iMac"};
    printf("%s\n",*strs);
    printf("%s\n",*(strs+1));
//   修改
    strs[0] = "Symban"; //strs[0] 访问的是字符指针,指针的重新指向另一个常量字符串
    printf("%s\n",strs[0]);

*/
  //  指针与函数 指针作为函数的参数
    
    int num1 = 30;
    int num2 = 90;
    changeValue(num1, num2);
    printf("%d %d\n",num1,num2);
    changeValue2(&num1, &num2);
    printf("%d %d\n",num1,num2);

// 字符指针作为实参
//    int *p = a;
//    func1(p,5);
//    func2(p, 5);

时间: 2024-12-13 07:35:26

C 入门 第八节 指针的相关文章

delphi指针简单入门

delphi指针简单入门:         看一个指针用法的例子:     1         var     2             X,   Y:   Integer;       //   X   and   Y   整数类型     3             P:   ^Integer;           //   P   指向整数类型的指针     4         begin     5             X   :=17; //   给   X   赋值     6

网易云课堂程序设计入门--C语言第七周:指针与字符串学习笔记

====================================== 第七周:指针与字符串学习笔记 网易云课堂 程序设计入门–C语言 指针与字符串 学习笔记 ====================================== 7-1指针初步 7-1-1类型大小与取地址运算 sizeof是一个运算符 给出某个变量货类型在内存中所占据的字节数 sizeof(int); sizeif(i); double变量在内存中占据的空间是int变量的两倍 { int a; a =6; prin

Delphi 指针大全(光看不练是学不会的)

大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支持指针,在此不论.其实,Pascal语言本身也是支持指针的.从最初的Pascal发展至今的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针. 以下内容分为八部分,分别是    一.类型指针的定义    二.无类型指针的定义    三.指针的解除引用    四.取地址(指针赋

VS2010/MFC对话框:非模态对话框的创建及显示

非模态对话框的创建及显示 上一节讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换.鸡啄米会将上一讲中创建的Tip模态对话框改为非模态对话框,让大家看下效果. 非模态对话框的对话框资源和对话框类 实际上,模态对话框和非模态对话框在创建对话框资源和生成对话框类上是没有区别的,所以上一讲中创建的IDD_TIP_DIALOG对话框资源和CTipDlg类都不需要修改. 创建及显示非模态

DOM 手势和操作 (HTML)

通过基本文档对象模型 (DOM) 手势事件处理,你可以自定义使用 Windows 触摸语言(如滑动.旋转和调整大小)描述的某些基本手势的用户体验. 针对 Windows 8.1 进行的更新:  Windows 8.1 针对指针输入 API 引入了多个更新和改善措施.请参阅 Windows 8.1 的 API 更改获取详细信息. 如果你不熟悉使用 JavaScript 开发应用:  阅读这些主题来熟悉此处讨论的技术. 采用 JavaScript 创建你的第一个应用 采用 JavaScript 的应

你知道Java的四种引用类型吗

从大一自学Java已经两年了,自觉已经可以独当一面,(其实远远不足),最近一直在看书.关于java四种引用类型,我也是刚了解,特此记下! 在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用.在这四个引用类型中,只有强引用FinalReference类是包内可见,其他三种引用类型均为public,可以在应用程序中直接使用.引用类型的类结构如图所示. 1.强引用 Java中的引用,类似C语言中最难的指针.(我是C语言入门编程,指针的概念还是很深入我心.)通过引用,可以对堆中的对象进行操

Java的四种引用类型史上最详细,再也不怕面试官

Java四种引用类型 1.引用的基本概念 强引用:当我们使用new创建对象时,被创建的对象就是强引用,如Object object = new Object(),其中的object就是一个强引用了.如果一个对象具有强引用,JVM就不会去GC它,JVM宁可会报OOM来终止程序,也不回收该对象. 软引用: 如果一个对象只具备软引用,如果内存空间足够,那么JVM就不会GC它,如果内存空间不足了,就会GC该对象. 弱引用: 如果一个对象只具有弱引用,只要JVM的GC线程检测到了,就会立即回收.弱引用的生

菜鸟入门记录篇1--C语言中两种关于字符串表达的方法(数组和指针)

现需表示一个字符串“itcast”,表示方法如下所列: 方法1: char name[]="itcast";     //此时定义的是一个字符串变量,数组内包含了6个字母及‘\0’一共7个元素,储存在内存的栈里面,数组内部的字符可以随意改动: (注:内存的“栈”里面储存的是局部变量,值是可以随意更改的) name[0]='t'; printf(“%s\n”,name); 输出结果为:ttcast: 方法2: char *name="itcast";    //此时定

指针的入门和理解

/* ============================================================================ Name : TestPointer.c Author : lf Version : Copyright : Your copyright notice Description : 指针的入门和理解 一个程序载入内存时,系统会为变量和函数均分配内存,所以每个变量和函数都有其对应的内存 地址. 所以在C语言中有一个很常见的操作&就是用来取地