美文网首页
复习指针

复习指针

作者: 无刻 | 来源:发表于2015-10-17 14:07 被阅读0次

一、指针基础

int c = 0;为例
变量三要素:变量名c0,和其在内存中的地址

指针即地址值

指针变量为专门存放指针(某个变量的地址)的变量
或:指针变量的值为另一个变量的地址。

指针的大小一般为4字节(sizeof(指针变量) == 4),64位编译器中则为8。

定义一个指针变量:int *pointer;
其中

  1. int 说明了指针变量的基类型
  2. * 为指针运算符,说明pointer的类型为指针
  3. pointer 为指针变量名

基类型:指针变量指向的变量的类型

int c = 76;    
int *pointer;    //定义名字为pointer的指针变量
pointer = &c;    //将变量c的地址赋值给指针变量pointer,称指针变量pointer指向了变量c

int *p1 = NULL指针变量赋初值,使之成为空指针。

& *运算符的优先级

从高到低分别为:

  • 后置++ --
  • 前置++ --, ! * &
  • 算数运算符
  • 关系运算符<= < >= > == !=
  • && ||
  • 赋值运算符=
    注意:(*pointer)++不等于*pointer++
    前者指*pointer的值加1,后者指*pointer使用后,地址加一,即指向下一个地址单位的存储的变量,具体加几个字节由pointer的基类型决定。

二、指针与数组

1.指针指向数组元素时与指向普通变量没有区别

2.与数组

int a[5] = {10, 11, 12, 13, 14};
cout<< a<<endl;      //0017F754
cout<<*a<<endl;      //10
cout<<&a[0]<<endl;   //0017F754
cout<<a[0];          //10

可以看出:
数组名代表数组首元素的地址,数组名相当于 (并不是)指向数组首元素的指针。因此,数组名不是变量,不能给数组名赋值。

若定义:数组int a[10], 指针int *pointer;
pointer = a;等价于pointer = *a[0];
数组访问:

  • pointer + i;等价于a + i;等价于&a[i];
  • *(pointer + i);等价于*(a+i);等价于a[i];

表示形式:pointer[i];等价于*(pointer + i);

注意:

  • a++是没有意义的,但是p++会引起p的变化
  • p可以指向数组之外的元素
  • 因此,指针做加减运算时一定注意有效范围

3.与二维数组

例:输入i, j,输出a[i][j]

int a[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23};
int (*p)[4], i, j;      //p指向一个“包含4个int型元素的一维数组”
p = a;
cin >> i >> j;
cout << setw(4) << *(*(p + i) + j);

因为p指向一个“包含4个int型元素的一维数组”
所以*(p + i)指向第i + 1个“包含4个int型元素的一维数组”
p + i等价于&a[i]
*(p + i)等价于a[i],即指向第i行
*(p + i) + j等价于a[i] + j,即指向第j列
** *(*(p + i) + j)便等价于a[i][j]**
根据c语言的规范,此处直接写p[i][j]也可以

三、指针与字符串

指向字符串的指针:
char a[10]; char *p; p = a;
字符串与数组的区别:字符串末尾一定为\0
字符串为双引号包含:"hello",系统会自动补\0。数组为大括号内{'h', 'e', 'l', 'l', 'l', '\0'}(不加\0的话就没有)。

与整形数组的区别:
打印指向字符串数组的指针,会打印整个字符串,而不是地址。
打印指向整形数组的指针,则会打印地址。

int a[5] = {1, 2, 3};
int *pa = a;
char b[6] = {'h', 'e', 'l', 'l', 'l', '\0'};
char *pb = b;
                    //同样是打印数组名或者指针
cout<<a<<endl;      //整形数组打印a的地址值
cout<<pa<<endl;     //打印a的地址值

cout<<b<<endl;      //字符串打印内容hello
cout<<pb<<endl;     //打印hello
char buffer[10] = "ABC";
char *pc;
pc = "hello";
cout<<pc<<endl;  //打印hello
pc++;
cout<<pc<<endl;  //打印ello
cout<<*pc<<endl;  //打印e
pc = buffer;    //实际是把buffer[]的首地址赋给了pc,因此pc也指向了这个字符串
cout<<pc;  //打印ABC

四、指向二维数组的指针

1.再谈指向一维数组的指针

