C语言进阶 ~ 一级指针与字符串

目录

2.1 指针强化

2.2 一级指针(char*)易错地方

2.2.1 对空字符串和非法字符串的判断

2.2.2 越界

2.2.3 指针的叠加会不断改变指针的方向

2.2.4 局部变量不要外传

2.2.5 函数内使用辅助变量的重要性

2.3 字符串

2.3.1 字符串初始化

2.3.2 数组法和指针法操作字符串

2.3.3 字符串拷贝函数 strcpy

剖析片段程序

2.4 const

2.4.1 冒牌的 “const”

2.4.2 const 与 指针


2.1 指针强化

强化1:指针是一种数据类型

1)指针变量也是一种变量,占有内存空间,用来保存内存地址测试指针变量占有内存空间大小。

2)保证所指的内存块能修改

3)指针是一种数据类型,是指它指向的内存空间的数据类型

4 ) 不允许向NULL和未知非法地址拷贝内存。

	char *p3 = NULL;
	//给p3指向的内存区域拷贝内存
	strcpy(p3, "1111"); //err


	char *p3 = 0x0001;
	//给p3指向的内存区域拷贝内存
	strcpy(p3, "1111"); //err

强化2:间接赋值(*p)是指针存在的最大意义

强化3:理解指针必须和内存四区概念相结合

强化4:应用指针必须和函数调用相结合(指针做函数参数)

值得一看:

用1级指针形参,去间接修改了0级指针(实参)的值。

用2级指针形参,去间接修改了1级指针(实参)的值。

用3级指针形参,去间接修改了2级指针(实参)的值。

用n级指针形参,去间接修改了n-1级指针(实参)的值。

#include 

void fun(char **p , int *len)
{
	if (p == NULL)
	{
		return;
	}

	char *tmp = (char *)malloc(100);
	if (tmp == NULL)
	{
		return;
	}
	strcpy(tmp, "adlsgjldsk");

	//间接赋值
	*p = tmp;
	*len = strlen(tmp);
}

int main(void)
{

	char *p1 = NULL;
	int len1 = 0;
	fun(&p1, &len1);
	if (p1 != NULL)
	{
		printf("p1 = %s, len1 = %d\n", p1, len1);
	}

	printf("\n");
	system("pause");
	return 0;
}

① 程序运行至 char *tmp = (char *)malloc(100);

C语言进阶 ~ 一级指针与字符串_第1张图片

C语言进阶 ~ 一级指针与字符串_第2张图片

② 程序运行至 strcpy(tmp, "adlsgjldsk");

C语言进阶 ~ 一级指针与字符串_第3张图片

C语言进阶 ~ 一级指针与字符串_第4张图片

③ 程序运行至 *p = tmp;

C语言进阶 ~ 一级指针与字符串_第5张图片

④ 程序运行至 *len = strlen(tmp);

C语言进阶 ~ 一级指针与字符串_第6张图片

2.2 一级指针(char*)易错地方

2.2.1 对空字符串和非法字符串的判断

void copy_str(char *from, char *to)

{

    if (*from == '\0' || *to == '\0')  // 正确的为    if (from == '\0' || to == '\0')   地址是否为空

    {

        printf("func copy_str() err\n");

        return;

    }

    for (; *from!='\0'; from++, to++)

    {

        *to = *from;

    }

    *to = '\0';

}

2.2.2 越界

char buf[3] = "abc";

2.2.3 指针的叠加会不断改变指针的方向

char *getKeyByValue(char **keyvaluebuf, char *keybuf)

{

    int i = 0;

    char *a = (char *)malloc(50);

    for (; **keyvaluebuf != '\0'; i++)

    {

        *a++ = *(*keyvaluebuf)++;

    }          

    free(a);

}  

2.2.4 局部变量不要外传

char *my_stract(char *x, char* y)

{

    char str[80];

    char *z=str;           /*指针z指向数组str*/ 

    while(*z++=*x++);

    z--;                    /*去掉串尾结束标志*/

    while(*z++=*y++);

    z=str;                 /*str地址赋给指针变量z*/

    return(z);

}

2.2.5 函数内使用辅助变量的重要性

int getSubCount(char *str, char *substr, int *mycount)

