RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 603691
Accepted
MaximPro
MaximPro
Asked:2020-12-15 03:15:25 +0000 UTC2020-12-15 03:15:25 +0000 UTC 2020-12-15 03:15:25 +0000 UTC

char * 和 const char *

  • 772

我决定回到 SI 去读 K&R 的书,我又一次被指针这个话题绊倒了,逻辑上似乎一切都清楚了,但就是这样有char *一些const char *问题。

给个代码,说明个个我都不清楚!

示例 1:

char *pstr = "Hello, world";
*pstr = 'D'; /// При запуске приложения на этом месте вылетит сбой не понятно!
printf(pstr); /// Ну и конечно ничего не выведет, измененную строку я не получу, ой точнее массив из символов

示例 2:

const char *pstr = "Hello, world";
*pstr = 'D'; /// Сбоя не будет и программа вообще не скомпилируется т.к компилятор сообщит что мы не можем изменять наш константный объект
printf(pstr); /// До сюда дело не дойдет

示例 3:

char str[] = "Hello, world";
char *pstr = str;
*pstr = 'D'; /// Все ок мы успешно поменяем наш первый элемент массива
printf(pstr); /// Мы получим это: "Dello, world"

让我们划清所有这些示例:为什么我不能在第一个示例中分别更改每个文字?(我没有像第二个例子那样声明对象常量)

PS第三个例子是给大图看的,如果你输入一个额外的参数,一切正常

c
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-12-15T03:49:14Z2020-12-15T03:49:14Z

    在第一种和第二种情况下,您直接使用字符串文字。

    在 C 中,您无法控制字符串文字的类型 const 限定。此 const 限定由语言唯一定义。C 中字符串文字的类型是char [N]. 尽管字符串文字的类型在技术上不包含限定符const,但字符串文字仍然是不可变(不可修改)的对象。尝试修改字符串文字,就像任何其他不可修改的对象一样,会导致未定义的行为。

    你如何声明你的指针pstr- 有const或没有 - 对字符串文字的类型和属性没有影响。您的指针本身与字符串文字无关。您的指针只不过是对真实对象的访问路径。访问路径的恒定性只不过是自律的一个要素,通常与该路径所通向的对象的恒定性无关。C 语言为您提供了合法创建可修改对象的常量访问路径和不可修改对象的非常量访问路径的方法。

    int a = 42;
    const int *pa = &a;   // константный путь доступа к модифицируемому объекту
    
    const int b = 5;
    int *pb = (int *) &b; // неконстантный путь доступа к немодифицируемому объекту
    

    最终,对象合法修改的可能性仅由对象本身的可修改性精确确定,而不以任何方式取决于访问路径的常量(因为后者很容易消除)。

    鉴于文字是不可变对象,使用非常量指针(如第一个示例)指向字符串文字没有任何意义,即使语言正式允许也是如此。

    在第三个选项中,您不直接使用字符串文字,而是创建自己的可修改数组,该数组仅使用字符串文字的值进行初始化。那些。您的数组包含字符串文字值的独立副本。这是您自己的数组,您可以随意修改它。

    • 12
  2. Vlad from Moscow
    2020-12-15T03:48:47Z2020-12-15T03:48:47Z

    根据C语言标准(6.4.5 String literals)

    7 未指定这些数组是否不同,前提是它们的元素具有适当的值。如果程序试图修改这样的数组,则行为是未定义的。

    也就是说,您不能更改字符串文字,即使它们具有非常量字符数组类型。C 字符串文字具有非常量数组类型的事实是为了 C 程序的向后兼容性。

    因此,在本提案中

    char *pstr = "Hello, world";
    

    用作指针初始值设定项的字符串文字pstr被隐式转换为 类型的指针char *,而不是指向const char *文字第一个字符的类型的指针。

    在 C++ 中,字符串文字具有常量字符数组的类型,这避免了混淆。

    在第三个例子中

    char str[] = "Hello, world";
    char *pstr = str;
    *pstr = 'D';
    

    指针pstr不再处理字符串文字,而是处理用户定义的字符数组。字符串文字仅用于用自己的字符初始化字符数组的元素。由于数组被声明为非常量,因此可以更改其元素。

    • 3
  3. αλεχολυτ
    2020-12-15T03:51:04Z2020-12-15T03:51:04Z

    c的类型安全性不够,并且允许为非常量指针分配字符串文字的地址。左侧的指针不是常量这一事实并不意味着您可以更改它指向的内容。对指针的赋值不会在字符串下创建额外的对象,也不会将右侧复制到其中。

    那。您的查看代码:

    char *pstr = "Hello, world";
    *pstr = 'D';
    

    本质上等同于此(出于演示目的更明显):

    "Hello, world"[0] = 'D';
    

    在这种形式下,即使是gcc也会报告带有适当的警告:

    警告:分配只读位置“你好,世界[0]”

    c标准明确指出,尝试修改字符串文字会导致未定义的行为 (6.4.5/7):

    如果程序试图修改这样的数组,则行为是未定义的。

    • 3
  4. Harry
    2020-12-15T03:24:03Z2020-12-15T03:24:03Z

    根据定义,字符串文字是 const 。它一般可以放在“只读”存储器中。例如,第一个示例中的 VC++ 将跳过代码,不会出现故障 - 但在执行过程中该行不会更改。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5