将值分配给C中的指针时零如何“重载”

时间:2018-06-19 22:09:29

标签: c pointers

这个问题的灵感来自我正在研究的一本C书中的摘录

在哪里说:

int num;
int *pi=0; // Zero referes to the null pointer, NULL
pi = #
*pi = 0;   // Zero refers to the integer zero
  

我们习惯于重载运算符,例如使用的星号   声明指针,取消引用指针或乘法。的   零也过载。我们可能会感到不适,因为我们   不习惯重载操作数。

所以我对调试器做了很多调查,我的回答是调试器向我展示了什么。这是未定义的行为,我明白了,但是我没有编写我想弄清楚的程序。无论如何,每次运行指针都会将其初始化为1,在某些计算中我并不依赖于此,而是调试器反复显示的内容。

这实际上只是一个问题,但是我不得不写更多,否则它不会接受。 为什么* p = 0在不同时间会有不同的影响? 0如何过载? 我怎么知道* p = 0是使p成为空指针还是将0赋给p指向的变量?编译器如何知道在p的地址而不是p指向的地址分配空值?

$ cat prac.c
#include <stdio.h>

int main()
{
  int num;
  int *p;                                

  printf("0) %p is %d\n",p,*p);

  *p=0;                                  //Why is this......

  printf("1) %p is %d\n",p,*p);

  num=5;
  p=&num;

  printf("2) Now %p is %d\n",p,*p);

  *p=0;                                  //....different than this

  printf("3) p is not null, %p : %d\n",p,*p);


  return 0;
}



$ ./prac
0) 0x7ffeb36b5c30 is 1    //pointer is initialized to 1, not-null, definitely out-of-bounds though
1) 0x7ffeb36b5c30 is 0
2) Now 0x7ffeb36b5b3c is 5
3) p is not null, 0x7ffeb36b5b3c : 0

2 个答案:

答案 0 :(得分:1)

您要询问的概念是空指针常量

C标准将空指针常量定义为

  

具有值0的整数常量表达式,或这样的表达式强制转换    键入void *

因此,0类型的表达式int也是一个空指针常量。 (请注意,空指针常量不必是指针类型。)

标准进一步指出:

  

如果将空指针常量转换为指针类型,则   得到的指针称为 null指针,可以保证进行比较   不等于指向任何对象或函数的指针。

给出:

int n;
int *p;

此:

p = 0;

int表达式0隐式转换为类型int*的空指针,而这:

n = 0;

*p = 0;

不执行隐式转换,因为正在初始化的对象已经是int类型。

赋值运算符的描述中说明了何时调用隐式转换的规则。相同的规则适用于初始化,参数传递和return语句。这些规则明确声明将空指针常量转换为目标类型。

请参阅C11标准的N1570草案(大PDF)。

  • 空指针常量和空指针:6.3.2.3
  • 简单分配:6.15.6.1

答案 1 :(得分:1)

我对您引用的书或文章不熟悉,但是它无法帮助您理解和使用C语言中的指针

什么是指针?

指针只是一个普通变量,它以其他值作为地址。换句话说,指针指向可以找到其他内容的地址。在通常情况下,您会想到一个包含立即数的变量,例如int a = 5;,指针将仅保存5存储在内存中的地址,例如int *b = &a;。无论指针指向哪种对象,其工作方式都相同。 (一个指针,仅仅是一个指针...。)

如何声明,分配地址并引用指向的值

让我们以您的示例为例,看看每一行的作用(忽略ppi的错别字,而仅使用p):

int num;    /* declares an integer 'num' whose value is uninitialized */

int *p = 0; /* declares a pointer 'p' and ininializes the address
             * to a the constant expression 0. (a Null Pointer Constant)
             */

请参见C11 Standard - Null Pointer Constant (p3),它是一个值为0的常量表达式,或者是强制转换为类型void *的表达式(例如(void *)0)。几乎所有C编译器,如果有的话,C标准为此提供NULL。 (请参阅:C11 Standard - 7.19 Common definitions )因此,您通常会看到:

int *p = NULL;  /* declare and initialize 'p' to the Null Pointer Constant */

接下来,一元运算符'&'用于获取对象的地址。在这里:

p = &num;   /* assigns the address of 'num' as the value of 'p', so 
             * 'p' holds the address of 'num' (e.g. 'p' points to the
             * memory location where 'num' is stored).
             */

一元'*'操作符是 dereference操作符,它提供了一种直接访问指针所持有(指向)的内存地址上的值的方法,因此:

*p = 0;     /* sets the value at the address held by 'p' to zero */

现在让我们看一下代码并输出:

int num;
int *p;                                

printf("0) %p is %d\n",p,*p);

p持有的地址是什么,num的值是什么?

您试图访问未初始化指针未初始化整数的值。您刚刚调用了 未定义行为 。您的代码定义的操作已经结束,任何事情都可能发生,无论是看起来正常还是出现SegFault。您无法访问未初始化的值

*p=0;

printf("1) %p is %d\n",p,*p);

p现在已初始化为空指针常量,您不能取消引用NULL指针-再次出现未定义的行为。

num=5;
p=&num;

printf("2) Now %p is %d\n",p,*p);

哈利路亚! num现在已初始化为5p现在拥有(指向)一个有效的内存地址! (但是很遗憾,一旦您调用 Undefined Behavior ,游戏就结束了,您可能会或可能不会获得正确的输出,但幸运的是,您似乎可以了。

*p=0;

printf("3) p is not null, %p : %d\n",p,*p);

p指向什么? (提示:num)。 取消引用运算符做什么? (提示:允许您访问指针保存的存储位置中的值)。那么*p = 0;做了什么? (提示:您只需将num的值设置为0,这就是p拥有的地址上的值)

如果您还有其他问题,请告诉我。