下面的C代码编译并运行,但它是未定义的吗?
我发布了一个关于我之前在这个问题中遇到的一些指针问题的问题: 从一些评论中,我相信:下面的C代码编译并运行,但它是未定义的吗?,c,pointers,undefined-behavior,C,Pointers,Undefined Behavior,我发布了一个关于我之前在这个问题中遇到的一些指针问题的问题: 从一些评论中,我相信: #include <stdlib.h> #include <stdio.h> int main(){ int *p; *p = 1; printf("%d\n", *p); return 0; } int i; int *p; p = &i; #包括 #包括 int main(){ int*p; *p=1; printf(“%d\
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p;
*p = 1;
printf("%d\n", *p);
return 0;
}
int i;
int *p;
p = &i;
#包括
#包括
int main(){
int*p;
*p=1;
printf(“%d\n”,*p);
返回0;
}
这是一种未定义的行为。这是真的吗?我一直都这样做,甚至在我的C课程中也看到过。
然而,当我
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p=NULL;
*p = 1;
printf("%d\n", *p);
return 0;
}
#包括
#包括
int main(){
int*p=NULL;
*p=1;
printf(“%d\n”,*p);
返回0;
}
在打印p
的内容之前(在*p=1;
行之后),我遇到了seg故障。这是否意味着我应该一直malloc
在任何时候为指向的指针赋值
如果是这样,那么为什么char*string=“这是一个字符串”
总是有效
我很困惑,请帮帮我 是,执行
int*p*p=1代码>是未定义的行为。您正在解除对未初始化指针的引用(访问它所指向的内存)。如果它能工作,那只是因为p
中的垃圾恰好是某个内存区域的地址,该区域是可写的,并且其内容不够关键,当您重写它们时不会立即导致崩溃。(但您仍然可能损坏了一些重要的程序数据,导致了稍后才会注意到的问题…)
如此明显的例子应该会触发编译器警告。如果没有,请找出如何调整编译器选项。(在gcc上,请尝试-Wall-O
)
指针必须指向有效内存才能解除引用。这可能是由malloc
分配的内存,也可能是现有有效对象的地址(p=&x;
)
char*string=“这是一个字符串”代码>非常好,因为这个指针不是未初始化的;你初始化了它!(字符字符串中的*
是其声明的一部分;您没有取消对它的引用。)具体来说,您使用一些内存的地址初始化了它,您要求编译器保留这些内存并用字符填充这是一个字符串\0
。这样做之后,您就可以安全地取消对该指针的引用(尽管只用于读取,因为写入字符串文本是未定义的行为)
这是一种未定义的行为。这是真的吗
当然是。它看起来就像是在你的系统上用你尝试过的东西工作,但是你正在执行一个无效的写操作。由于写入无效,您首先将p
设置为NULL
的版本是segfaulting,但在技术上它仍然是未定义的行为
您只能写入已分配的内存。如果您不需要指针,最简单的解决方案是只使用常规的int
int p = 1;
一般来说,尽量避免使用指针,因为使用自动变量要容易得多
您的char*
示例之所以有效,是因为C语言中字符串的工作方式——内存中的某个地方有一块带有序列“thisastring\0”的内存块,您的指针指向该块。但这将是只读内存,尝试更改它(即,string[0]='T';
)是未定义的行为。这是:
int *p;
*p = 1;
是未定义的行为,因为p
没有指向任何地方。它未初始化。因此,当你试图去引用p
时,你实际上是在向一个随机地址写入数据
这意味着,无法保证该计划将起到什么作用。它可能会崩溃,可能会输出奇怪的结果,或者看起来工作正常
这也是未定义的行为:
int *p=NULL;
*p = 1;
因为您正在尝试取消对空指针的引用
这项工作:
char *string = "this is a string" ;
因为您正在使用字符串常量的地址初始化string
。这和另外两个案子不一样。实际上与此相同:
char *string;
string = "this is a string";
请注意,此处未取消对字符串的引用。指针变量本身被赋值。带行
char *string = "this is a string";
您正在使指针字符串
指向只读内存中包含字符串“这是一个字符串”
的位置。编译器/链接器将确保此字符串将被放置在适合您的位置,并且指针string
将指向正确的位置。因此,可以保证指针字符串指向有效的内存位置,而无需您采取任何进一步的操作
然而,在代码中
int *p;
*p = 1;
p
未初始化,这意味着它未指向有效的内存位置。因此,取消引用p
将导致未定义的行为
不必总是使用malloc
使p
指向有效的内存位置。这是一种可能的方法,但还有许多其他可能的方法,例如:
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p;
*p = 1;
printf("%d\n", *p);
return 0;
}
int i;
int *p;
p = &i;
现在p
也指向一个有效的内存位置,并且可以安全地解除引用。请考虑以下代码:
#include <stdio.h>
int main(void)
{
int i=1, j=2;
int *p;
... some code goes here
*p = 3;
printf("%d %d\n", i, j);
}
#包括
内部主(空)
{
int i=1,j=2;
int*p;
…这里有一些代码
*p=3;
printf(“%d%d\n”,i,j);
}
将语句*p=2代码>写入i
、j
,还是两者都不写入?如果p
指向该对象,它将写入i
或j
,但如果p
指向其他地方,则不会写入。如果代码的..
部分与p
没有任何关系,那么p
可能指向i
,或j
,或stdout
对象中的某个对象,或任何东西。如果恰好指向i
或j
,则写入*p=3代码>可能会影响该对象而不会产生任何副作用,但如果它指向stdout
控件中的信息