p -> a[0]
则++p -> a[1]
基类型起作用

根据c语言规范,一个数组名,当它不作为&,sizeof,Alignof的操作数时,可以看作是指向数组首的指针变量。

a是一个数组名,则a可以看作指向首元素的指针,其基类型为a数组的类型。&a则是指向整个数组地址值,可以看作指向整个数组的指针,其基类型为大小、类型与a相同的数组。&a相当于把a的管辖范围上升了一级,从首元素的地址上升到了整个数组的地址。*a则可以把管辖范围下降一级,从首元素的地址下降到首元素的值。因此*(&a)相当于,先上升,再下降,最后结果即为:a。因此cout<<*(&a)打印的结果与cout<<a相同,都打印数组a首元素的地址值。

2.指向二维数组的指针

int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

二位数组a[3][4]包含三个元素:a[0],a[1],a[2],每一个元素都是包含四个整形元素的一维数组。
按级别:

名称 级别 含义
&a 最高 指向整个二维数组的指针
a 指向a[0]即第一个一维数组的指针
a[0] 指向第一个一维数组中第一个元素的指针
a[0][0] 最低 第一个一维数组中第一个元素的值

同时可以使用&*运算符对他们进行级别的提升和下降;

三条规律

  • 数组名相当于指向数组第一个元素的指针
  • &可以提升一个级别
  • *可以下降一个级别

五、指针与函数

1.指针做函数的参数

可以将数组名作为实参传递给函数的指针形参
多维数组名作函数实参

int maxvalue( int (*p)[4]);    //p[i][j]即可访问数组a内的内容
main函数里:
int a[3][4];

数组名也可以直接做形参。C++编译器会将形参数组名作为指针变量来处理。
int sum(int arr[][4]);int sum((*arr)[4]);等效。前者:arr[]是形参,会被解释为arr指针变量,[4]说明arr指向的是有4个int型元素的数组。

int sum(int array[], int n);    //合法,array被当作了指针变量这样能够改动main函数里变量的值,可能会导致未知的危险
int sum(const int array[], int n);  //合法,且函数内*array的值不能被更改

指向符号常量的指针const int *p。不能通过*p = 20来赋值,或者其他方式修改指向的内容,即使它指向的变量不是常量。

2.指针做函数的返回值

int *function(int x, int y);
注意,应返回全局变量或静态局部变量的地址,否则子函数结束后,内存被释放,这个地址就没有意义了

静态局部变量

在子函数中定义,定义方式为static int value1 = 10。函数执行完毕后,内存被释放,但是这个静态局部变量不会被释放,因此仍然可以被使用。假设函数执行完毕后value1 == 20;,下一次执行此函数时,虽然按理又要执行定义语句static int value1 = 10使value1变成10,实际value1的值仍未20,并不会被再次初始化
虽然子函数会被调用多次,但是静态局部变量的定义语句只会执行一次。

六、练习

1.计算矩阵边缘元素之和

输入:

1    //数据组数
4 4    //矩阵行数、列数
1 1 1 1
0 0 0 0
1 0 1 0
0 0 0 0
3 3
3 4 1
3 7 1
2 0 1

输出:

5
15

代码:

#include<stdio.h>
#include<iostream>

using namespace std;

int answer;

int compute()
{
    int m, n;
    cin >> m >> n;
    int answer = 0;
    for(int i = 0; i < m; ++i)
    {
        int *p = new int[n];
        for(int x = 0; x < n; ++x)cin>>*(p + x);
        if(i == 0 || i == m - 1)
        for(int j = 0; j < n; ++j)
        {
            answer += *(p + j);
        }
        else
        {
            answer = answer + *p + *(p + n - 1);
        }
    }
    return answer;
}

int main()
{
    int k = 0;
    cin >> k;
    int *p = new int[k];
    for(int i = 0; i < k; ++i)
    {
        *(p + i) = compute();
    }
    for(int i = 0; i < k; ++i)
    {
        cout<<*(p + i)<<endl;
    }
    return 0;
}

2.二维数组右上左下遍历

输入:

3 4    //矩阵行数列数
1 2 4 7
3 5 8 10
6 9 11 12

输出:

1
2
3
4
5
6
7
8
9
10
11
12

代码:

#include<stdio.h>
#include<iostream>

using namespace std;

