C语言-指针三

一. 二级指针

二级指针传参:在函数传参时:char *str[ ]char **str是等价的,类型兼容的

数组名在进行传参时都会降级为指针,故:char *str[ ]char **str等价

cpp 复制代码
void show_str1(char *str[], int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
        printf("%d %s\n",i,str[i]);
}
void show_str2(char **str, int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
        printf("%d %s\n",i,*(str+i));
}
int	main(int argc, char **argv)
{
    char *str[5] = {"apple","happy","how","are","you"};
    int size = sizeof(str) / sizeof(str[0]);
    //show_str1(str, size);
    show_str2(str, size);
    return 0;
}

二. main函数参数

argc: 命令行参数个数
argv: 命令行参数的具体内容

cpp 复制代码
int	main(int argc, char **argv)
{
    //argc 命令行参数个数
    //argv 命令行参数的具体内容

    return 0;
}

eg:使用命令行来完成两数相加

cpp 复制代码
#include <stdio.h>
#include<stdlib.h>

int	main(int argc, char **argv)
{
    //argc 命令行参数个数
    //argv 命令行参数的具体内容
    printf("argc is %d\n",argc);
    int i = 0;
    for(i = 0; i < argc; i++)
        printf("argv[%d] is %s\n",i,argv[i]);
//完成两数相加
    //当命令行传参个数不够时打印错误信息提醒用户
    // if(argc < 3)
    // {
    //     printf("Usage:%s num1 num2\n",argv[0]);
    //     return 1;
    // }
    // int sum = atoi(argv[1]) + atoi(argv[2]);
    // printf("sum = %d\n",sum);

//完成多数相加
    if(argc < 3)
    {
        printf("Usage:%s num1 num2...\n",argv[0]);
        return 1;
    }
    int sum = 0;
    for(i = 0; i < argc; i++)
        sum += atoi(argv[i]);

    printf("sum = %d\n",sum);

    return 0;
}

atoi函数:

作用:函数会将 `nptr` 指向的字符串的开头部分转换为整数。

返回值:返回转换后的值

三. 指针常量与常量指针

3.1 指针常量

指针常量:指针的指向可以改变,但是不能通过指针修改指针指向的数据。

cpp 复制代码
int	main(int argc, char **argv)
{
    char str[10] = "happy";
    char str2[10] = "apple";
    const char *p = NULL;//指针常量:指针指向可以改变,指针指向的数据不能改变,只读
    //char const *p = NULL; //这样也是一个指针常量,const修饰*p,只要const在*p的左边即可

    p = str;//指针的指向可以改变
    //p[0] = 'b'; //指针指向的数据不能改变

    return 0;
}

3.2 常量指针

常量指针:指针的指向不可以改变,但是可以通过指针修改指针指向的数据。

cpp 复制代码
int	main(int argc, char **argv)
{
    char str[10] = "happy";
    char str2[10] = "apple";

    char * const p2 = str;//常量指针:指针的指向不能改变,指针指向的数据可以改变
                          //const修饰p2,const处在p2的左边
                          //注意:常量指针一定要初始化
    p2[0] = 'b';//可以通过指针修改指针指向的数据可以
    //p2 = str2;//指针的指向不能改变

    char a[5] = "hhh";//数组名本质就是一个常量指针
    a[0] = 'b';//可以通过指针修改指向的数据
    //a++;//但是不能修改指针的指向

    const char* const p3 = str;//都不能改变,指向常量的常量指针

    return 0;
}

四. void类型指针

void类型修饰指针 :万能指针,可以接收任意类型指针作为参数在被调函数中。其他类型的指针

(char*,int*,double*short*,结构体指针等)传参到void*类型指针,直接传递参

数,即可。

当需要使用void*指针时,要对其进行强制类型转换。

void*类型的指针,存储着实参传递过来的地址,但是不能进行解引用操作,因

为没有void类型的变量。

可以用来修饰函数的返回值,或者参数。

memcpy函数的实现:

cpp 复制代码
int show_array(int *a, int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
        printf("%d ",*(a + i));
    puts("");

    return 0;
}

void show_char_array(char *a)
{
  while (*a)
  {
    printf("%c", *(a++));
  }
  puts("");
}

// void *my_memcpy(void *dst, const void *src, size_t size)
// {
//     void *ret = dst;
//     while(size--)
//         *((char*)dst++) = *((char*)src++);

//     return ret;
// }

void *my_memcpy(void *dst, const void *src, size_t size)
{
    char *pdst = (char*)dst;
    char *psrc = (char*)src;
    while(size--)
        *pdst++ = *psrc++;
    return dst;
}

void* my_memmove(void* dst, const void* src, size_t num)
{
	void* ret = dst;
	if (src >= dst)//src在dst后面(或同地址),从前向后拷贝,不会覆盖
	{
		while (num--)
			*((char*)dst++) = *((char*)src++);
	}
	else//dst在src后面 → 从后向前拷贝,防止重叠覆盖
	{
        while(num--)
			*((char*)dst+num) = *((char*)src+num);
	}
	return ret;
}

int	main(int argc, char **argv)
{
    int a1[9] = {1,2,3,4,5,6,7,8,9};
    int a2[9] = { 0 };
    char str1[10] = "hello lll";
    char str2[10] = { 0 };
    // my_memcpy(a2,a1,sizeof(int)*10);
    // show_array(a2,10);
    // my_memcpy(str2, str1, sizeof(str1));
    // show_char_array(str2);

    // my_memmove(a2,a1,sizeof(int)*9);
    // show_array(a2,9);
    
    my_memmove(a1+2,a1,sizeof(int)*4);
    show_array(a1,9);

    return 0;
}
相关推荐
kkeeper~1 小时前
0基础C语言积跬步之深入理解指针(5下)
c语言·开发语言
Tisfy1 小时前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
IronMurphy1 小时前
【算法四十七】152. 乘积最大子数组
算法
淘矿人2 小时前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
Cosolar3 小时前
万字详解:RAG 向量索引算法与向量数据库架构及实战
数据库·人工智能·算法·数据库架构·milvus
三品吉他手会点灯3 小时前
C语言学习笔记 - 40.数据类型 - scanf函数的编程规范与非法输入处理
c语言·开发语言·笔记·学习
落羽的落羽4 小时前
【算法札记】练习 | Week4
linux·服务器·数据结构·c++·人工智能·算法·动态规划
萑澈5 小时前
算法竞赛入门:C++ STL核心用法与时空复杂度速查手册
数据结构·c++·算法·stl