c语言基础--------字符串指针

news2024/11/22 11:23:07

在 C 语言中,字符串指针是一个指向字符类型的指针,通常用于指向字符串的第一个字符。字符串在 C 语言中通常表示为字符数组,而字符串指针则是用来存储这种字符数组首地址的变量。

定义字符串指针

字符串指针的定义方式如下:

char *stringPtr;

这里的 char * 表示 stringPtr 是一个指向 char 类型的指针,它可以用来指向一个字符串。

初始化字符串指针

字符串指针可以通过以下方式初始化:

char *stringPtr = "Hello, World!";

在这个例子中,stringPtr 被初始化为指向一个字符串常量 “Hello, World!” 的第一个字符。

使用字符串指针

字符串指针可以用来访问和操作字符串。以下是一些使用字符串指针的示例:

#include <stdio.h>
int main() {
    char *stringPtr = "Hello, World!";
    // 使用字符串指针打印字符串
    printf("%s\n", stringPtr);
    // 访问字符串中的单个字符
    for (int i = 0; stringPtr[i] != '\0'; i++) {
        printf("%c ", stringPtr[i]);
    }
    printf("\n");
    return 0;
}

在上面的代码中,stringPtr 指向了一个字符串常量。使用 %s 格式化字符串可以打印整个字符串。通过循环和数组下标的方式,可以逐个访问字符串中的字符,直到遇到空字符 \0,这表示字符串的结束。

字符串指针与字符数组的区别

字符串指针与字符数组在 C 语言中是不同的:

  • 字符串指针:是一个指针,它存储的是字符串的首地址。
  • 字符数组:是一个数组,它存储的是字符串本身。
    以下是一个字符数组的示例:
char strArray[] = "Hello, World!";

在这个例子中,strArray 是一个字符数组,它包含了 “Hello, World!” 字符串的所有字符,包括结尾的空字符 \0

注意事项

  • 字符串指针可以指向字符串常量,但是不能直接修改字符串常量中的内容,因为这通常会导致未定义的行为。
  • 当使用字符串指针时,应当注意避免越界访问,即不要访问字符串结束标记 \0 之后的内存。
    字符串指针是 C 语言中处理字符串的一种基本方式,理解和掌握它们的使用对于 C 语言编程非常重要。

字符数组 与字符指针的区别

在 C 语言中,字符数组和字符指针虽然都可以用来处理字符串,但它们在概念、用途和内存布局上存在一些关键的区别。

定义和内存布局

  1. 字符数组
    • 定义:字符数组是一个数组,其元素类型为 char,用于存储一系列字符。
    • 内存布局:字符数组在内存中分配一块连续的空间来存储字符序列,包括字符串的结束标志 \0
      示例:
    char strArray[20] = "Hello, World!";
    
  2. 字符指针
    • 定义:字符指针是一个指向 char 类型的指针,通常用于指向字符串的第一个字符。
    • 内存布局:字符指针本身只占用一个指针大小的内存(通常是 4 或 8 字节,取决于系统架构),它存储的是字符串首地址。
      示例:
    char *strPtr = "Hello, World!";
    

在这里插入图片描述

内容修改

  1. 字符数组
    • 可以直接修改数组中的字符,因为数组分配了内存空间来存储这些字符。
      示例:
    strArray[0] = 'h'; // 将第一个字符修改为小写的 'h'
    
  2. 字符指针
    • 通常指向字符串常量,这些常量存储在程序的只读数据段中,因此直接尝试修改这些字符可能会导致运行时错误或未定义行为。
    • 如果字符指针指向的是可修改的内存(如动态分配的内存或字符数组),则可以修改它所指向的内容。
      示例(错误用法):
    strPtr[0] = 'h'; // 错误:如果 strPtr 指向字符串常量,这将导致未定义行为
    

大小和生命周期

  1. 字符数组
    • 的大小在编译时确定,且在函数作用域结束时自动释放。
    • 的大小必须足够大,以容纳字符串及其结束标志 \0
  2. 字符指针
    • 自身的大小是固定的,不随指向的字符串长度变化。
    • 指向的字符串的生命周期不受字符指针的生命周期影响。
      在这里插入图片描述

