c语言 char *str = ““ 和 char *str = NULL 以及 char str[] = {} 区别

目录

  • 前言
  • char *str = "" 和 char *str = NULL 区别
  • char *str = NULL 和 char str[] = {} 区别
  • char *str = "" 和 char str[] = {} 区别
  • char *str = "" 和 const char *str = "" 区别

前言

C语言指针的使用非常常见且易出错,这里对常见的用法做个总结。

指针就是固定大小(一般系统占据4字节)的一块空间,保存的是其他变量的地址。一个指向性的东西。

  • C语言里面“”表示字符串,保存在常量区,不能修改;
  • {}表示数组,自动分配栈空间,可以修改;
  • 指针本身是个变量,一般固定占用4个字节,保存其他变量的地址,可以修改从而指向不同的地址空间(非const修饰保存在栈空间)。
char *p1 = NULL;
char *p2 = "";strlen(p1);    // 段错误(访问0地址)
strlen(p2);    // 返回0(安全)
sizeof(p1);	   // 安全,strlen计算的是指针指向的字符串空间的长度,而sizeof计算的是指针本身的长度*p1 = 'a';     // 段错误
*p2 = 'a';     // 段错误(只读内存)// 指针是个变量,本身保存在栈空间里,修改指针本身从而指向不同的地方
char *reason_str = "";
switch (reset_reason)
{case ESP_RST_UNKNOWN:   reason_str = "UNKNOWN"; break;case ESP_RST_POWERON:   reason_str = "POWERON"; break;case ESP_RST_EXT:       reason_str = "PIN"; break;case ESP_RST_SW:        reason_str = "SW"; break;case ESP_RST_PANIC:     reason_str = "PANIC"; break;case ESP_RST_WDT:       reason_str = "WDT"; break;case ESP_RST_DEEPSLEEP: reason_str = "DEEPSLEEP"; break;case ESP_RST_BROWNOUT:  reason_str = "BROWNOUT"; break;case ESP_RST_SDIO:      reason_str = "SDIO"; break;
}

char *str = “” 和 char *str = NULL 区别

在C语言中,char *str = “” 和 char *str = NULL 有本质区别,主要体现在内存分配、使用场景和操作安全性上。以下是详细对比:

1. 内存表现

特性char *str = NULLchar *str = “”
‌指针值0x00000000(无效地址)有效地址(如 0x00405060)
‌指向内容无内存分配1字节的 ‘\0’(空字符串)
‌‌内存区域只读数据段(.rodata)

‌2. 核心区别

  • ‌NULL‌

    • 表示指针未初始化或指向无效地址。
    • ‌解引用会崩溃‌(如 strlen(NULL) 触发段错误)。
    • 典型用途:标识错误返回值或未初始化的状态。
  • ‌""‌

    • 指向合法的空字符串(仅含终止符 ‘\0’)。
    • ‌可安全操作‌(如 strlen(“”) 返回 0)。
    • 典型用途:表示逻辑上的“空值”而非“无值”。

‌3. 使用场景对比‌
‌场景1:函数返回值

const char* get_error_msg(int code) {if (code == 0) return NULL;  // 无错误消息if (code == 1) return "";    // 空错误消息(合法但无内容)return "Error occurred";
}

NULL:表示“无消息”
“”:表示“有消息但内容为空”

场景2:字符串处理

void print_str(const char *s) {if (s == NULL) {printf("NULL input\n");} else if (s[0] == '\0') {printf("Empty string\n");} else {printf("%s\n", s);}
}

输入 NULL → 输出 NULL input
输入 “” → 输出 Empty string

‌场景3:默认值初始化

char *log_msg = NULL;   // 默认未记录日志
char *user_input = "";  // 默认空输入(避免NULL解引用崩溃)

‌4. 操作安全性

操作NULL 结果“” 结果
‌strlen(str)段错误返回 0
‌strcpy(dest, str)段错误复制 ‘\0’
‌‌printf(“%s”, str)段错误输出空(无崩溃)

‌5. 总结‌
‌- 用 NULL 当‌:

    • 需要明确表示“无值”或“无效”。
    • 作为错误返回值或未初始化状态。
      ‌- 用 “” 当‌:
    • 需要安全处理字符串操作(避免NULL检查)。
    • 表示逻辑上的“空字符串”而非“无字符串”。

