user-0 提问: 问个指针初始化的问题

回复:
user: user-1
content: 引用 6 楼 a30037338 的回复:关于第一段代码和第二段代码， 如果不崩溃只能说你的编译器对这种情况做了一些优化或者你运气好， 这个指针指向的内存刚好可以被你操作。我这里VS2010， GCC-4.4.6版本 两个编译器都会奔溃， 这也是必然的。 char * str ;    //这样仅仅是定义了一个指针， 指针指向哪里， 是未知的。 strcpy(); //这个函数修改了一个未知的指针， 这是不可容忍的错误。不论这个指针是一个普通局部变量，还是结构成员， 没有分配内存的指针是野指针。。。  char * str = (char*)malloc(sizeof(char)*10); //这是c的指针的经典用法。  关于  stu.str又不能输出了， 上面已经说了， 对一个未知的指针操作， 程序崩溃才是必然结果+1,你们怎么都喜欢用野指针呢

user: user-2
content: 另外，野指针是可能指向可读可写区域的，所以你有时能运行成功，不出错。

user: user-2
content: typedef struct __Test {     char *str; }Test_t;   int main(int argc, char *argv[]) {     Test_t stu;     char *str = (char *)malloc(10*sizeof(char));     strcpy(str, "hello 1");     printf("%s\n", str);       stu.str = str;     strcpy(stu.str, "hello 2");     printf("%s\n", stu.str);     return 0; } 试试这样可以输出吗？

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

user: user-4
content: 引用 3 楼 wangjun403 的回复:[quote=引用 2 楼 CharlesSimonyi 的回复:] 使用未初始化指针会产生未定义行为，未定义行为在不同的编译器，不同的平台上会有不同的结果，所以不能做出统一的解释。 比如我这里编译你的代码运行后Debug下报错，Relase下崩溃，均不能正常输出任何内容。 如果感兴趣其背后到底发生了什么可以转到反汇编查看反汇编代码，我这里反汇编后可以看到Debug模式下未初始化的指针都会被编译器初始化为0xcccccccc，从而后面strcpy使用该指针时CRT发现了错误并报错。Relase下该未初始化的指针为0x00000001，从而后面strcpy使用该指针时，触发操作系统的内存访问保护从而程序崩溃结束运行，因为0x00000001的内存是不可访问的。  请问第一个问题 stu.str为什么不提示”未初始化“[/quote]  对于 char *str; 标准地讲，C并没有规定非要产生一个警告（diagnostic message），即使它没有初始化，也没有赋初值。如果C的实现认为它可以检查到这类问题，它可以产生警告，这对C的用户来说是有裨益的，也许还有用户口碑的因素。 对于以上声明，检查可能比较简单，但对其它情况，比如结构内部的指针，C的实现可能要花更多的代价才能检查出问题，这可能是不值得的。所以，C的实现干脆就不能保证它会发现问题。