作为函数参数

  1. 字符数组
    • 作为参数传递时,实际上传递的是数组的首地址,但数组的大小不会被传递。
  2. 字符指针
    • 作为参数传递时,传递的也是字符串的首地址,但不需要知道字符串的长度。

总结

以下是字符数组和字符指针的主要区别的总结:

  • 内存分配:字符数组在栈上分配内存,而字符指针本身在栈上分配内存,它指向的字符串可能在栈上、堆上或只读数据段中。
  • 修改能力:字符数组的内容可以被修改,而字符指针指向的字符串常量通常不能被修改。
  • 大小:字符数组的大小取决于其存储的字符数量,而字符指针的大小是固定的。
    理解这些区别对于正确使用字符数组和字符指针至关重要。
    下面是字符数组和字符指针的代码示例,以及它们之间的区别:
#include <stdio.h>
#include <string.h>
int main() {
    // 字符数组示例
    char strArray[20] = "Hello, World!"; // 分配了20个字符的空间
    // 修改字符数组中的内容
    strArray[0] = 'h'; // 将第一个字符修改为小写的 'h'
    // 打印字符数组
    printf("Character array: %s\n", strArray);
    // 字符指针示例
    char *strPtr = "Hello, World!"; // 指向一个字符串常量
    // 尝试修改字符指针指向的内容(这是错误的,会导致未定义行为)
    // strPtr[0] = 'h'; // 错误,不要这样做!
    // 打印字符指针指向的字符串
    printf("Character pointer: %s\n", strPtr);
    // 字符指针指向动态分配的内存示例
    char *dynamicStr = malloc(20 * sizeof(char)); // 动态分配内存
    if (dynamicStr != NULL) {
        strcpy(dynamicStr, "Hello, Dynamic World!"); // 复制字符串到动态分配的内存
        // 修改动态分配内存中的内容
        dynamicStr[0] = 'h'; // 这是合法的,因为我们分配了可写的内存
        // 打印修改后的动态字符串
        printf("Dynamic string: %s\n", dynamicStr);
        // 释放动态分配的内存
        free(dynamicStr);
    }
    return 0;
}

在这个示例中:

  • strArray 是一个字符数组,它被初始化为 “Hello, World!”,并且我们修改了它的第一个字符为小写的 ‘h’。
  • strPtr 是一个字符指针,它指向一个字符串常量 “Hello, World!”。尝试直接修改 strPtr 指向的字符串是错误的,因为这会试图修改只读内存。
  • dynamicStr 是一个指向动态分配内存的字符指针。我们可以安全地修改 dynamicStr 指向的内容,因为它指向的是我们分配的可写内存。在使用完毕后,我们使用 free 函数释放了这块内存。
    这个示例展示了字符数组和字符指针在定义、内存分配、修改能力以及作为函数参数时的不同用法。

在这里插入图片描述

字符指针作为函数参数

在 C 语言中,字符指针经常被用作函数参数,尤其是在处理字符串时。以下是如何使用字符指针作为函数参数的几个示例。

示例 1:打印字符串

一个简单的函数,它接收一个字符指针作为参数并打印字符串。

#include <stdio.h>
void printString(const char *str) {
    printf("%s\n", str);
}
int main() {
    char *str = "Hello, World!";
    printString(str); // 调用函数并传递字符串
    return 0;
}

在这个例子中,printString 函数接收一个指向 char 的指针 str,它指向一个字符串。函数使用 printf 来打印这个字符串。

示例 2:计算字符串长度

一个函数,它接收一个字符指针作为参数并返回字符串的长度。

#include <stdio.h>
#include <string.h>
int stringLength(const char *str) {
    int length = 0;
    while (*str != '\0') {
        length++;
        str++;
    }
    return length;
}
int main() {
    char *str = "Hello, World!";
    int len = stringLength(str); // 调用函数并传递字符串
    printf("The length of the string is: %d\n", len);
    return 0;
}

