为什么显示负值的地址

时间:2019-01-18 20:10:17

标签: c

我正在学习指针,并尝试进行实验! 这是我的代码。

#include<stdio.h>

int main() {
int a[2]={1,2};
int* p=a;
int* q=&a;
int *r=&a[0];
printf("%d %d %d",p,q,r);
return 0;
}

代码的输出为:

-20578720 -20578720 -20578720  

现在,当我将q更改为integer variable时,地址不是负数:

#include<stdio.h>

int main() {
int a[2]={1,2};
int* p=a;
int q =*a;//this is the change
int *r=&a[0];
printf("%d %d %d",p,q,r);
return 0;
}

现在输出:

1822271664 1 1822271664

我尝试在网上搜索,发现了这个memory address positive or negative value in c? 它告诉使用%p ,我这样做了,我得到了正十六进制地址值

0x7ffc4b5dbb90 0x7ffc4b5dbb90 0x7ffc4b5dbb90  

现在我的答案正确了,但是不知道

  1. 为什么%p 有效,但%d
  2. 无效
  3. 为什么将 q整数设为

对于第一个,我明白了,但我无法理解答案:Difference between %d and %p printf format string directives in c language?

2 个答案:

答案 0 :(得分:2)

应该用%p而不是%d打印指针:该数字可能太大,因此溢出。


编辑 让我更清楚一点:int char等类型的位/字节数是固定的。即使两种类型具有相同的位数,区别也在于计算机如何解释它们。对于包括字符在内的整数,n位可以表示2^n个值。有符号整数使用其中一些来表示负数:特别是您可以表示-2^(n/2)2^(n/2) - 1范围内的数字。相反,unsigned int表示从02^n - 1的数字。最大的整数将除msb之外的所有位都设置为1。要获得对应的正数,步骤是完全相同的

使用Two's complement计算负数:您采用正数的位表示形式,对每个位进行负运算,然后将结果加1。负数的最高有效位设置为1。

让我们考虑2位:您可以用它表示4个值。如果您使用无符号表示形式,则二进制数10显然对应于1。相反,如果您将其解释为带符号的数字,则其值为-2

另一个例子是下面的例子,例如一个8位的整数:00001011。这是一个正数。假设将其转换为较小大小的整数类型,例如4位。根据{{​​3}},最常见的行为(实际上取决于实现)是丢弃最高有效位。因此,您的电话号码将变为1011,但是使用int表示形式,现在将其视为负数。


您可能尝试以未签名的%u进行打印:

printf("%u %u %u",(unsigned int)(p),(unsigned int)(q),(unsigned int)(r));

还请注意,我收到警告:warning: incompatible pointer types initializing 'int *' with an expression of type 'int (*)[2]' [-Wincompatible-pointer-types]

对于

int *q  = &a;

编辑

例如,在我的计算机上运行的该程序中,返回的指针大小为int类型为8字节,int类型为4字节:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    printf("size of int*: %lu\n", sizeof(int*));
    printf("size of int: %lu\n", sizeof(int));
    return 0;


}

由此看来,您正在关注我所举示例的第二种情况。

请注意:如果指针大小较大,则强制转换为unsigned int可能还不够。

答案 1 :(得分:-1)

与将其转换为整数变量无关。 您运行了两次程序,每次将变量分配到不同的地址。

使用%d时,它将打印该值的带符号整数表示形式,但可以容纳16位或32位