user-0 提问: 菜鸟关于字符串函数strcpy的疑惑

回复:
user: user-1
content: 引用char *p;  这里p是一个指针变量，但没有指向任何地址，很多编译器将他直接置为NULL。  引用strpy(p,"abc");  如果编译器直接初始化为NULL，那么函数到p=0，会报你说的错误； 如果p初始化为进程内的地址，那么会出现不可预期的运行错误； 如果p初始化为进程外的地址，那运行时会报内存泄露错误。

user: user-2
content: 无论p的初始值为多少。总是存在于内存中的地址。不妨碍复制和显示。  你的思想主要错在认为系统中有且只有你自己写的一个程序在运行【即使是这样，比如在纯DOS操作系统或者Linux的文本界面中也是危险的】  对于一个指针，是否初始化，都指向内存中的“有效”地址这种想法是不对的 根据你使用的编译器、IDE不同，可能会有不同的初始值 比如：0xCC、0x00、0xFF等 【http://blog.csdn.net/zhandoushi1982/article/details/6275429】【VC 0xCC的例子】  即便一个指针指向着内存中的有效地址，如果不控制它的数据类型【指针所指向内存的大小】，也很容易“越界访问”到别的程序或者自己程序的别的代码段的领域里去，会造成系统或者程序崩溃   形象点说：指针变量就像你的手指，内存数据就像一座大楼下面各家整齐的邮箱 如果是派发小广告：那么首先得把手指指向第一个邮箱，然后指定好邮箱大小，投递，下一个，判断是否是最后一个邮箱，继续投递 未经初始化的指针的行为，很像闭着眼睛随手一指，往里面投递【写入数据】。哦卖糕，我的手指【指针变量】怎么指向的不是邮箱，而是电梯，哦卖糕，怎么扔了一电梯的广告……

user: user-3
content: C标准的解释最权威，但不是那么通俗。我再结合标准补充几句： N1570，6.5.3.2： If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.102) ------------ 102) Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.  楼上的同学只注意到NULL指针，以及p所指向的对象的生存期结束之后的情况（我在前面的发言里也提及了），但没有注意到地址未正确对齐的情况。指针的值也是无效的情况也包括未对齐。

user: user-4
content: 定义一个指针，如果上面代码位于函数内部，那么它的存储空间在栈帧上分配。如果不对其初始化，那么它可能是上个函数调用时使用栈帧时遗留下的数据或者第一次使用时的随机值或0。 对于一个不确定的值，它不一定是有效的进程地址空间内的地址。因此不一定可以用来解引用，之所以说不一定，是因为假如碰巧这个值处于进程地址空间之内，那么就可以正常访问，这种情况发生时属于一种安全漏洞。更多情况下是无效的值，访问时产生SIGSEGV- （invalid memory reference）信号，又称为“段错误”，即进程解引用了一个无效的内存。这意味着一个bug诞生了，最常见的操作是解引用NULL指针。此外，进程对此信号默认操作是中止程序的运行！ 你的问题可以用进程的地址空间来解答。每个进程都有自己的地址空间，OS为了自己的安全，它不会让进程访问所有的地址，而是一段固定的区间。 大致给你说这么多吧，如果想详细了解，自己多多学习研究吧！ 如果有不当之处，请大神指明，谢谢！

user: user-3
content: 按C标准说法，如果一个左值实际上并未指示一个对象，或者引用一个过了生存期的对象，行为是未定义的； 生存期由存储期决定； C有静态、自动和指派三种存储期，以p为例，p自身可以具有静态或自动存储期，但是： p = malloc (/* ... */);    //p指向的对象具有指派存储期 p = a;    //若a是文件作用域，则p指向的对象具有静态存储期，若a在块内声明，则p指向的对象具有自动存储期。 检查你的程序，若p指向的对象与此都不符，则它符合上面第一行的说法，行为自然为定义。

user: user-5
content: p这个变量是存在的 ，p存储的地址未赋值， 访问p的存储值值时出现错误。系统为了保护，很多地址不能访问使用的。

user: user-6
content: 引用 楼主 I_better 的回复:char *p; strpy(p,"abc"); puts(p);  这里会报错，书中解释为，p未初始化。所以“abc”被复制到任何地方 应改为 char *p; char b[50]; p=b; strpy(p,"abc"); puts(p);  而我的理解：无论p的初始值为多少。总是存在于内存中的地址。不妨碍复制和显示。 求问我的思想错在哪里  与其说是p未初始化，更准确的说是，LZ没有为p分配地址空间。

user: user-7
content: 因为p指向的内存不是你自己分配的，而是随意乱指，那么你执行strcpy会把p所指向的内存原来的数据给覆盖掉，如果那片区域是别的程序正在使用的，那就可能会让别的程序出错了，因此为了安全起见，不应该这样做。

user: user-8
content: C语言是一个过程性语言，程序执行的每一个状态都要注意，正如1楼说的那样别的函数调用时，可能会改变数据，所以指针最好要初始化一下

user: user-9
content: 这个字符串也是保存在常量区中 "也“字要去掉

user: user-9
content: char *p; 这句仅仅是告诉编译器留出4个字节来保存地址，这个地址并没有指向任何内存区域，所以没有办法往指针p复制字符。另外即使p指向字符串，比如  char *p = "hello"，这个字符串也是保存在常量区中，不能被修改。 char a[30] 声明了一块内存空间，大小30字节，所以能用strcpy来向其中复制字符串。

user: user-10
content: 其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

user: user-11
content: 你的理解没有错， 可是既然没有定义的值，是不是乱拷贝呢，你的不知道拷贝到内存的哪里了？如果那快内存是操作系统的代码呢，那操作系统不就被你破坏了吗,所以说能复制，但是操纵系统 不让你复制． #include<stdio.h> #include<stdlib.h> #include<string.h>  int main() { 	char *p; 	p = (char *)malloc(sizeof(char) * 10);  	strcpy(p,"asdfg"); 	puts(p); 	exit(0); }

user: user-12
content: 问题就出在"无论p的初始值为多少。总是存在于内存中的地址"上.当p使用的地址是另外程序使用时,就有可能被写入数据,结果就可能不是你所希望的"abc"了,所以,使用指针必须要初始化.