在这个例子中,stringLength 函数通过遍历字符串直到遇到空字符 \0 来计算字符串的长度。

示例 3:字符串复制

一个函数,它接收两个字符指针作为参数,并将源字符串复制到目标缓冲区。

#include <stdio.h>
#include <string.h>
void copyString(char *dest, const char *src) {
    while ((*dest = *src) != '\0') {
        dest++;
        src++;
    }
}
int main() {
    char src[] = "Hello, World!";
    char dest[20]; // 确保有足够的空间来存储复制的内容
    copyString(dest, src); // 调用函数并传递源字符串和目标缓冲区
    printf("Copied string: %s\n", dest);
    return 0;
}

在这个例子中,copyString 函数将源字符串 src 复制到目标缓冲区 dest 中。注意,目标缓冲区需要有足够的空间来存储源字符串及其结束标志 \0

注意事项

  • 当使用字符指针作为函数参数时,应当注意不要修改指针所指向的字符串常量。
  • 如果函数内部需要修改字符串,应该传递指向可修改内存的指针,例如动态分配的内存或字符数组。
  • 使用 const 关键字可以确保函数不会修改传入的字符串,这是一个好的编程实践。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2056301.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android更改包名和签名

一、更改包名 1、包名——鼠标右键——Refactor——Rename 修改自己想更改的包名和选择更改范围后点击Refactor就可以了 2.手动修改app的build.gradle文件中的applicationId&#xff08;改成和我们之前修改的包名相同&#xff09; 3.修改AndroidManifest.xml文件中的packag…

“AI+Security”系列第2期(三):面向LLM(大语言模型)的漏洞挖掘与对齐防御研究

近日&#xff0c;由安全极客、Wisemodel 社区和 InForSec 网络安全研究国际学术论坛联合主办的“AISecurity”系列第 2 期——对抗&#xff01;大模型自身安全的攻防博弈线上活动如期举行。 在此次活动中&#xff0c;前阿里云高级安全专家郑瀚带来了以《通往LLM安全对齐的道路…

网易云音乐故障 2 小时,这次到底谁背锅?(今天记得领补偿)

大家好&#xff0c;我是程序员鱼皮&#xff0c;8 月 19 日下午&#xff0c;网易云音乐突发严重故障&#xff0c;并登顶微博热搜&#xff0c;跟黑神话悟空抢了热度。 根据用户的反馈&#xff0c;故障的具体表现为&#xff1a;用户无法登录、歌单加载失败、播放信息获取失败、无法…

SQL— DML语句学习【后端 10】

数据库操作-DML 详解 在数据库管理系统中&#xff0c;DML&#xff08;Data Manipulation Language&#xff0c;数据操作语言&#xff09;扮演着至关重要的角色&#xff0c;它负责对数据库中的数据进行增、删、改操作。掌握DML操作对于数据库的日常维护和管理至关重要。本文将详…

CSP 2023 普及组第一轮 - CSP/S 2023初试题 完善程序第二题解析

一、题目阅读 &#xff08;编辑距离&#xff09;给定两个字符串&#xff0c;每次操作可以选择删除&#xff08;Delete&#xff09;、插入&#xff08;Insert&#xff09;、替换&#xff08;Replace&#xff09;&#xff0c;一个字符&#xff0c;求将第一个字符串转换为第二个字…

时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention

时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention 文章目录 前言时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention 一、BO-CNN-BiGRU-Attention模型1. 贝叶斯优化&#…

【C++ 第十二章】二叉搜索树

1.1 二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 左边小&#xff1a;若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值右边大&#xff1a;若它的右子树不为空&#xff0c;则右子树上…

并网式光伏气象站——科技百科

并网式光伏气象站的工作原理简洁而充满智慧&#xff0c;并网式光伏气象站巧妙地通过太阳能电池板将太阳能转化为电能&#xff0c;利用先进的气象监测设备&#xff0c;‌对风速、‌风向、‌温度、‌湿度、‌光照等关键气象要素进行实时监测和记录&#xff0c;不仅充分利用了太阳…

【初阶数据结构题目】32. 希尔排序

