C语言提高_02

1.一级指针的典型用法     

数组int a[10];

字符串

1.c语言中以0结尾的字符串

2.在c语言中没有字符串类型,通过字符数组来模拟字符串。

3.字符串的内存分配   堆上,栈上,全局区


C语言字符数组的初始化:

1.指定长度 char buf[100]={'a','b','c','d'}   初始化一个100个字符的字符串其中buf[4]--buf[99]为0;

2.不指定长度   char buf1[] = {'a','b','c','d'}     buf1是一个数组,但是不是一个以0结尾的字符串。

3.使用字符串初始化  char buf3[] = “abcd”;  buf3作为数组的话是5个字节,末尾有个\0;如果作为字符串的话是4个字节;求字符串长度使用strlen()函数;求数据类型大小使用sizeof();

数组也是一种数据类型的。char buf4[100]=“abcd”;buf4的大小就是100字节;buf4的长度就是4个字节 ;右边是字符串常量在全局区,左边是在栈内存中申请了100字节的内存,等号是将常量字符串烤呗到栈内存中。也就是说右边不能修改,但是这时左边就可以修改了。

通过数组的下标和定义一个指针,把数组的的首地址赋值给指针,指针++,这两种方式都能遍历数组。其实数组的本质也是指针,严格意义上述数组是一个常量指针,不能被赋值。


2.指针做函数参数

int  checkstr(char *  str1,char* str2){}
上述函数中可以明显的看出传两个地址进去,对内存的操作。
一般情况下需要对这两个指针进行接收,避免指针多次赋值后,再去操作形参指针的时候出问题。
应用场景:快速开发函数工具模型,把c作为工具模型去开发使用,这种思想很重要。


3.两头堵模型


4.字符串翻转


5.递归翻转字符串
重点理解参数入栈模型和函数嵌套返回调用流程


6.一级指针易错的地方

当指针作为参数的时候,判断的是指针变量而不是指针变量所指向的空间是否为NULL。
下表越界  char a[3]  ="abc";  这是错误的,要考虑\0;
不断修改指针变量的值,最终返回的时候或者释放这个指针的时候,要注意啦。
局部内存空间用完free掉了,不能向外抛出这个内存空间的地址,可以molloc一块内存空间去返回。

要注意运算符的优先级;


7.const在c语言中的定义

例如:const int a; 和int const a;  这两个所表达的意思是一样的,a不能被修改。但是如果给a取地址,赋值给一个指针,通过指针可以修改a的值。所以在c语言中const是个冒牌货。
const char* b; 和 char* const b;这两个所表达的意思是不一样的,第一个是修饰指针变量所指向的空间不能被修改,第二个时指针不能被修改。记住指针变量和指针所指向的空间是两个不同的概念。
const char* const b;则表达的意思就是两个都不能被修改。


8.二级指针做输出的模型
做形参输出模型,在函数内部申请内存,通过二级指针形参接受外部函数定义的两个一级指针的取地址,然后将这内存地址赋值给传进来的指针,这样就可以将内部申请的内存传递出去。当内存空间使用完后记得释放,并将指针赋值为NULL。二级指针在释放的时候可以防止野指针。但是一级指针传入一个方法中去使用,完后再函数内部释放掉的话,实参的一级指针就是也指针了。这点希望注意。

9.二级指针做函数参数、做输入的模型

9.1.指针数组:数组本身就是一个指针,指针的的数组就变成了一个二级指针了。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>


void printfarr(char** arr,int a)
{
	int i = 0;
	for (i = 0; i < a; i++)
	{
		//printf("%s \n", arr[i]);
		printf("%s \n", *(arr + i));
	}
}

void paixuarr(char** arr,int a)
{
	int i = 0, j = 0;
	char* temp = NULL;
	for ( i = 0; i < a; i++)
	{
		for ( j = i; j < a; j++)
		{
			if (strcmp(arr[i], arr[j])>0)
			{
				char* temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}
}
void main()
{
	int a = 0;
	int i = 0;
	//二级指针的一种形式,数组本身就是一个指针,指针的的数组就变成了一个二级指针了。
	char* arr[] = {"aaaa","bbbb","cccc","dddd"};
	a = sizeof(arr) / sizeof(arr[0]);
	//打印
	printfarr(arr,a);
	//排序,升序;
	paixuarr(arr,a);
}


2.二维数组也是一个二级指针模型
char str[10][30] = {"aaaa","bbbb","cccc"};
这是一个字符的二维数组,10行30列;
str[0]的sizeof为30;也就是一行的大小。
str+1  就是指针调到第二行了,多维数组的本质


3.malloc申请内存的二级指针模型
    char** sarr=NULL;
    sarr=(char**)malloc(sizeof(char*)*num);

    for (int i= 0;  i < num; i++) {
        sarr[i] = (char*)malloc(30);
        sprintf(sarr[i],"%d%d%d",i+1,i+1,i+1);// 初始化内存空间
    }
上面的sarr所指向的就是一个指针数据,所指向的内存空间的数据类型为char*;
sarr[i] 就是sarr所指向的空间所存放的数据地址。


案例如下:基本操作打印、排序、二级指针做函数参数做输入。

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

void printfsarr(char** sarr,int num)
{
    if(sarr==NULL)
    {
        return ;
    }
    //打印
    for (int i = 0; i < num; ++i) {
        printf("%s\n",sarr[i]);
    }
}

void paixuarr(char** sarr,int num)
{
    if(sarr==NULL)
    {
        return ;
    }
    for (int i = 0; i < num; ++i) {
        for (int j = i+1; j < num; ++j) {
            if(strcmp(sarr[i],sarr[j])>0)
            {
                char* temp=sarr[i];
                sarr[i]=sarr[j];
                sarr[j]=temp;
            }
        }
    }
}

void freesarr(char** sarr ,int num)
{
    if(sarr==NULL)
    {
        return ;
    }
    for (int i = 0; i < num; ++i) {
        if(sarr[i]!=NULL)
        {
            free(sarr[i]);
            sarr[i]=NULL;
        }
    }
    if(sarr!=NULL)
    {
        free(sarr);
        sarr=NULL;
    }
}

void main()
{
    int num=5;
    char** sarr=NULL;
    sarr=(char**)malloc(sizeof(char*)*num);

    for (int i= 0;  i < num; i++) {
        sarr[i] = (char*)malloc(30);
        sprintf(sarr[i],"%d%d%d",i+1,i+1,i+1);// 初始化内存空间
    }
    //打印
    printfsarr(sarr,num);
    //排序  这里只是将指针所指向的内存空间做了调换。也可将内存空间的内容做调换
    paixuarr(sarr,num);
    //释放内存
    freesarr(sarr,num);
}

9.4 看看上面三种的内存模型图



10.多级指针

一般的使用场景也是多级指针做函数参数,二级指针去地址传入多级指针的函数,然后做输出
注意,传入的多级指针要做判断是否为NULL;
可以这样,不管是几级指针统一理解成,指向一块内存空间,需要判断指向的内存空间是否为NULL就可以了。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值