“ int * p = 0;”和有什么区别?和“ int * p; * p = 0;”

时间:2019-06-24 08:08:10

标签: c pointers initialization variable-assignment declaration

试图弄清楚指针初始化和指针分配之间的区别。

C语言

int *p=0;
int *p;
*p=0;

我不知道两种方法之间有什么区别。一样吗?

8 个答案:

答案 0 :(得分:7)

在功能内

int *p = 0;

等效于:

int *p;
p = 0;

即变量本身被初始化,声明的声明部分被忽略。相对于:

int *p;
*p = 0;

由于未分配指针的 target 被分配给它,因此导致未定义行为。

答案 1 :(得分:2)

int *p=0;

此行将声明int *指针并使其指向0。另外,请确保在取消引用之前使p指向有效内存。

int *p;
*p=0;

是未定义的行为。由于p没有指向任何地方。

答案 2 :(得分:1)

两者都不同。在这里

int *p=0;

整数指针p被分配了0,它与

相同
int *p; /* first p is declared : uninitialized */
p = 0; /* then assigned with 0 */

尽管我不希望使用p = 0。这个

int *p = NULL;

更好。 还有这里

int *p; 
*p=0; /* p doesn't have any valid address, de-referencing it causes UB */

您正尝试为*p分配0,这是错误的,因为在这种情况下p没有有效的地址。它调用未定义的行为

答案 3 :(得分:1)

每个新的C程序员都难以使用指针的主要原因是指针声明和指针访问/取消引用之间的语法相似。

  • int *p;是一个指向整数的指针的声明。
  • *p=0;正在取消引用指针,访问其指向的位置,并尝试在其中写入值0。为此,必须先将指针设置为指向有效的内存位置。
  • int *p = 0;是一个带有初始化值的整数指针的声明。这将设置指针本身指向的位置。它不是取消引用。

将值0分配/初始化给指针本身是一种特殊情况,因为这会转换为“空指针常量”。基本上,指针指向明确定义的无处。最好改用stddef.h中的宏NULL,这样我们才不会将其与整数值0混在一起。

因为*p=0;单独位于一行,所以0就是一个纯整数值。

另请参阅Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer

答案 4 :(得分:0)

int *p = 0;

这将创建一个整数指针,该指针将指向地址零,因此它是一个空指针。空指针仅表示该指针未指向任何东西,或者在某些语言中表示它所指向的对象是未知的。但是因为它是一个空指针,所以您知道这一点,代码也知道这一点,所以没有问题。

未初始化的指针变量通常称为悬挂指针,仅是因为您不知道其指向何处。表演

  int *p;
    *p=0;

具有不可预测的效果。

答案 5 :(得分:0)

快速解答

它们是不同的,因为在第一个示例int *p=0;中,您将p声明为指针,然后将其设置为指向地址0x0。这一行示例等效于这两行代码int *p; p=0;

在第二个示例int *p; *p=0;中,您在第一行声明了p,但尚未初始化...因此p指向的位置未定义。在第二行上,您将转到该未定义位置的地址,然后尝试将该地址的值设置为0。

您可以看到此示例与之前等价的2行示例之间的区别,因为一个示例使用p=0;,而另一个示例使用*p=0;

示例

因此,在尝试访问* p之前,您需要定义p指向的位置。假设您知道要p指向的整数的地址为0x76543210。在代码运行之前,让我们看一下内存中的值:

//  Dummy Memory Dump
//   Offset:      0        4        8        C
//  (0x76543200): 00000000 00000000 00000000 00000000
//  (0x76543210): 00000000 00000000 00000000 00000000
//  (0x76543220): 00000000 00000000 00000000 00000000

在此示例中,我将您的*p=0;更改为*p=5;,以便我们可以看到内存中的更改。现在,我们运行以下代码行:

int *p;                // Declare a pointer p
p = (int*) 0x76543210; // Set p to point at the address 0x76543210 cast to (int*)
*p = 5;                // Go to the address that p is pointing to, and set the value to 5

现在,如果我们回头看一下我们的内存,我们应该看到我们将5设置为p指向的地址:

//  Dummy Memory Dump
//   Offset:      0        4        8        C
//  (0x76543200): 00000000 00000000 00000000 00000000
//  (0x76543210): 00000005 00000000 00000000 00000000
//  (0x76543220): 00000000 00000000 00000000 00000000

说明

通常,声明分为以下几个部分:

[type] [name];

并且可选地,可以这样中断在线初始化:

[type] [name] = [value];

在此示例中:

int *p=5;
  • [类型] =(int *)
  • [名称] = p
  • [值] = 5

这可能会造成混淆,因为声明中的*附加在名称上。声明中的*仅表示p是指针。 但是指针的名称仍然只是p。

现在我们知道了组成部分,可以这么说

int *p=5;

等同于

int *p;
p=5;

现在增加了混乱,在声明指针和访问指针地址时,*之间存在区别。 在访问期间使用*时,它将使用p中的值作为将被访问的地址。 在此示例中:

int *p; // This declares a pointer p with no value
*p=5;   // This line wants to go to the address that p is pointing to and set it to 5
        // At this point, p is undefined because p was just declared and hasn't been set
        // So it is trying to go to an unknown location to set the value 5.

答案 6 :(得分:-1)

指针初始化和指针分配没有什么区别,除了可以将指针声明及其初始化放置在全局名称空间中,而作为表达式语句的赋值只能在函数内部使用。

因此,通常,这两个代码段具有相同的效果。

int *p = 0;

int *p;
p = 0;

您错误地将指针指向的对象分配视为指针本身的分配。

在此声明中

*p=0;

指针被取消引用,并且指针所指向的对象被分配值为0。

int *p;
*p=0;

由于指针本身未初始化,因此它具有一些不确定的值,并且带有赋值表达式的expression语句具有未定义的行为。

请考虑以下代码段

int x;
int *p;

p = &x; // pointer assigment
*p = 0; // object assignment pointed to by the pointer

为指针类型使用typedef将有助于避免指针分配和指针所指向的对象的分配之间的混淆

例如

typedef int * Pointer;

Pointer p;
p = 0;

因此,在声明中,符号'*'用于声明指针。

在表达式中,符号'*'表示表示间接的一元运算符。将此运算符应用于指针的结果是一个左值指定了对象。

答案 7 :(得分:-1)

没有区别。 只有一点。

int *p = 0;

是带有初始化的合并声明的示例

同时

int *p;
*p = 0;

是先声明然后初始化的示例。

int a = 0;

相同
int a;
a = 0;