理解 char *、char[] 和 strcpy()

Posted

技术标签:

【中文标题】理解 char *、char[] 和 strcpy()【英文标题】:Understanding char *, char[] and strcpy() 【发布时间】:2014-10-19 14:34:39 【问题描述】:

我的理解如下:

char * 指向一个字符串常量,修改它指向的数据是未定义的。但是,您可以更改它指向的位置。

char[] 指的是可以更改的内存块。您可以更改其内容,但不能更改其引用的内容。

strcpy(dest, src)src 复制到dest

我的问题是,将strcpy()dest 一起使用是不正确的char * 已经指向某些东西(因为我相信旧内容将被@覆盖987654329@ - 这是未定义的行为)?

例如:

char *dest = malloc(5);
dest = "FIVE";

char *src = malloc(5);
src = "NEW!";

strcpy(dest, src); /* Invalid because chars at dest are getting overwritten? */

【问题讨论】:

char * points to a string constant - 不。适当设置的char * 指向char。无论是char 的序列是否适当地以nulchar 结尾,都是它处理的数据的产物。而且它不是恒定的。 array(在您的列表中:char[])的一般描述更接近现实。一个指针持有一个地址;一个数组一个地址。 首先,char * 是一个指向 char 的指针。在 C 中,字符串是由零字符终止的字符序列,因此通常 char * 指向此类字符串的开头。但它也可以指向一个缓冲区的开始,该缓冲区旨在接受这样的字符串。如果字符串不是文字,可以修改。 @WhozCraig "数组是地址" - 呃,数组个地址 数组不是地址;它们是由非零元素组成的对象 @user93353 我知道我的理解力很差,我是个初学者。学习 C 作为我的第一语言很难。 【参考方案1】:

很遗憾,您的理解并不完全正确。

char * 指向字符数据,由于其中没有const,因此您可以写入指向的数据。

但是,完全可以这样做:

char *a = "hello";

它为您提供了一个指向只读数据的读/写指针,因为字符串文字存储在只读内存中,但语言的语法并不“认为”为常量。

上面最好写成:

const char *a = "hello";

为了更清楚地说明您不能修改a指向的数据。

另外,您将malloc() 和分配混合的示例是错误的。

这个:

char *dest = malloc(5);
dest = "FIVE"; /* BAD CODE */

是糟糕的代码,你不应该这样做。它只是用指向字符串"FIVE" 的指针覆盖dest 返回的指针,该字符串作为字符串文字存在于(同样是只读的)内存中的某处。

用字符串数据初始化新分配的内存的正确方法是使用strcpy()

char *dest = malloc(5);
if(dest != NULL)
  strcpy(dest, "five");

请注意,检查malloc() 的返回值是个好主意。

对同一个内存进行多次写入是没有问题的,这是 C 语言中一个非常基本的想法;变量代表内存,可以通过“覆盖”在不同时间赋予不同的值。

一些简单的事情:

int a = 2;

printf("a=%d\n", a);
a = 4;
printf("a=%d\n", a);

证明了这一点,它当然也适用于字符串,因为它们只是内存块。

您可以扩展上述基于malloc() 的示例:

char *dest = malloc(5);
if(dest != NULL)

  strcpy(dest, "five");
  printf("dest='%s'\n", dest);
  strcpy(dest, "four");
  printf("dest='%s'\n", dest);
  strcpy(dest, "one");
  printf("dest='%s'\n", dest);

它会打印出来:

dest='five'
dest='four'
dest='one'

【讨论】:

char *a = "hello"; 向后兼容性实际上不受欢迎的情况 “很遗憾,您的理解并不完全正确。”认为这样。我是来学习的,我不希望是正确的:) 所以使用char *a = "hello" 将“hello”存储在只读内存中,但指向它的指针允许您修改内容?修改内容哪个是违法的,对吧? @CSStudent 对!有点奇怪。 我得出了相同的结论,但有更多的试验和错误以及测试代码 sn-ps。如果我早点找到这个答案就好了:)【参考方案2】:

