【问题标题】:tolower() segfault's when trying to assign the returned value a char pointer [duplicate]尝试将返回的值分配给char指针时出现tolower()段错误[重复]
【发布时间】:2020-11-04 21:37:03
【问题描述】:

我正在尝试理解作为指针的黑色巫术魔法,但我无法理解以下情况。 我对getline()的第一个参数的理解比较笨拙,所以我想这都归结为它的类型,这与第二个例子中的单词不同。

以下是加载文件(单词字典)并逐行读取其内容的函数的摘录。为什么 tolower() 在第一个示例中起作用:

int l;
size_t len = 0;
char *word = NULL;

while ((l = getline(&word, &len, fp)) != -1)
{
    for (char *p = word; *p; ++p) *p = tolower(*p);
    // Irrelevant code below
}

但是在第二个示例中,在尝试从第一个字符分配 tolower() 的返回值之后,出现了段错误:

char *word = "POTATO";
for (char *p = word; *p; ++p) *p = tolower(*p);

【问题讨论】:

  • 顺便提一下,当p的类型是char *时,使用tolower((unsigned char) *p)而不是tolower(*p)。当*p 为负但不是EOF 时,C 标准未定义tolower 的行为,并且在某些C 实现中char 的值可能为负。

标签: c undefined-behavior c-strings string-literals tolower


【解决方案1】:

浏览 C 标准(6.4.5 字符串文字)就足够了

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

首先,字符串字面量是具有静态存储时长的字符数组。

例如,在 C 中,字符串文字 "POTATO" 的类型为 char[7]

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    printf( "sizeof( \"POTATO\" ) = %zu\n", sizeof( "POTATO" ) );
    
    return 0;
}

程序输出是

sizeof( "POTATO" ) = 7

用在表达式数组中,有极少数例外(例如,用作运算符 sizeof 的操作数)被转换为指向它们的第一个元素的指针。

所以在这个声明中

char *word = "POTATO";

(仅用于演示目的)可以重写为

char *word = &"POTATO"[0];

用作初始化器的字符串文字被转换为指向其首字母'P'的指针。

为了避免在 C++ 中更改字符串文字的这种错误,与 C 字符串文字相反,它具有常量字符数组类型。

因此在 C++ 中你必须编写

const char *word = "POTATO";

建议在 C 中也使用限定符 const 来声明指向字符串文字的指针。

【讨论】:

    【解决方案2】:

    写下我的问题后,我决定重新检查 getline() 文档。 根据它,第一个参数是 char **lineptr。这意味着它是一个指向 char 的指针。 更具体地说:

    getline() 从流中读取整行,存储地址 包含文本的缓冲区到 *lineptr

    由于我对双指针和一般指针的理解仍然有限,我决定阅读 getline() 的代码,试图了解发生了什么:

    https://dev.w3.org/libwww/Library/src/vms/getline.c

    这是我的理解和对第二个示例的更正,因此它不会出现段错误。

    char word[] = "POTATO";
    for (char *p = word; *p; ++p) *p = tolower(*p);
    

    然后试图真正理解为什么更正有效,我还搜索了 char 数组和 char 指针之间的差异,我发现并阅读了以下内容:

    https://overiq.com/c-programming-101/character-array-and-character-pointer-in-c/

    我学到的是数组的元素可以单独修改。但是字符指针(字符串字面量)不能。

    我认为后者可以做到,但这是不可能的。因此我在第二个例子中犯了错误。 我试图修改 char 指针指向的值,但由于我缺乏对 Black Mojo 的理解而得到了段错误。

    现在我明白了一点,这次旅行很愉快。

    请随时编辑或添加您的见解。

    【讨论】:

      猜你喜欢
      • 2018-07-20
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多