繁体   English   中英

带有 char[] 的 C 指针,忽略 const 关键字?

[英]C pointer with char[], const keyword ignored?

我在 C 中做了一个小函数,它复制了一个char数组。 我不想更改source ,所以我将const放入函数声明和主体中,但它更改了。

主文件

#include "copy_char.h"
#include <stdio.h>

int main(void)
{
  char source[] = { 'h', 'e', 'l', 'l', 'o', 0 };
  char dest[] = { 'a', 'b', 'c', 0 };

  printf("%s\n", source); // hello
  printf("%s\n", dest); // abc

  copy_char(source, dest);
  
  printf("%s\n", source); // o (?) - why did this change? 
  printf("%s\n", dest); // hello
}

复制字符.c

#include "copy_char.h"

void copy_char(const char* source, char* dest)
{
  while(*source != 0)
  {
    *dest++ = *source++; 
  }

  *dest = 0;
}

复制字符.h

#ifndef COPYCHAR_H
#define COPYCHAR_H

void copy_char(const char* source, char* dest);

#endif /* COPYCHAR_H */

谁能向我解释一下,为什么我的source字符数组从hello变为o

缓冲区溢出。 字符串source比为dest分配的内存长,因此当您将source复制到dest您正在遍历您不想要的内存。 然后会发生奇怪的事情(未定义的行为)。

您可以通过将dest的大小声明为足以容纳“hello”来使dest足够大:

char dest[6] = { 'a', 'b', 'c', 0 };

我不想更改源代码,因此我将 const 放入函数声明和主体中。 但是,它变了

const限定符并不能神奇地保护您不写不该写的地方。 这只是你和编译器之间的契约,上面写着“相信我,我不会修改这个指针指向的内存”。

在您的函数中,您正在写入超过dest末尾的数据,这是未定义的行为。 你应该:

  1. 将最大长度传递给函数:

     void copy_char(const char* source, char* dest, size_t maxlen) { size_t i; for (i = 0; i < maxlen && source[i]; i++) { dest[i] = source[i]; } dest[i] = 0; }
  2. *source == 0*dest == 0处停止:

     void copy_char(const char* source, char* dest) { while(*source != 0 && *dest != 0) { *dest++ = *source++; } *dest = 0; }
  3. 创建一个足够大的dest数组并保持函数不变。

函数的语义会根据您选择的选项而变化,哪个是正确的取决于您。

在您的情况下最有可能发生的情况是source恰好在dest的末尾之后,因此您用'h','e','l','l'覆盖了dest的内容,然后source第一个字符为'o' ,第二个字符为'\\0' 幸运的是,您的程序没有崩溃,最终在source中得到一个有效的字符串"o" 尽管如此,你永远不应该依赖未定义的行为,无论你的程序是否神奇地工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM