本帖最后由 major_lyu 于 2020-2-29 13:20 编辑
首先正确的代码是这样的:
具体错在那看代码注释
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h> // strcpy()函数头文件
void catstr(char *dest, char *src);
void main()
{
char *dest, *src = "help you ?";
//if ((dest = (char *)malloc(80)) ==NULL)
if (!(dest = (char *)malloc(80)) )
{
printf("no memory\n");
exit(1); //错误,退出程序
}
//dest = "Can I"; // 这种赋值方式是将指针dest指向了一个字符串常量,而不是将字符串的内容放进上面分配的空间。
strcpy(dest, "Can I "); // 要将一个字符串放到一个分配好的字符数组中或者字符串指针对应的内存空间中,应该采用strcpy函数,具体怎么用自己去查
catstr(dest, src);
puts(dest);
free(dest); // malloc 与free通常是成对出现的, 分配的空间在用完后要用free()回收。不然程序退出时指针dest已经无效了,但是dest指向的空间还没有被回收,会造成内存泄露。
}
void catstr(char *dest, char *src)
{
while (*++dest)
; //移动指针,让指针指向字符串的末尾
while (*dest++ = *src++)
;
}
你所问的问题:
第一个问题这是书上的源代码,编译没有问题,但是运行没反应,帮忙看下错在哪?
你之前的代码有问题,由于采用了dest="Can I "这种赋值,将dest指向了一个字符串常量,当dest指向字符串“Can I ”最后一个字符后面的空间时,会出现访问越界,因此会提示“段错误”或者“Segment Fault",然后程序退出。所以你之前的代码虽然能编译通过,但是运行时并不是没反应,而是遇到地址越界,打印了“段错误”或者“Segment Fault",然后退出了。
第二个问题就是,为什么一开始两个指针变量中src在定义就可以赋予字符串首地址,
而dest在申请内存后,才可以赋地址。书上说例:char *str; scanf("%s",str);这种给字符指针变量赋值,
是很危险的,应申请分配内存,取得确定地址。那么是不是也可以推测src这种赋值也是很危险的?
或者说这两种赋值方法有什么区别?请指教
char* src="Help you"这种定义方式叫作字符串初始化。是将指针src指向内存中的一个字符串常量,这种字符串常量是放在内存的常量区的,这个牵扯到内存管理的东西,比较复杂。你只需要知道这种赋值的过程是,编译器在程序编译的过程中在常量区开辟一个容量与所指示的字符串长度相等的空间,并将字符串放进去,然后让src指针指向这个空间。
char* dest.这种定义方式之定义了一个指针变量,他所指示的空间时不确定的,在没有对其进行赋值之前,其指示的地址是未知的,所以对其指示的内存进行操作是不安全的。例如:dest可能指示的地址是操作系统的正在使用的一段内存,改变dest指示的内存空间的值会造成未知的后果。只有在通过malloc分配一段空闲的内存空间,并把这段空间的起始地址赋值给dest之后,dest所指示的空间才可以安全的使用。
同样char *str; scanf("%s", str);这种操作并不是给指针变量str赋值,而是在没有给str分配确定空间的时候忘str指示的空间写入字符串,这个时候,str可能某个随机的数,它所指示的空间有可能正在被其他进程或者程序使用,更改其内部数据会造成其他程序的数据错误的。
char *src = "Help you "这种赋值是非常安全的,原因其空间时程序编译时就分配好的。
第三个问题*++dest改为*dest++有什么不一样
*++dest 是先对dest自加然后去其内容;执行步骤是 dest=dest+1; --->*dest;
*dest++ 是先取内容再自加。执行步骤是:*dest; --->dest=dest+1;
例如dest = a[0]
*++dest = x 的结果是 dest = 0+1; a[1] = x;
*dest++ = x 的结果是 a[0] =x; dest = 0+1