将短路分配给 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;
中,&s
是short
的地址,通常是16 位整数。如果将ptr_i
设置为指向同一内存并使用*ptr_i
,它会尝试引用该地址处的int
,通常是32 位整数。这通常是一个错误;从一个有 16 位整数的地方加载一个 32 位整数,并且我们不知道它之外是什么,通常不是所需的操作。 C 标准未定义尝试此操作时的行为。
事实上,这有很多地方会出错:
如上所述,当我们只知道有一个short
时使用*ptr_i
可能会产生不希望的结果。
short
对象的对齐方式可能不适合 int
,这可能会导致指针转换或使用转换后的指针出现问题。
C 标准没有定义将short *
转换为int *
的结果,除非它与int
正确对齐,结果可以转换回short *
以产生等于原始指针。
即使short
和int
的宽度相同,比如32 位,并且对齐良好,C 标准也有关于别名的规则,允许编译器假定int *
永远不会访问一个对象被定义为short
。因此,您的程序的优化可能会以意想不到的方式改变它。
我将整数作为参数传递给期望指向 long long 的函数。
C 确实允许将整数默认转换为宽度相同或更宽的整数,因为这些通常不会出错。
【讨论】:
以上是关于将短路分配给 int * 失败的主要内容,如果未能解决你的问题,请参考以下文章
当我调用 JsonConvert.DeserializeObject() 时,为啥将 JArray 分配给 var 失败?