简体   繁体   English

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

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

I made a little function in C which copies a char array.我在 C 中做了一个小函数,它复制了一个char数组。 I didn't want source to be changed, so I put const into the function declaration and body, but it changed.我不想更改source ,所以我将const放入函数声明和主体中,但它更改了。

main.c主文件

#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
}

copy_char.c复制字符.c

#include "copy_char.h"

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

  *dest = 0;
}

copy_char.h复制字符.h

#ifndef COPYCHAR_H
#define COPYCHAR_H

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

#endif /* COPYCHAR_H */

Can anyone explain to me, why did my source char array change from hello to o ?谁能向我解释一下,为什么我的source字符数组从hello变为o

Buffer overrun.缓冲区溢出。 The string source is longer than the memory allocated for dest , so when you copy source to dest you are tromping over memory you didn't intend to.字符串source比为dest分配的内存长,因此当您将source复制到dest您正在遍历您不想要的内存。 Weird things then happen (undefined behavior).然后会发生奇怪的事情(未定义的行为)。

You can make dest big enough by declaring its size to be big enough for "hello":您可以通过将dest的大小声明为足以容纳“hello”来使dest足够大:

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

I didn't want source to be changed, so I put const into function declaration and body.我不想更改源代码,因此我将 const 放入函数声明和主体中。 but, it changed但是,它变了

The const qualifier does not magically protect you from writing where you should not. const限定符并不能神奇地保护您不写不该写的地方。 It's merely a contract between you and the compiler that says "trust me, I am not going to modify the memory pointed to by this pointer".这只是你和编译器之间的契约,上面写着“相信我,我不会修改这个指针指向的内存”。

In your function you are writing data past the end of dest , which is undefined behavior.在您的函数中,您正在写入超过dest末尾的数据,这是未定义的行为。 You should either:你应该:

  1. Pass a maximum length to the function:将最大长度传递给函数:

     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. Stop at either *source == 0 or *dest == 0 :*source == 0*dest == 0处停止:

     void copy_char(const char* source, char* dest) { while(*source != 0 && *dest != 0) { *dest++ = *source++; } *dest = 0; }
  3. Create a big enough dest array and leave the function unchanged.创建一个足够大的dest数组并保持函数不变。

The semantics of the function change depending on which option you choose, which one is the right one is up to you.函数的语义会根据您选择的选项而变化,哪个是正确的取决于您。

What most likely is happening in your case is that it just so happens that source is right past the end of dest , so you overwrite the contents of dest with 'h','e','l','l' , then the first character of source with 'o' and then the second one with '\\0' .在您的情况下最有可能发生的情况是source恰好在dest的末尾之后,因此您用'h','e','l','l'覆盖了dest的内容,然后source第一个字符为'o' ,第二个字符为'\\0' Luckily enough, your program does not crash, and you end up with a valid string in source that is "o" .幸运的是,您的程序没有崩溃,最终在source中得到一个有效的字符串"o" Nonetheless, you should never rely on undefined behavior , whether your program seems to magically work or not.尽管如此,你永远不应该依赖未定义的行为,无论你的程序是否神奇地工作。

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

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