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

2023-05-16

目录

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 <stdio.h>

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);

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

③ 程序运行至 *p = tmp;

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

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 <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
  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;
}

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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 <stdio.h>
#include <stdlib.h>
#include <string.h>


//成功为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);

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;

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言进阶 ~ 一级指针与字符串 的相关文章

  • Threat of Adversarial Attacks on Deep Learning in Computer Vision: A Survey 论文阅读笔记

    本文是论文的阅读笔记 Paper A Threat of Adversarial Attacks on Deep Learning in Computer Vision A Survey Author Naveed Akhtar cor n
  • ubuntu20.04安装skopeo

    文章目录 1 先安装好go环境2 配置环境3 安装skopeo3 1 安装依赖3 2 获取项目 xff0c 并进行编译3 3 构建文档3 4 安装3 5 验证 4 注意 1 先安装好go环境 如何安装go环境 xff0c 最好选择系统范围内
  • go get得到的东西不在$GOPATH中

    最近在ubuntu20 04上安装oci image tool xff0c 按照官方文档执行 xff0c 结果第一步就发现go get得到的东西找不到 xff0c 后来查阅了这篇博客 xff0c 发现了原因 xff0c 是因为开了gopro
  • 容器镜像加密-containerd imgcrypt实践

    最近在研究容器镜像加密 xff0c 发现国内对容器镜像这部分的博客好像不太多 xff0c 在看了一些人的博客后 xff0c 跟着他们的步骤进行了containerd imgcrypt的实践 xff0c 期间出现了一些错误 xff0c 决定记
  • ubuntu20.04安装howdy

    howdy是一款用于Linux系统的人脸识别身份验证系统 xff0c 可以看作是Windows中的Windows Hello的替代品 xff0c howdy在安装的过程中会去外网下载一些安装包 xff0c 所以前提条件是有访问外网的手段 h
  • zipimport.ZipImportError: can‘t decompress data; zlib not available

    在Ubuntu16 04上通过pyenv安装python3 6 8时出现以下错误 xff0c 记录一下 ubuntu 64 ubuntu pyenv span class token function install span 3 6 8
  • Ubuntu16.04安装zabbix4.0

    以下教程为Ubuntu16 04安装zabbix4 0 xff0c 需提前自己安装好Mysql数据库 其中第1 7点为主节点安装配置Zabbix server Zabbix agent Web前端 xff0c 第8点不用进行 xff1b 第
  • Ubuntu16.04搭建gitea1.14.1

    以下教程为在Ubuntu16 04上搭建gitea1 14 1 xff0c 同时附上官方教程链接 文章目录 1 数据库准备1 1 登录数据库1 2 创建gitea用户1 3 创建gitea数据库1 4 给gitea用户赋予数据库的权限1 5
  • ubuntu16.04搭建spice-html5用于配合KVM

    文章目录 0 配置需求1 启动spice客户端2 配置websockify3 配置spice html54 浏览器访问 0 配置需求 Firefox或Chrome浏览器 xff0c IE浏览器也可以 xff0c 但是效果不是太好 WebSo
  • python 数据挖掘中的数值计算

    一 环境安装 环境配置 xff1a OS xff1a Red Hat 4 4 7 11 查看命令 xff1a uname a xff1a 电脑以及操作系统的相关信息 cat proc version xff1a 正在运行的内核版本 cat
  • 银河麒麟下libguestfs-tools中virt工具无法使用情况

    银河麒麟下libguestfs tools中virt工具无法使用情况 问题描述 xff1a 在银河麒麟高级服务器版本V10下安装libguestfs tools工具包后 xff0c 使用virt xx等一系列命令都会出现以下错误 xff1a
  • ubuntu16.04搭建containerd

    本博客具体介绍在ubuntu16 04下安装containerd的过程 xff0c 有关ctr的命令都要有root权限才能运行 搭建过程 下载containerd安装包解压containerd安装包到根目录下启动containerd并设置开
  • KVM安装Windows11系列(一)

    本教程系列为KVM安装Windows11 xff0c 会分成两部分 xff0c 第一部分会跳过Windows11的硬件要求TPM和安全启动 xff0c 第二部分会安装TPM模拟器进行模拟 文章目录 软件环境下载Windows11镜像和驱动创
  • 容器技术对比(Docker/LXC/LXD/Multipass)

    DockerLXCLXDMultipass基本介绍为了打破 程序即应用 的观念 xff0c 通过镜像imges将作业系统核心除外 xff0c 运作应用程序所需的系统环境 xff0c 由下而上打包 xff0c 达到应用程序跨平台间的无缝接轨运
  • KVM虚拟机配置静态IP(一):Ubuntu16.04

    该系列文章为制作KVM虚拟机镜像的同时配置静态IP xff0c 为用户直接提供好固定IP xff0c 无需手动配置 系列文章目录 Ubuntu16 04Ubuntu18 04Centos6Centos7 文章目录 系列文章目录软件环境一 安
  • KVM虚拟机配置静态IP(二):Ubuntu18.04

    该系列文章为制作KVM虚拟机镜像的同时配置静态IP xff0c 为用户直接提供好固定IP xff0c 无需手动配置 系列文章目录 Ubuntu16 04Ubuntu18 04Centos6Centos7 文章目录 系列文章目录软件环境一 安