user: user-5
content: 引用 10 楼 wangjun403 的回复:[quote=引用 8 楼 mymtom 的回复:] 第一段代码会有warning吗？ 第一段有warning，我最奇怪的是第二段没有warning  编译器：MingW4.6[/quote]   typedef struct __Test {     char *str; }Test_t;   int main(int argc, char *argv[]) {     Test_t stu;  //那么请问，这一句都干了什么     strcpy(stu.str, "hello 2");     printf("%s\n", stu.str);     return 0; }

user: user-6
content: 不要相信变量未定义的行为，否则总有一天你会付出很大的代价！ 不要过分相信你的编译器，因为你不可能永远依赖他。就算你依赖他，运行你代码的其他人也不一定会使用它。

user: user-0
content: 引用 8 楼 mymtom 的回复:第一段代码会有warning吗？ 第一段有warning，我最奇怪的是第二段没有warning  编译器：MingW4.6

user: user-7
content: 我在vs2010下试，在debug模式下回崩溃，在release下可以运行 这两种模式下都会有两个warning:一个是说strcpy不安全，建议strcpy_s替换；另一个是：使用了未初始化的局部变量“str”  #include <string> int main(int argc, char *argv[]) { 	char *str; 	strcpy(str, "hello 1"); 	printf("%s\n", str); 	return 0; }   #include <string> typedef struct __Test { 	char *str; }Test_t;   int main(int argc, char *argv[]) { 	Test_t stu; 	strcpy(stu.str, "hello 2"); 	printf("%s\n", stu.str); 	return 0; }

user: user-8
content: 第一段代码会有warning吗？

user: user-9
content: str 和 stu.str没有初始化，也就是所为的野指针，指向的内存地址是不确定(有可能是已分配的内存空间，即使是没分配的内存空间，也可能以后被分配系统分配给其他变量)，容易造成程序崩溃； str是单独的指针变量，没有初始化所以有警告 stu.str因为结构stu定义的变量，而stu.str是结构体stu的成员变量，所以编译器没给出警告  stu.str不能输出是正常的，原因如上，野指针指向的地址是不确定

user: user-10
content: 关于第一段代码和第二段代码， 如果不崩溃只能说你的编译器对这种情况做了一些优化或者你运气好， 这个指针指向的内存刚好可以被你操作。我这里VS2010， GCC-4.4.6版本 两个编译器都会奔溃， 这也是必然的。 char * str ;    //这样仅仅是定义了一个指针， 指针指向哪里， 是未知的。 strcpy(); //这个函数修改了一个未知的指针， 这是不可容忍的错误。不论这个指针是一个普通局部变量，还是结构成员， 没有分配内存的指针是野指针。。。  char * str = (char*)malloc(sizeof(char)*10); //这是c的指针的经典用法。  关于  stu.str又不能输出了， 上面已经说了， 对一个未知的指针操作， 程序崩溃才是必然结果

user: user-11
content: 楼主试图从内存的角度来理解程序试试,看看你的每一步,对应内存都发生什么.

user: user-12
content: 跟编译器有关！可以让它提示也可以不提是警告

user: user-13
content: strcpy修改的是对象，而不是指针本身，一个指针不初始化就是一个野指针，用strcpy去修改一个野指针所指的对象是非常危险的，运行时可能发生无法预估的错误。

user: user-14
content: typedef struct __Test { 	char *str; }Test_t;  int main(int argc, char *argv[]) { 	Test_t stu; 	strcpy(stu.str, "hello 2"); 	printf("%s\n", stu.str); 	return 0; }    第二段代码在我这里编译器VC2010也是会报出warning提示的，仍然是编译器问题。

user: user-0
content: 引用 2 楼 CharlesSimonyi 的回复:使用未初始化指针会产生未定义行为，未定义行为在不同的编译器，不同的平台上会有不同的结果，所以不能做出统一的解释。 比如我这里编译你的代码运行后Debug下报错，Relase下崩溃，均不能正常输出任何内容。 如果感兴趣其背后到底发生了什么可以转到反汇编查看反汇编代码，我这里反汇编后可以看到Debug模式下未初始化的指针都会被编译器初始化为0xcccccccc，从而后面strcpy使用该指针时CRT发现了错误并报错。Relase下该未初始化的指针为0x00000001，从而后面strcpy使用该指针时，触发操作系统的内存访问保护从而程序崩溃结束运行，因为0x00000001的内存是不可访问的。  请问第一个问题 stu.str为什么不提示”未初始化“

user: user-14
content: 使用未初始化指针会产生未定义行为，未定义行为在不同的编译器，不同的平台上会有不同的结果，所以不能做出统一的解释。 比如我这里编译你的代码运行后Debug下报错，Relase下崩溃，均不能正常输出任何内容。 如果感兴趣其背后到底发生了什么可以转到反汇编查看反汇编代码，我这里反汇编后可以看到Debug模式下未初始化的指针都会被编译器初始化为0xcccccccc，从而后面strcpy使用该指针时CRT发现了错误并报错。Relase下该未初始化的指针为0x00000001，从而后面strcpy使用该指针时，触发操作系统的内存访问保护从而程序崩溃结束运行，因为0x00000001的内存是不可访问的。

user: user-15
content: 我也很困惑，昨天编了个sub_str()函数想仿造Perl的substr，死活出不了结果。。。