{

    int ret = 0;

    char *p = str;   

    char *sub = substr;

    if (str==NULL || substr==NULL || mycount == NULL)

    {

        ret = -1;

        return ret;

    }

............

 

2.3 字符串

c语言没有字符串类型,通过字符数组模拟
c语言字符串,以字符‘\0’或数字0

2.3.1 字符串初始化

①  strlen:测字符串长度,不包含数字0,字符'\0'
      sizeof:测数组长度,包含数字0,字符'\0'

    char buf9[100] = "agjdslgjlsdjg";
    printf("strlen = %d, sizeof = %d\n", strlen(buf9), sizeof(buf9));

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

/*
  C语言没有字符串类型,通过字符数组模拟
  C语言字符串,以字符‘\0’, 数字0
*/
int main(void)
{
////////////////////////////////////////////////////////
	//不指定长度, 没有0结束符,有多少个元素就有多长
	char buf[] = { 'a', 'b', 'c' };
	printf("buf = %s\n", buf);

	//指定长度,后面没有赋值的元素,自动补0
	char buf2[100] = { 'a', 'b', 'c' };
	printf("buf2 = %s\n", buf2);

	//所有元素赋值为0
	char buf3[100] = { 0 };
//////////////////////////////////////////////////////////

	//char buf4[2] = { '1', '2', '3' };  //数组越界

	char buf5[50] = { '1', 'a', 'b', '0', '7' };
	printf("buf5 = %s\n", buf5);

	char buf6[50] = { '1', 'a', 'b', 0, '7' };
	printf("buf6 = %s\n", buf6);

	char buf7[50] = { '1', 'a', 'b', '\0', '7' };
	printf("buf7 = %s\n", buf7);
//////////////////////////////////////////////////////////

	//使用字符串初始化,常用
	char buf8[] = "agjdslgjlsdjg";
//////////////////////////////////////////////////////////
	//strlen: 测字符串长度,不包含数字0,字符'\0'
	//sizeof:测数组长度,包含数字0,字符'\0'
	printf("strlen = %d, sizeof = %d\n", strlen(buf8), sizeof(buf8));
//////////////////////////////////////////////////////////
	char buf9[100] = "agjdslgjlsdjg";
	printf("strlen = %d, sizeof = %d\n", strlen(buf9), sizeof(buf9));

/////////////////////////////////////////////////////////

	printf("\n");
	system("pause");
	return 0;
}

C语言进阶 ~ 一级指针与字符串_第7张图片

2.3.2 数组法和指针法操作字符串

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

int main(void)
{
	char buf[] = "algjdlksajgldksjg";
	int i = 0;
	int n = strlen(buf);
	char *p = NULL;

	//[]方式
	for (i = 0; i < n; i++)
	{
		printf("%c", buf[i]);
	}
	printf("\n");

	//指针方法
	//数组名字,数组首元素地址
	p = buf;
//////////////////////////////////////////////////////////////
	for (i = 0; i < n; i++)
	{
		printf("%c", p[i]);
	}
	printf("\n");
//////////////////////////////////////////////////////////////
	for (i = 0; i < n; i++)
	{
		printf("%c", *(p+i) );
	}
	printf("\n");
//////////////////////////////////////////////////////////////
	for (i = 0; i < n; i++)
	{
		printf("%c", *(buf+i) );
	}
	printf("\n");
//////////////////////////////////////////////////////////////
	//buf和p完全等价吗?
	//p++;     正常
	//buf++;   此处出错
	//buf 只是一个常量,不能修改

//////////////////////////////////////////////////////////////
	printf("\n");
	system("pause");
	return 0;
}

2.3.3 字符串拷贝函数 strcpy

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 


//成功为0,失败非0
//1、判断形参指针是否为NULL
//2、最好不要直接使用形参
int  my_strcpy(char *dst, char *src)
{
	if (dst == NULL || src == NULL)
	{
		return -1;
	}

	//辅助变量把形参接过来
	char *to = dst;
	char *from = src;
////////////////////////////////////////////////////////////////////
	//*to = *from
	//to++, from++
	//判断 *to是否为0, 为0跳出循环
	while (*to++ = *from++)
	{
		NULL;
	}
////////////////////////////////////////////////////////////////////
	printf("my_strcpy: dst = %s\n", dst);

	return 0;
}

int main(void)
{
	char src[] = "abcedfdgds";
	char dst[100] = { 0 };
	int ret = 0;

////////////////////////////////////////////////////////////////////
	ret = my_strcpy(dst, src);
	if (ret != 0)
	{
		printf("my_strcpy err:%d\n", ret);
		return ret;
	}
	printf("%s\n", dst);
////////////////////////////////////////////////////////////////////

	printf("\n");
	system("pause");
	return 0;
}

剖析片段程序

////////////////////////////////////////////////////////////////////
    while (*to++ = *from++)
    {
        NULL;
    }
////////////////////////////////////////////////////////////////////

① *to = *from

② to++, from++

③ 判断 *to是否为0, 为0跳出循环

2.4 const

2.4.1 冒牌的 “const”

const旨在用户层面不能修改,而一般在机器修改时候都是用的是地址进行改数。

    const int b = 10;
    //b = 100; //err
    int *q = &b;
    *q = 22;
    printf("%d, %d\n", b, *q);

C语言进阶 ~ 一级指针与字符串_第8张图片

2.4.2 const 与 指针

    指针变量, 指针指向的内存, 2个不同概念


	char buf[] = "aklgjdlsgjlkds";

    从左往右看,跳过类型,看修饰哪个字符

    const char *p = buf;
    // 等价于上面 char const *p1 = buf;

  •     如果是*, 说明指针指向的内存不能改变

    const char *p = buf;
    // 等价于上面 char const *p1 = buf;
    //p[1] = '2'; //err
    p = "agdlsjaglkdsajgl"; //ok

  •     如果是指针变量,说明指针的指向不能改变,指针的值不能修改

    char * const p2 = buf;
    p2[1] = '3';
    //p2 = "salkjgldsjaglk"; //err

  •    如果是指针变量和*, 指向不能变,指向的内存也不能变

//p3为只读,指向不能变,指向的内存也不能变
    const char * const p3 = buf;

 

你可能感兴趣的:(深入浅出C语言,指针强化,c语言,字符串,const,与,指针,一级指针易错地方)