L1D7 C语言指针(二)

C语言指针(二)

承接上文C语言指针(一),链接为:C语言指针(一)

一、多级指针

1.1 多级指针的定义及应用

把一个指向指针的变量称为多级指针变量,常用二级指针,其实二级指针都用的不太多。
二级指针变量说明形式:<存储类型> <数据类型> **<指针名> 例如: char **q;
示例程序如下:

#include <stdio.h>
int main(int argc , char **argv)
{
    int m  = 100;
    int *p = &m;
    int **q = &p;
    printf("m = %d  &m = %p p = %p &p = %p\n q = %p &q = %p *q = %p \
    **q = %d\n", m , &m , p , &p , q, &q , *q , **q);
    
    return 0;
}

在这里插入图片描述

在这里插入图片描述

1.2 多级指针的运算

多级指针运算也是以其目标变量为单位进行偏移,比如int* p ,p+1是移动一个int变量占用的内存空间,int **p , p+1就是移动一个int *变量占用的内存空间 , int ***p , p+1就是移动一个int **所占的内存空间。代码演示如下:

#include <stdio.h>
int main(int argc , char **argv)
{
    int m  = 100;
    int *p = &m;
    int **q = &p;
    printf("q = %p  &q = %p  *q = %p **q = %d\n" , q , &q , *q , **q);
    printf("q+1 = %p sizeof(q) = %ld\n" ,q+1 , sizeof(q));
    
    return 0;
}

在这里插入图片描述
可以看出q+1比q大了8个字节,多级指针+1,就是移动一个指针变量,不管是几级指针,都是存储内存编号(地址),在64位机器上,占8字节,因此多级变量指针本身也是占用8字节,所以多级指针偏移以8字节为单位。

二、指针数组

2.1 指针数组的定义及初始化

指针数组的定义:
指针数组是指由若干个指针构成的集合,指针数组一般形式为:<存储类型> <数据类型> *<指针数组名>[<大小>],例如:int p[2]
缘由是[]优先级比
高,p先和[]结合形成数组,然后数组的每个元素都是指针变量。指针数组名就是指针数组的储存首地址,即指针数组名为数组的指针。

指针数组的初始化:
声明一个指针数组: double * pa[2] ,a[2][3];
把一维数组a[0]和a[1]的首地址分别赋予指针变量数组的数组元数pa[0]和pa[1]:
pa[0]=a[0] ; // 等价pa[0] = &a[0][0];
pa[1]=a[1]; // 等价pa[1] = &a[1][0];
此时pa[0]指向了一维数组a[0]的第一个元素a[0][0], 而pa[1]指向了一维数组a[1]的第一个元素a[1][0]。,如下图所示:

在这里插入图片描述

三、void指针和const修饰符

3.1 void指针的用法

概念:void指针是一种不确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量
一般形式:void * <指针变量名称> ;
对于void指针,在没有强制类型转换之前,不能进行任何指针的算术运算。如下程序所示:(printf里,如果不做转换,由于void的p读取字节不定,没法取值。)

#include <stdio.h>

int main(int argc, char const *argv[])
{
    void *p;
    int a = 10;
    p = (void *)&a;
    printf("%d\n", *(int *)p);   //如果不做转换,由于void的p读取字节不定,没法取值
    return 0;
}

在这里插入图片描述

3.2 const与指针

在C语言中,关键字const修饰变量,可以使得变量常量化。const修饰基本简单类型(非指针)时,很容易理解,就是变量的值不允许被修改,下面两种写法均可:

const int m = 10;
int const m = 10;

若要用const修饰指针,由于const放置的位置不同,修饰的内容也不同,主要是如下三种情况:
1、常量化指针目标表达式
一般说明形式:const <数据类型> * <指针变量名称>[= <指针运算表达式>] ;
例如:int m = 100 ;const int p = &m; //此时p的值不可被修改,但是p指向的位置可以移动。如下演示:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int m = 100;
    const int *p = &m;
    *p = 101;
    return 0;
}

在这里插入图片描述

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int m = 100;
    const int *p = &m;
    //*p = 101;
    p++;
    return 0;
}

在这里插入图片描述
2、常量化指针变量
一般说明形式为:<数据类型> * const <指针变量名称>[= <指针运算表达式>] ;
例如:int * const m = 100 ;//此时,指向的目标值可以变,但是指针地址不可变,意思是指针不能移动,示例如下:

/*可修改目标值*/
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int m = 100;
    int* const p = &m;
    *p = 101;
    return 0;
}
/*不可修改指针地址,否则编译报错,提示地址是只读的*/
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int m = 100;
    int* const p = &m;
    //*p = 101;
    p++;
    return 0;
}

在这里插入图片描述

3、常量化指针变量及其目标表达式

一般说明形式如下: const <数据类型> * const <指针变量名> = <指针运算表达式> ;
常量化指针变量及其目标表达式,使得既不可以修改<指针变量>的地址,也不可以通过*<指针变量名称>修改指针所指向变量的值

const总结:左值右指
const出现在左边,代表值不可修改(指针指向的目标不可修改),const在右边,代表指针(地址)不可修改。左右都有const,代表值和指针地址都不可修改。

四、字符指针与字符串

4.1 字符指针概念