int main()
{
    int row, col;
    cin>>row>>col;                      //row == 3, col == 4
    int *p = new int[col * row];
    for(int i = 0; i < row; ++i)
    {
        for(int j = 0; j < col; ++j)
        cin>>*(p + i * col + j);
    }
    for(int j = 0; j < col; ++j)
    {
        cout<<*(p + j)<<endl;
        for(int i = 1, k = j - 1; k >= 0 && i < row; --k, ++i)
        cout<<*(p + i * col + k)<<endl;
    }
    for(int i = 1; i <= row - 1; ++i)
    {
        cout<<*(p + i * col + col -1)<<endl;
        for(int j = col - 2, k = i + 1;j >= 0 && k < row;++k, --j)
        cout<<*(p + k * col + j)<<endl;
    }
    
    return 0;
}

3.文字排版

输入:

84  //单词数
One sweltering day, I was scooping ice cream into cones and told my four children they could "buy" a cone from me for a hug. Almost immediately, the kids lined up to make their purchases. The three youngest each gave me a quick hug, grabbed their cones and raced back outside. But when my teenage son at the end of the line finally got his turn to "buy" his ice cream, he gave me two hugs. "Keep the changes," he said with a smile. 

输出:

One sweltering day, I was scooping ice cream into cones and told my four
children they could "buy" a cone from me for a hug. Almost immediately, the kids
lined up to make their purchases. The three youngest each gave me a quick hug,
grabbed their cones and raced back outside. But when my teenage son at the end
of the line finally got his turn to "buy" his ice cream, he gave me two hugs.
"Keep the changes," he said with a smile.

代码:

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>

using namespace std;

int lengthOfstr(char *str)
{
    return strlen(str);
}

int main()
{
    char str[50];
    int num, lengthOfLine = 0;
    cin>>num;
    for(int i = 0; i < num; ++i)
    {
        cin>>str;
        if(i == 0)          //全文第一个单词 
        {
            cout<<str;
            lengthOfLine += strlen(str); 
        }
        else if(lengthOfLine + 1 + strlen(str) <= 80)   //不是第一个单词且输出这一个单词后行字符数没超过80 
        { 
            cout<<" "<<str;
            lengthOfLine = lengthOfLine + 1 + strlen(str); 
        }
        else if(lengthOfLine + 1 + strlen(str) > 80)    //不是第一个单词且输出这一个单词后行字符数将超过80
        {
            cout<<endl<<str;
            lengthOfLine = strlen(str); 
        }   
    }
    return 0;
}

相关文章

  • 复习指针

    一、指针基础 以int c = 0;为例变量三要素:变量名c,值0,和其在内存中的地址。 指针即地址值 指针变量为...

  • 10 重忆C之 指针、内存、位运算

    指针(复习) 指针(pointer) 或 指针变量(pointer variable)。是“储存地址的变量”。它存...

  • 02_C++笔记_函数

    复习数组和指针的关系: 结果如下: 数组和指针作为参数传递: 进一步改进: const和指针, 指针指向指针: 函...

  • 嵌入式学习笔记之用C语言点亮一个LED

    硬件连接请查看前一篇文章 目录 C指针复习 写C程序 汇编编写启动程序 1.C指针复习 ​ int *...

  • 2017年9月23日 学习总结1

    今天重点复习指针,指针与数组的关系。 对结构体指针的使用需要再进一步理解。

  • Ios面试复习-- 指针

    1.指针的长度 和 类型 二维数组的指针强转

  • Runtime笔记三:Runtime发送消息的流程

    我们调用方法的时候,其实就是在发送消息,那这个消息发送的流程是什么样子的呢。 复习isa指针 首先,复习isa指针...

  • lc25 关于链表

    复习知识点:1)链表反转2)关于指针。理解C++中指针传参,大概指针传参也是传的形参(like int数字),但是...

  • 2018-05-24

    基础不够扎实,听的懂做不出来 函数指针复习 行指针 指针数组 新知识 函数声明 函数定义 函数调用 函数名相同,型...

  • 2020-04-14长光工程师学习日记

    今天继续学习了指针的内容 指针的难度教之前学习的内容难度有所上升,今天主要的内容就是对指针问题的继续学习与复习。 ...

网友评论

      本文标题:复习指针

      本文链接:https://www.haomeiwen.com/subject/jnkacttx.html