关键区别‌:NULL 是“指针无意义”,“” 是“指针有意义但内容为空”。

char *str = NULL 和 char str[] = {} 区别

在C语言中,char *str = NULL和char str[] = {}有本质区别,主要体现在内存分配、可修改性和使用场景上:

‌1. 内存分配方式

特性char *str = NULLchar str[] = {}
‌‌类型指针(未指向有效内存)数组(自动分配栈内存)
‌内存区域无实际分配栈空间(通常可读写)
大小指针大小(如4/8字节)1字节(仅含\0)

‌2. 核心区别‌

  • ‌char *str = NULL‌

    • 定义了一个未初始化的‌指针变量‌,值为0x0
    • ‌不能直接操作内容‌(解引用会崩溃,如str[0]触发段错误)
    • 典型用途:动态内存分配的占位符或错误标识
  • ‌char str[] = {}‌

    • 定义了一个‌空字符数组‌,实际包含1字节的’\0’
    • ‌可安全操作内容‌(如str[0] = 'a’修改栈内存)
    • 典型用途:局部缓冲区的空初始化

3. 操作对比‌
‌示例代码

#include <stdio.h>int main() {char *ptr = NULL;    // 指针未指向有效内存char arr[] = {};     // 空数组(含'\0')// 操作测试printf("ptr size: %zu\n", sizeof(ptr));  // 输出指针大小(如8)printf("arr size: %zu\n", sizeof(arr));  // 输出1(含'\0')// arr[0] = 'a';     // 合法(修改栈内存)// ptr[0] = 'a';     // 崩溃(解引用NULL)return 0;
}

关键操作安全性

操作NULL 结果{} 结果
sizeof返回指针大小返回1(含\0)
下标访问(如[0])段错误可读写
strlen段错误返回0

4. 使用场景

‌用 char *str = NULL 当‌:

  • 需要后续动态分配内存(如str = malloc(10))

  • 作为函数参数表示“未初始化”状态

    用 char str[] = {} 当‌:

  • 需要局部空字符串缓冲区

  • 避免指针解引用风险时(如嵌入式开发)

‌5. 特殊注意

C99/C11标准中,char str[] = {}是‌非标准语法‌(但部分编译器支持),更规范的写法是:

char str[] = "";  // 标准写法,等效含'\0'的空数组

若需明确空数组初始化,建议使用:

char str[1] = {0};  // 显式初始化为0

总结‌
NULL指针表示“无内存关联”,而空数组{}是“已分配的可操作内存”。前者需动态分配后使用,后者直接具备栈内存安全性。

char *str = “” 和 char str[] = {} 区别

在C语言中,char *str = ""和char str[] = {}有以下核心区别:

1、‌内存分配与生命周期‌
char *str = “”:指针指向只读数据段的空字符串常量(.rodata段),生命周期为整个程序运行期
char str[] = {}:数组分配在栈空间(自动存储期),生命周期限于当前作用域
‌2、可修改性‌
char *str = “”:内容不可修改(尝试修改会导致未定义行为)
char str[] = {}:内容可修改(栈内存可读写)
3、‌语法有效性‌
char *str = “”:标准C语法
char str[] = {}:非标准语法(部分编译器扩展支持),更规范的写法是char str[] = ""或char str[1] = {0}
4、‌sizeof行为‌
sizeof(str)在指针情况下返回指针大小(如8字节)
sizeof(str)在数组情况下返回实际分配大小(空数组为1字节,含’\0’)
‌5、典型使用场景‌
指针形式常用于定义全局字符串常量
数组形式常用于局部可修改缓冲区

注意:空数组初始化{}在C99/C11中不是标准语法,建议改用""或{0}明确初始化。

char *str = “” 和 const char *str = “” 区别

在C语言中,char *str = ""和const char *str = ""的关键区别在于‌类型安全性和编译器约束‌,具体对比如下:

1. 本质区别

特性char *str = “”const char *str = “”
‌类型修饰普通指针常量指针
‌内容可修改性语法允许修改(但实际会引发未定义行为)明确禁止修改(编译器报错)
编译器检查无保护强制类型检查

2. 实际表现‌

‌示例代码

char *p = "";         // 无const修饰
const char *cp = "";  // 有const修饰// p[0] = 'a';       // 编译通过,但运行时可能崩溃(字符串常量区不可写)
// cp[0] = 'a';      // 直接编译报错(const保护)