文章目录 希尔排序希尔排序的时间复杂度计算 希尔排序 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff08;通常是gap n/31&#xff09;&#xff0c;把待排序文件所有记录分成各组&#xff0c;所有的距离相等的记录分在同一组内&#x…

全国10米分辨率逐年植被覆盖度(FVC)数据集

本数据集包括2017至2023年间&#xff0c;全国植被覆盖度数据&#xff0c;FVC范围值为0-1&#xff0c;数据为浮点型&#xff0c;GeoTIFF格式。GeoTIFF文件均可用ArcGIS软件和GDAL读取和打开。 植被覆盖度是指植被&#xff08;包括叶、茎、枝&#xff09;在地面的垂直投影面积占统…

系统编程-进程初步2

进程初步2 目录 进程初步2 1、进程等待清理函数&#xff08;wait&#xff09; 2、等待指定的子进程&#xff08;waitpid&#xff09; 3、新的开辟进程的函数&#xff08;vfork&#xff09; 4、在程序中运行系统下的指令&#xff08;system&#xff09; 5、exec 函数族 …

初识指针4の学习笔记

目录 1>>前言 2>>字符指针变量 3>>数组指针变量 4>>函数指针变量 5>>函数指针数组 6>>回调函数是什么&#xff1f; 7>>结语 1>>前言 今天我会继续分享一些我做的笔记&#xff0c;以及我对指针的理解&#xff0c; 后续会…

查看会议所属CCF级别(A/B/C类会议)

步骤&#xff1a; 1、打开中国计算机学会官网&#xff1a;中国计算机学会 (ccf.org.cn)。 2、搜索框中输入会议名称&#xff0c;例如&#xff1a;SIGKDD。 3、点击打开如图所示来源是“学术评价”的网页。 4、进入如下页面。 可以看到&#xff0c;SIGKDD是CCF A类会议。 参考…

低代码: 关于Test Driven Development - 测试驱动开发组件与测试示例

TDD 的开发方式 Test Driven Development - 测试驱动开发这是一种非常有意思的开发方式,我们进入一个实际场景,拿需要自研的colorpicker表单组件来说表单中的很多属性,都需要进行一个颜色的选择,如背景颜色,字体颜色等等我们来看一下相关设计交互在这里我们分两个图,点击…

python的导入包飘红

本文是mac的解决方法 1、点击pycharm-preferences-paython interpreter 直接搜索你要导入的包名&#xff0c;选择版本号点击 install 2、第二种方法是命令 pip3 install pandas2.2.2

学习文件IO,让你从操作系统内核的角度去理解输入和输出(理论篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

day06——前后端交互

一、计算属性 计算属性就是基于现有的数据推算出来的新属性&#xff0c;只要依赖的数据变化&#xff0c;新属性就会自动更新&#xff0c;而且计算属性多次调用的情况下只会计算一次&#xff0c;效率非常高 简化写法 const app new Vue({ el: #app, data: {}, methods: {//跟da…

易境通海运系统:打造海运专线稳定合作的强力引擎

对于海运专线而言&#xff0c;稳定的合作伙伴至关重要。在激烈的市场竞争中&#xff0c;如何持续保持客户的高满意度&#xff0c;不断强化自身优势&#xff0c;并提升用户粘性&#xff0c;是众多海运专线必须面对并解决的问题。而拥有一套可靠的系统&#xff0c;提供完备的服务…

会“坐”电梯,能避障碍,AGV无人搬运车进入各行各业

AGV 近年来&#xff0c;自动导引车&#xff08;Automated Guided Vehicle&#xff0c;简称AGV&#xff09;作为一种先进的物流设备&#xff0c;在制造业中广泛应用。AGV是一种能够自主行驶的无人驾驶车辆&#xff0c;通过内置的导航系统和传感器&#xff0c;实现对环境的感知与…

Loop Map 循环的几种方法

参考 Using entrySet() public void iterateUsingEntrySet(Map<String, Integer> map) {for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey() ":" entry.getValue());} } Iterator<Map.Entry<String…