零';超载';在C中为指针赋值时

零';超载';在C中为指针赋值时,c,pointers,C,Pointers,这个问题的灵感来自我一直在读的一本C语言书 他在哪里说: int num; int *pi=0; // Zero referes to the null pointer, NULL pi = # *pi = 0; // Zero refers to the integer zero 我们习惯于重载运算符,例如使用星号 声明指针、取消引用指针或乘法。这个 zero也是重载的。我们可能会感到不安,因为我们 不习惯重载操作数 所以我用调试器做了一系列的调查,我的答案是调试器给我的

这个问题的灵感来自我一直在读的一本C语言书

他在哪里说:

int num;
int *pi=0; // Zero referes to the null pointer, NULL
pi = #
*pi = 0;   // Zero refers to the integer zero
我们习惯于重载运算符,例如使用星号 声明指针、取消引用指针或乘法。这个 zero也是重载的。我们可能会感到不安,因为我们 不习惯重载操作数

所以我用调试器做了一系列的调查,我的答案是调试器给我的。我明白,这是一种未定义的行为,但我不是在写程序,我只是想弄明白。不管是什么情况,每次运行指针时都会将其初始化为1,在某些计算中我并不依赖于它,它是调试器反复显示的

这其实只是一个问题,但我必须写更多,否则它不会接受。 为什么*p=0在不同的时间有不同的影响?0是如何重载的? 如何判断*p=0是将p设为空指针,还是将0赋给p所指向的变量?编译器如何知道在p的地址而不是p所指向的地址分配null

$ 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
$cat prac.c
#包括
int main()
{
int-num;
int*p;
printf(“0)%p是%d\n”,p,*p);
*p=0;//为什么。。。。。。
printf(“1)%p是%d\n”,p,*p);
num=5;
p=&num;
printf(“2)现在%p是%d\n”,p,*p);
*p=0;//…与此不同
printf(“3)p不为空,%p:%d\n”,p,*p);
返回0;
}
美元/普拉克
0)0x7ffeb36b5c30为1//指针初始化为1,不是null,但绝对超出范围
1) 0x7ffeb36b5c30是0
2) 现在0x7ffeb36b5b3c是5
3) p不为null,0x7FFEB36B3C:0

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

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

值为
0
的整型常量表达式,或此类表达式 键入
void*

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

该标准进一步规定:

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

鉴于:

int n;
int *p;
这:

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

n = 0;

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

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

参见C11标准草案(大PDF)

  • 空指针常量和空指针:6.3.2.3
  • 简单作业:6.15.6.1

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

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

值为
0
的整型常量表达式,或此类表达式 键入
void*

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

该标准进一步规定:

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

鉴于:

int n;
int *p;
这:

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

n = 0;

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

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

参见C11标准草案(大PDF)

  • 空指针常量和空指针:6.3.2.3
  • 简单作业:6.15.6.1

我不熟悉您引用的书或文章,但它在帮助您理解和使用C语言中的指针方面失败得惊人

什么是指针?

指针只是一个普通变量,它将其他对象的地址作为其值。换句话说,指针指向可以找到其他内容的地址。通常认为一个变量包含一个立即数,比如
inta=5
,指针只需保存
5
存储在内存中的地址,例如
int*b=&a。无论指针指向什么类型的对象,其工作方式都是相同的。(一个指针,就是一个指针……)

如何声明、分配地址和引用指向的值

让我们以您的示例为例,看看每一行的功能(忽略您的
p
&
pi
打字错误,仅使用
p
):

查看哪个是值为
0
的常量表达式,或转换为类型
void*
(例如
(void*)0
)的此类表达式。实际上所有的C编译器,如果事实上C标准为此提供了
NULL
。(请参见:)因此您通常会看到:

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).
             */
一元
'*'
op
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).
             */
*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=0;

printf("1) %p is %d\n",p,*p);
num=5;
p=&num;

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

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