我的理解如下:

char * 指向一个字符串常量,修改它指向的数据是未定义的。但是,您可以更改它指向的位置。

这里你指的是一个表达式

char * string = "mystring";

你说得对,string[1]='r'; 是未定义的。但这不是因为char *,而是因为涉及的字符串文字以某种方式将其放入只读内存中。

比较一下

char string[] = "mystring";

我在 RAM 中定义了一个数组,将所述字符串放入其中。这里允许string[1] = 'r';,因为我们在正常的数据内存中。

这似乎支持你的假设,但请接受:

char string[] = "mystring";
char * string2 = string;

这里string2[1] = 'r'; 是有效的,因为它指向的位置也可以写入。

char[] refers to a block of memory that you can change its contents but not what it refers to.

是的,因为名称只是变量的名称,而不是指针。

strcpy(dest, src) copies src into dest.

没错。

我的问题是,将 strcpy() 与 dest 一起使用是否不正确 char * 已经指向某些东西(因为我相信旧的 内容将被 strcpy() 覆盖 - 这是未定义的 行为)?

这取决于“已经指向某物”的意思...

例如:

char *dest = malloc(5);
dest = "FIVE";

char *src = malloc(5);
src = "NEW!";

strcpy(dest, src); /* Invalid because chars at dest are getting

覆盖? */

这里你又把几件事搞混了。

首先,您有dest 指向一个全新的内存块。之后,你让它指向其他你不能写的地方,这块内存就丢失了(内存泄漏)。

src 也是如此。

所以strcpy() 失败了。

你可以的

char *dest = malloc(5);

char *src = "NEW!";

strcpy(dest, src);

这里dest指向一个可写的地方,src指向有用的数据。

【讨论】:

感谢您的详细回答。我所说的“已经指向某事”的意思是,如果我删除了mallocs 并且只有char *dest = "FIVE"char *src = "NEW!" 然后我使用了strcpy(),那是合法的还是strcpy() 覆盖了dest 指向? "或者是 strcpy() 覆盖了 dest 指向的字符串" 是的,这就是它的意思。它获取一个地址,尝试写入它,但是当它不允许在那里写入时,它会导致未定义的行为(UB)。 所以如果我有dest 指向来自malloc 的新内存块,我可以在没有UB 的情况下使用strcpy() @CSSStudent 是的,这就是它的用途。但你也可以char dest[10]; strcpy(dest, "DATA");【参考方案3】:

快速分析:

char *dest = malloc(5);
// 'dest' is set to point to a piece of allocated memory
// (typically located in the heap)
dest = "FIVE";
// 'dest' is set to point to a constant string
// (typically located in the code-section or in the data-section)

你给变量dest赋值了两次,很明显,第一次赋值没有意义。

就像写作:

int i = 5;
i = 6;

最重要的是,您“丢失”了分配内存的地址,因此您以后将无法释放它。

【讨论】:

【参考方案4】:

char* 是指向内存地址的指针,因此您可以修改该地址中包含的信息。

char* 和 char[] 的区别在于 char[] 不是动态的,你不能改变它的大小。此外,char * 指向堆中的地址,而 char[] 存储在程序的堆栈中。

您可以将 strcpy 与指针和数组一起使用,它会起作用,因为两者的数据都可以被覆盖。

【讨论】:

“char[] 不是动态的”,并不完全正确。您可以使用 VLA,或者数组是动态分配的结构的一部分。最好是更准确地表达你的断言,而不是仅仅给出关于“char []”的笼统陈述。那或使用代码示例来澄清。

以上是关于理解 char *、char[] 和 strcpy()的主要内容,如果未能解决你的问题,请参考以下文章

个人理解的int数组和char数组

strcpy()strncpy()和memcpy()对比

在 char 指针上使用 strcpy 时程序中止? (在 char 数组上工作正常)

在strcpy之后具有重复值的char []

重写strcpy函数,以实现strcpy的功能

实现strcpy函数