将短路分配给 int * 失败

Posted

技术标签:

【中文标题】将短路分配给 int * 失败【英文标题】:Assigning a short to int * fails 【发布时间】:2021-05-15 18:28:17 【问题描述】:

我知道,如果合适的话,我可以将变量重新分配给更大的类型,这样做可以。例如:

short s = 2;
int i = s;
long l = i;
long long ll = l;

当我尝试用指针来做这件事时,它失败了,我不明白为什么。我有整数,我将它们作为参数传递给期望指向 long long 的指针的函数。而且还没有失败..

前几天我从 short 到 int,发生了一些奇怪的事情,我希望有人能给我解释一下。这将是重现的最少代码。

short s = 2;
int* ptr_i = &s; // here ptr_i  is the pointer to s, ok , but *ptr_i   is definitely not 2

【问题讨论】:

en.cppreference.com/w/c/language/conversion 了解为什么您可以将 int 或 short 或任何其他整数类型的参数传递给函数。但整数不是指针,它们有不同的规则。 数据指针的大小都是一样的。他们的目标大小不同。如果sizeof(int) != sizeof(short)int *short * 将永远不会兼容,因为它不会访问正确的目标大小。如果您的编译器警告不兼容的指针类型,您应该将其视为错误并修复它。 但这意味着int *long long int * 也永远不会兼容,但这不会失败。感谢@Shawn 的链接。 @piptin 不,如果sizeof(int) != sizeof(long long int),这意味着它们不兼容。但是由于它们在大多数平台上确实具有不同的尺寸,因此它们在您的平台上可能不兼容。仅仅因为您没有看到问题并不意味着它不存在。如果您将long long 加载为int,您可能会得到低阶(在小端机器上)或高阶(在大端机器上)。您可能没有注意到差异,但这是未定义的行为。而且,如果您要存储到更大的大小,则情况会更糟,因为您正在破坏内存。 解决方法是用-Wall -Wextra -Werror编译,然后修复代码中的错误。 【参考方案1】:

当我尝试用指针来做这件事时,它失败了,我不明白为什么。

C 中类型系统的一个主要目的是减少编程错误。默认转换可能会被禁止或诊断,因为它是错误的征兆,而不是因为无法转换值。

int *ptr_i = &s; 中,&sshort 的地址,通常是16 位整数。如果将ptr_i 设置为指向同一内存并使用*ptr_i,它会尝试引用该地址处的int,通常是32 位整数。这通常是一个错误;从一个有 16 位整数的地方加载一个 32 位整数,并且我们不知道它之外是什么,通常不是所需的操作。 C 标准未定义尝试此操作时的行为。

事实上,这有很多地方会出错:

如上所述,当我们只知道有一个short 时使用*ptr_i 可能会产生不希望的结果。 short 对象的对齐方式可能不适合 int,这可能会导致指针转换或使用转换后的指针出现问题。 C 标准没有定义将short * 转换为int * 的结果,除非它与int 正确对齐,结果可以转换回short * 以产生等于原始指针。 即使shortint 的宽度相同,比如32 位,并且对齐良好,C 标准也有关于别名的规则,允许编译器假定int * 永远不会访问一个对象被定义为short。因此,您的程序的优化可能会以意想不到的方式改变它。

我将整数作为参数传递给期望指向 long long 的函数。

C 确实允许将整数默认转换为宽度相同或更宽的整数,因为这些通常不会出错。

【讨论】:

以上是关于将短路分配给 int * 失败的主要内容,如果未能解决你的问题,请参考以下文章

将 int ** 分配给 int 指针

将 int[][] 分配给 int** [重复]

当我调用 JsonConvert.DeserializeObject() 时,为啥将 JArray 分配给 var 失败?

将 Int 指针分配给 double 变量

将字母分配给c中的int变量

C#:如何将随机 int 值分配给变量?