随机推荐

  • KVM虚拟机配置静态IP(三):Centos6

    该系列文章为制作KVM虚拟机镜像的同时配置静态IP xff0c 为用户直接提供好固定IP xff0c 无需手动配置 系列文章目录 Ubuntu16 04Ubuntu18 04Centos6Centos7 文章目录 系列文章目录软件环境一 安
  • KVM虚拟机配置静态IP(四):Centos7

    该系列文章为制作KVM虚拟机镜像的同时配置静态IP xff0c 为用户直接提供好固定IP xff0c 无需手动配置 系列文章目录 Ubuntu16 04Ubuntu18 04Centos6Centos7 文章目录 系列文章目录软件环境一 安
  • KVM下Ubuntu18.04打开设置注销问题

    问题描述 xff1a 在KVM中创建Ubuntu18 04 xff0c 打开系统设置 xff0c 发现直接注销 xff08 不是锁屏 xff0c 因为所有程序都退出 xff09 解决思路 在google上搜索发现大多数都是指向显卡问题 xf
  • cloud-init中NoCloud配置

    本文章主要记录cloud init工具中NoCloud数据源的使用方法 xff0c 可以搭配KVM镜像制作系列文章 xff0c 为用户定制操作系统 文章目录 NoCloud使用方法1 安装并初始化文件2 修改cloud init配置文件3
  • winform界面设计

    来自于以下两个地址 xff0c 为便于查阅 xff0c 所以全复制到了自己的BLOG xff1a http dotnet chinaitlab com VCNET 436373 html http www aspxboy com priva
  • cloud-init离线安装编程环境

    本博客主要介绍通过cloud init工具实现在Ubuntu16 04操作系统和KVM虚拟化技术下实现创建虚拟机同时离线安装编程环境 文章目录 1 准备离线安装包1 xff09 下载软件包2 xff09 创建放置软件包的磁盘3 xff09
  • openEuler22.03安装zabbix4.0

    以下教程为openEuler22 03安装zabbix4 0 xff0c 主要原因是openEuler官方和zabbix官方提供的提供的软件源中没有相关软件 xff0c 因此需要使用zabbix源码进行编译 xff0c 并且安装过程中会出现
  • 1.2 SingleThreadExecutor

    线程池工具类给我们提供了一些常见的线程池 xff0c 这篇来谈一谈SingleThreadExecutor线程池 使用方式 创建方式比较简单 xff0c 直接使用工具创建就ok xff0c Executors newSingleThread
  • pycharm终止代码运行时报错:进程已结束,退出代码137 (interrupted by signal 9: SIGKILL)

    在pycharm中调试代码 xff0c 终止时报错 xff1a 进程已结束 退出代码137 interrupted by signal 9 SIGKILL 网上查找时 xff0c 遇到这个问题的一般是训练网络时的内存不足 xff0c 进程被
  • 【多机多卡】mmsegmentation训练报错“RuntimeError: NCCL error in: /opt/pytorch/pytorch/torch/csrc/distributed/”

    多机多卡训练代码 xff1a 报错信息 xff1a RuntimeError NCCL error in opt pytorch pytorch torch csrc distributed c10d ProcessGroupNCCL cp
  • STM32F4工程--串口--配置一个发送函数(详细版)

    STM32F4工程 串口 配置一个发送函数 xff08 库函数 xff09 芯片 xff1a STM32F429IGT6 目录 一 初始化串口相关的参数 二 初始化串口IO口时钟等参数 三 函数声明 四 主函数 xff08 执行函数 xff
  • Ubuntu:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver. 解决方法总结

    在Ubuntu上运行Cuda并行计算的渲染项目 xff08 Massively Parallel Rendering of Complex Closed Form Implicit Surfaces 论文代码GUI部分源码 xff09 xf
  • Ubuntu16.04下基于BUCK安装onos

    踩了很多坑 xff0c 其中很多错误也没整明白怎么回事 xff0c 实在搞不了就重装系统 xff0c 经过多次测试 xff0c 找到了一个合适的安装步骤安装ONNO 1 13 2 1 安装mininet 需要可以安装 xff09 此步骤安装
  • Ubuntu16.04安装中文输入法

    转载自 xff1a https jingyan baidu com article 86f4a73e8f534637d752695e html 这是基于Fcitx框架的 可以安装Google pinyin xff0c Sougou piny
  • 基于IDEA分析ONOS源码

    1 安装Java依赖 sudo apt get install software properties common y amp amp sudo add apt repository ppa webupd8team java y amp
  • ESP8266- 使用AT指令获取网络时间

    前言 xff1a 很早就考虑过用 ESP8266 获取网络时间 xff0c 以前都是用 ESP8266 刷机智云的 Gagent 固件 xff0c 但无奈现在手头的 ESP 01 的 Flash 只有 1M xff0c 实在无法胜任 经过在
  • 使用git在项目中的一些经验

    近期在使用gitLab管理项目 xff0c 在使用过程中遇到一些问题 xff0c 在此整理一下 git的基本配置在这里就不累赘了 xff0c 主要讲一下如何将项目托管到gitLab xff0c 并实现多人协作开发 尤其介绍一下如何解决冲突
  • Ubuntu安装ROS报错 sudo: rosdep:找不到命令

    安装ROS时初始化rosdep过程中 xff0c 执行到 xff1a sodu rosdep init 报错 xff1a sudo rosdep xff1a 找不到命令 原因 xff1a 没有安装python rosdep这个包 解决方法
  • C语言进阶 ~ 内存四区(栈、堆、全局、代码区)

    特别声明 xff1a 该部分是根据B站大佬 什么都想干好的视频学习而来 目录 1 1 数据类型本质分析 1 1 1 数据类型概念 1 1 2 数据类型的本质 1 1 3 数据类型的别名 1 1 4 数据类型之 void 1 2 变量的本质分
  • C语言进阶 ~ 一级指针与字符串

    目录 2 1 指针强化 2 2 一级指针 char 易错地方 2 2 1 对空字符串和非法字符串的判断 2 2 2 越界 2 2 3 指针的叠加会不断改变指针的方向 2 2 4 局部变量不要外传 2 2 5 函数内使用辅助变量的重要性 2