一. 二级指针
二级指针传参:在函数传参时: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;
}