【问题标题】:Why are address with negative values being displayed [closed]为什么显示负值的地址[关闭]
【发布时间】:2019-01-18 20:10:17
【问题描述】:

我正在学习指针并尝试使用它! 这是我的代码..

#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?

【问题讨论】:

  • 请正确格式化您的代码
  • 简单来说,用指针使用%d是不正确的,会调用undefined behavior。因此,您的问题在技术上毫无意义:任何事情都可能在您的两个程序中发生。
  • %d 是一个 32 位有符号整数,这就是您要求打印地址的方式。 %u 是一个 32 位无符号整数。您也可以尝试打印一个 64 位整数,有符号或无符号。这是你的家庭作业,完成后回复我。
  • @TheGreatContini "%d" 代表intint 位宽在这里并不重要。
  • 很有可能,在您的 C 实现中,指针是 8 个字节,int 是 4 个字节。当您使用%d 错误地打印指针时,恰好指针的低四个字节用于int。 (这只是发生的事情,而不是您可以依赖的行为。)低四个字节是变化最大的,系统会改变程序布局以使恶意软件更难攻击。所以他们在int的“符号位”上有所不同。

标签: c


【解决方案1】:

指针应该打印%p 而不是%d:这个数字可能太大了,所以溢出了。


编辑 让我更清楚一点:intchar 等类型具有固定数量的位/字节。即使两种类型具有相同的位数,区别在于计算机如何解释它们。对于整数,包括字符,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 位。根据this answer,实际上取决于实现的最常见行为是丢弃最高有效位。因此,您的号码将变为 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 可能还不够。

【讨论】:

  • 是的,我不知道为什么会出现这个警告,因为 afaik &amp;aa 相同。我是不是哪里错了?
  • 你想给q分配什么? aa 本身的地址(也就是数组的地址)?
  • 我正在试验..因此我认为&amp;a is same as a 并尝试了两种方法,但前者给出了您提到的警告
  • 不要这么认为&amp;aa的地址,a是那个地址的那个地址,它是一个地址但是对数组来说。
【解决方案2】:

把它变成整数变量没有任何关系。 你运行程序两次,每次变量分配在不同的地址。

当使用 %d 时,它将打印该值的有符号整数表示,但它可以保存 16 位或 32 位

【讨论】:

    猜你喜欢
    • 2021-04-04
    • 2022-06-13
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2016-08-01
    相关资源
    最近更新 更多