关键差异‌
‌char *str‌

  • 仅表示指向字符的指针,不承诺指向的内容是否可改
  • 若指向字符串常量(如""),尝试修改会导致‌未定义行为‌(通常是段错误)

const char *str‌

  • 明确告知编译器指向的内容不可修改
  • 任何修改尝试会触发‌编译时错误‌,提前暴露问题

‌3. 使用场景建议‌
‌用 char * 当‌:

  • 需要兼容旧代码(历史遗留API)
  • 明确知道后续会指向可修改内存(如malloc分配的堆内存)

用 const char * 当‌:

  • 指向字符串常量(如""或字面量)
  • 作为函数参数防止意外修改(如strlen的原型)

‌4. 为什么推荐const版本?‌

‌1、安全性‌:避免意外修改只读数据(如p[0] = 'x’的隐蔽错误)
‌2、可读性‌:明确表达设计意图(“我只读不写”)
‌3、编译器优化‌:const可能帮助编译器生成更优代码

5. 特殊注意‌

  • 以下写法是‌等效‌的(均指向只读空字符串):
const char *s1 = "";
char const *s2 = "";  // const位置不同,但含义相同
  • 但若写成char * const s3 = “”,则表示‌指针本身不可改‌(而非指向内容)。

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

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

相关文章

小程序入门: tab bar 实现多页面快速切换效果

在小程序开发中&#xff0c;tab bar 是实现多页面快速切换的关键组件&#xff0c;能极大提升用户体验。上一篇我们完成了基础配置&#xff0c;今天深入探索&#xff0c;打造更丰富实用的 tab bar 效果。 实现目标 这次要在小程序底部创建包含 “首页”“消息”“联系我们” 三…

Python 数据分析:numpy,抽提,多维切片索引

目录 1 示例代码2 欢迎纠错3 免费爬虫------以下关于 Markdown 编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个…

【向上教育】结构化面试概述.pdf

目 录 第一章 面试须知—面试形式 .......................................................................................................... 1 一、结构化面试 .................................................................................................…

STM32F407控制单个张大头闭环步进电机讲解与梯形加减速(HAL库)

文章目录 硬件连接CubeMX配置**使用TIM5定时器CH3,即PA2作为脉冲控制&#xff0c;PE5控制方向&#xff08;TIM5_CH4是为控制双电机做准备的可以先不配置&#xff09;** 设置占空比为50%,以下为AI讲解重要&#xff01;&#xff01;&#xff01;定时器更新中断脉冲触发原理详解PW…

MongoDB入门学习(含JAVA客户端)

0.序章 致命的面试问题&#xff1a;为什么使用MongoDB&#xff1f; 大型的分布式的文档型数据库&#xff0c;也是NoSQL数据库&#xff08;例如 redis&#xff09; MongoDB适合数据量大而价值又低的这种数据&#xff08;播放进度、评论、弹幕&#xff0c;实时数据的CRUD&…

RedisCache与StringRedisTemplate的深度对比

1. 基本概念 RedisCache ​​定位​​&#xff1a;自定义封装的Redis缓存工具类​​特点​​&#xff1a;通常针对业务场景进行了高层抽象​​典型功能​​&#xff1a; 带过期时间的缓存操作自定义序列化方式业务键前缀管理简化常用操作API StringRedisTemplate ​​定位…

HOOPS Visualize技术详解(二):3D图形系统HOOPS/3DGS的段结构与属性机制

在工业级三维可视化领域中&#xff0c;HOOPS Visualize凭借其高性能和模块化设计被广泛应用于CAD、CAM、仿真、BIM等工程软件中。其中&#xff0c;HOOPS 3D Graphics System&#xff08;简称HOOPS/3DGS&#xff09;是HOOPS Visualize的核心组件&#xff0c;承担着图形场景管理、…

随机化在临床试验中的应用与挑战

一、随机化的核心目的 1.1 控制混杂偏倚 1.1.1 平衡预后因素 确保已知/未知预后因素在组间分布均衡,避免基线不平衡影响结果。 1.1.2 避免选择偏倚 防止研究者或患者主观选择分组,保障组间差异归因于干预。 1.2 保障统计推断有效性 1.2.1 满足独立性假设 满足统计检验…

在C++中#pragma“可选预处理指令的作用“。

文章目录 1. 标准定位&#xff1a;2. 语法形式&#xff1a;3. 常见用途举例4. 为什么用 #pragma&#xff1f;5. 宏里用 __pragma / _Pragma6. 常见误区 在 C/C 里&#xff0c;#pragma 本质上是“可选预处理器指令”&#xff0c;用来告诉编译器在编译某段代码时启用或关闭某些特…

windows系统中docker数据迁移出系统盘

1、关闭docker 2、移动docker数据 找到docker数据目录&#xff0c;一般在C:\Users\61050\AppData\Local\Docker文件&#xff0c;将整个docker目录复制到其他盘&#xff08;例如 D:\Docker&#xff09;&#xff0c;为保证不出错&#xff0c;可以先提前复制一份。 3、创建符号链…

win11电脑突然休眠问题排查

WinR, 输入eventvwr.msc打开事件查看器。找到出现问题的时间点那条数据。会显示原因。首先还是要先排查原因。再去猜测。我因为猜测就直接去了科技市场扫灰加硅来了一个遍。另外还买了散热风扇和金属支架。虽然不知道有没有必要。但是别人是很原因。到头来早上还是发现自动休眠…

安卓开发 lambda表达式

第一步&#xff1a;初学者代码 (没有 Lambda 的“旧”方法) 假设我们有一个简单的需求&#xff1a;执行一个耗时的计算&#xff08;比如网络请求&#xff09;&#xff0c;并在计算完成后&#xff0c;通过一个“回调”来通知我们结果。 1. 定义一个回调接口 这个接口只有一个…

JMeter中变量如何使用?

在性能测试的世界中&#xff0c;Apache JMeter是一把利器&#xff0c;凭借其强大的可扩展性与图形化操作界面&#xff0c;在工业界和开源社区中广受青睐。而“变量的使用”作为JMeter中提高测试灵活性、可维护性和复用性的关键技术点&#xff0c;却常常被初学者忽略或误用。本文…

印度和澳洲的地理因素

研究表明&#xff0c;气温每升高1℃&#xff0c;劳动生产率可能下降1.5%至3%&#xff0c;甚至更多。印度大部分地区夏季高温且湿度较大&#xff0c;有地方60多度&#xff0c;严重限制了劳动效率和农业产出。若印度整体地理位置北移约300公里&#xff0c;平均气温将降低&#xf…

3D Gaussian Splatting

3D高斯溅射&#xff08;3D Gaussian Splatting &#xff09;是一种基于显式三维高斯分布的场景表示与渲染方法。与传统的三维重建技术&#xff08;如多边形网格、点云或隐式神经辐射场NeRF&#xff09;不同&#xff0c;3DGS将场景表示为大量带有属性的3D高斯椭球的集合&#xf…

鸿蒙5:布局组件

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

Flink状态和容错-基础篇

1. 概念 flink的状态和容错绕不开3个概念&#xff0c;state backends和checkpoint、savepoint。本文重心即搞清楚这3部分内容。 容错机制是基于在状态快照的一种恢复方式。但是状态和容错要分开来看。 什么是状态&#xff0c;为什么需要状态&#xff1f; 流计算和批计算在数…

【若依学习记录】RuoYi后台手册——分页实现

目录 若依系统简介 前端调用实现 前端调用举例 后台逻辑实现 若依系统简介 RuoYi 是一个基于 Spring Boot、Apache Shiro、MyBatis 和 Thymeleaf 的后台管理系统&#xff0c;旨在降低技术难度&#xff0c;助力开发者聚焦业务核心&#xff0c;从而节省人力成本、缩短项目周…

从台式电脑硬件架构看前后端分离开发模式

在软件开发领域,前后端分离早已成为主流架构设计理念。它将系统的业务逻辑处理与用户界面展示解耦,提升开发效率与系统可维护性。有趣的是,我们日常生活中常见的台式电脑硬件架构,竟与这一理念有着异曲同工之妙。今天,就让我们从台式电脑的硬件组成出发,深入探讨其与前后…

可观测性的哲学

在现代系统架构中&#xff0c;“可观测性&#xff08;Observability&#xff09;”已不仅仅是一个工程实践&#xff0c;是一种关于“理解世界”的哲学姿态, 还是一种帮助架构演变的认知工具。从柏拉图的“洞穴寓言”出发&#xff0c;我们可以构建起一条从被动接受投影&#xff…