字符指针就是存储字符变量的地址,在C语言中没有字符串这个数据类型,通常用字符数组存储字符串。字符指针可以存储字符串的起始地址,即指针指向字符串的第一个字符。通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。

4.2 字符指针初始化

初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针中。

char  str[] = “Hello World”;  		
char  *p = str;

在C当中,如果直接把一个字符串给一个指针的话,会变成字符串常量,是不能被修改的。
如:char *p = “hello world”; *p = ‘h’这个是不行的(很重要),这样写相当于const char *p = “hello world”;
如果使用 char str[] = “hello world”; char *p = str;这样指针就是指向字符串的首地址。

4.3 字符串

字符串操作演示代码(把字符串进行大小写转换,大写字母变为小写,小写字母变为大写):

/*
 * @Description: 
 * @Author: 余红祥
 * @Date: 2022-07-03 18:21:18
 * @LastEditTime: 2022-07-03 18:21:21
 * @LastEditors:  
 */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char *argv[])
{
	char str[] = "Ation";
	char *p = str;
	for(int i = 0;i<strlen(str);i++)
	{
		if(isalpha(*p))
			{
				if(isupper(*p))
				{
					*p = tolower(*p);   //大写变小写
				}
				else
				{
					*p = toupper(*p);   //小写变大写
				}
		}
		p++;
	}
	p = str;
	printf("%s %s\n",str,p);
	return 0;
}

在这里插入图片描述

4.4 字符指针数组

若数组中存储若干个字符串的地址,则该数组叫做字符指针数组。形式:char *a[3];
示例程序如下:

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

int main(int argc, char const *argv[])
{
    char s1[] = "welcome";
    char s2[] = "to";
    char s3[] = "jiangxi";

    char *a1[3] = {s1, s2, s3};
    char *a2[3] = {"welcome", "to" , "jiangxi"};
    char **p = a1;
    int i = 0;
    printf("array1:%s %s %s\n", a1[0], a1[1], a1[2]);

    for (i = 0; i < sizeof(a1)/sizeof(char *); i++)
        printf("%s ", *(p+i));
    printf("\n");
    
    p = a2;
    printf("array2:%s %s %s\n", a2[0] , a2[1] , a2[2]);
    for (i = 0; i < sizeof(a2)/sizeof(char *); i++)
        printf("%s ", *(p+i));
    printf("\n");

    return 0;
}

在这里插入图片描述

四、综合练习

1、不使用strcat连接函数,用指针编程实现字符串连接功能。

#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char *argv[])
{
	char dest[256] = "attion";
    char src[256] = "please";
    char *p = dest;
    char *q = src;
    int qlen = strlen(q);
    int plen = strlen(dest);
    while (*q != '\0')
    {
        for (int i = 0; i < qlen; i++)
        {
            *(p+plen) = *q;
            p++;
            q++;
        }
    }
    printf("dest: %s\nsrc: %s\n", dest, src);
	return 0;
}

在这里插入图片描述
2、用指针编程实现字符串反转功能。

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
	char string[100] = "please";
    char *p = string;
    char *q = string + strlen(string) -1;
    char temp = 0;
    while (p < q)
    {
        temp = *q;
        *q = *p;
        *p =temp;
        p++;
        q--;
    }
    printf("string: %s\n", string);
}

在这里插入图片描述
3、利用指针数组处理一个二维数组,要求求出二维数组所有元素的和
答:

#include<stdio.h>

int main(int argc, char *argv[])
{
	int a[2][3] = {0};
	int *p[2] = {a[0],a[1]};
	int i = 0 ,j = 0;
	int sum = 0;
	for(i = 0;i<2; i++)
	{
		for(j = 0;j < 3;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	for(i = 0; i < 2 ; i++ )
	{
		for(j = 0; j < 3 ; j++)
		{
			printf("%d ",a[i][j]);
			sum += *(p[i]+j);
		}
		putchar('\n');
	}
	printf("%d\n",sum);
	return 0;
}

在这里插入图片描述
4、用指针写出strcmp函数
答:

#include <stdio.h>
int main(int argc,char *argv[])
{
	char str1[100];
	char str2[100];
	char *p = str1;
	char *q = str2;
	char temp;
	puts("please input the first str:");
	gets(p);
	puts("please input the second str:");
	gets(q);
	while(*p == *q)
	{
		if(*p == '\0')
			break;
		p++;
		q++;
	}
	temp = *q - *p;
	printf("the cmp return val is %d\n",temp);
	return 0;
}

在这里插入图片描述
5、利用指针实现strncmp函数功能
答:

#include <stdio.h>

int my_strncmp(char *p,char *q,int n);

int main(int argc,char *argv[])
{
	char str1[100];
	char str2[100];
	char *p = str1;
	char *q = str2;
	char temp = 0;
	//char test = 0;
	puts("please input the first str:");
	gets(p);
	puts("please input the second str:");
	gets(q);
	//temp = strncmp(p,q,5);    //用于测试
	temp = my_strncmp(p,q,5);	//比较前5个字符
	printf("the cmp return val is %d\n",temp);
	return 0;
}
//比较两个字符串的前n个字符
int my_strncmp(char *p, char *q, int n)
{
	int i = 0;
	for(i = 0;i < n-1;i++)
	{
		if(*p == *q)
		{
			if(*p == '\0')
				break;
		}
			p++;
			q++;
	}
	return *p - *q;
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值