Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C指针初始化差异_C_Pointers - Fatal编程技术网

C指针初始化差异

C指针初始化差异,c,pointers,C,Pointers,我是C新手,对指针有一些问题 问题1与以下两个问题有什么区别?哪种方式初始化指针更好?为什么 int *p=NULL; int *p; #包括 void main() { char*s=“你好”; printf(“%p\t%p”,s); //printf(“%p\t%p”,&s)它每次都会给我不可预知的结果 //printf(“%p\t%p”,(void*)&s)这样就可以了 //问题3:为什么? } 问题2:我试着用谷歌搜索%p在做什么。根据我的阅读,它应该打印指针。这意味着它打印指针的

我是C新手,对指针有一些问题

问题1与以下两个问题有什么区别?哪种方式初始化指针更好?为什么

int *p=NULL;
int *p;

#包括
void main()
{
char*s=“你好”;
printf(“%p\t%p”,s);
//printf(“%p\t%p”,&s)它每次都会给我不可预知的结果
//printf(“%p\t%p”,(void*)&s)这样就可以了
//问题3:为什么?
}
问题2:我试着用谷歌搜索
%p
在做什么。根据我的阅读,它应该打印指针。这意味着它打印指针的地址?

1)第一个是初始化(在本例中为
NULL
),第二个只是
p
的声明,作为
int
的指针,在本例中没有为
p
分配初始值。您应该始终希望使用初始化来防止未定义的行为

2) 使用
%p
打印指针时,应强制转换为
void*
(注意在格式说明符中使用该指针的次数过多)。打印
p
点的内存地址。

1)

定义并初始化指向NULL的指针“p”。如果以后忘记为指针分配有效地址,这是初始化指针以获取“Seg Fault”的正确方法

int *p
仅定义具有未知地址的指针“p”。如果在使用指针之前忘记为此指针指定有效值,则某些编译器会通知您此错误,而其他编译器则不会,并且您可能会访问无效地址并获得运行时错误或程序的未定义行为

2) “%p”正在打印指针指向的地址。由于指针包含地址,因此“%p”打印此地址

printf("%p\t%p",s);
因此,第一个“%p”将打印指针“s”指向的地址,即存储字符串“hello”的地址。但是,请注意,您使用了两次“%p”,但您只提供了一个指针来打印其地址!!
大多数编译器不会对此大惊小怪,因为它没有什么效果;但是,尽量避免它。

回答1:

int *p=NULL;
p是指向以NULL初始化的int变量的指针。此处NULL表示指针p未指向任何有效内存位置

int *p;
p是指向int变量的指针。p未初始化。读取未初始化的变量是未定义的行为。(如果尝试使用,一种可能性是它将抛出分段错误)

答复二:


它打印指针的内容。我是指字符串“hello”的基址问题1,这些是指针
p
的定义。一个初始化指向
NULL
的指针,另一个使其未初始化(如果它是函数中的局部变量,而不是全局变量,则默认情况下全局变量初始化为0)。使用
NULL
初始化可能是好的,也可能是坏的,因为编译器可以警告您使用未初始化的变量,并帮助您查找错误。另一方面,编译器无法检测未初始化变量的所有可能用法,因此初始化为
NULL
几乎可以保证在使用时会产生分段错误,然后您可以很容易地使用调试器捕获和调试分段错误。就我个人而言,我会在定义变量时始终进行初始化,如果可能,使用正确的值(如果初始化对于单个语句来说太复杂,请添加一个帮助函数来获取值)

问题2,
%p
打印传递给
printf
的地址值。所以
printf(“%p”,指针)
获取变量
指针的传递值
并打印该值,而
printf(“%p”,&pointer)
(注意这里额外的
)获取变量
指针的传递地址,并打印该地址。
%p
的精确数字格式是实现定义的,它可能只是作为普通数字打印


问题3是关于未定义的行为,因为格式字符串包含的项目比实际传递给
printf
的项目多。简而言之,行为是不确定的,没有“为什么”。更长的答案是,使用机器代码调试器运行应用程序,并在“反汇编”视图中跟踪执行情况,以查看实际发生的情况,并了解原因。请注意,在不同的运行中,结果可能不同,在调试器和正常运行下,行为可能不同,因为内存在不同的运行中可能由于各种原因具有不同的字节值。

主要区别在于,在
*p=NULL
中,NULL是指针指向的预定义标准“位置”。 阅读维基百科

The macro NULL is defined as an implementation-defined null pointer constant, 
which in C99 can be portably expressed as the integer value 0 
converted implicitly or explicitly to the type void*.
这意味着名为
p
的“内存单元”包含NULL宏值。
如果您只写
int*p
,您将使用名称
p
命名内存单元,但该单元是空的。

它打印指针包含的地址,而不是指针变量的地址。“大多数编译器不会对此尖叫,因为它没有效果”。。。如果编译器没有对可检测的
printf
etc格式字符串错误发出警告,那么您需要提高警告级别<代码>-Wall-Wextra
是gcc和clang的良好开端。如果编译器无法对此类事件发出警告,则应认真考虑切换编译器至少用于开发构建,或者至少运行单独的静态分析器。此外,这是一种可怕的未定义行为,您不能真的相信它是无效的。抱歉,我被另一种情况弄错了。这一行将给您一个错误,编译器将尝试打印第二个“%p”,并且找不到任何要打印的指针,因此它将给出一个错误,而不是警告!!编译器不应该给出错误,而应该给出警告,因为
printf
是varargs函数,并且格式字符串的内容实际上不是由编译器处理的。生成警告只是编译器的一个额外功能,与实际编译不同,这是由于str格式中的错误而添加的
int *p;
The macro NULL is defined as an implementation-defined null pointer constant, 
which in C99 can be portably expressed as the integer value 0 
converted implicitly or explicitly to the type void*.