gpt4 book ai didi

c - 指针、转换和不同的编译器

转载 作者:太空狗 更新时间:2023-10-29 16:12:39 25 4
gpt4 key购买 nike

我现在正在参加 ANSI C 编程语言类(class),并尝试从讲师的幻灯片中运行这段代码:

#include<stdio.h>

int main()
{
int a[5] = {10, 20, 30, 40, 50};
double *p;

for (p = (double*)a; p<(double*)(a+5); ((int*)p)++)
{
printf("%d",*((int*)p));
}

return 0;
}

不幸的是,它不起作用。在 MacOS、XCode、Clang 上我得到一个错误:“Assignment to cast is illegal, lvalue casts are not supported” 在 Ubuntu gcc 上我得到下一个错误:“lvalue required as increment operand "

我怀疑问题出在我们学习 ANCI C 的编译器上,它有自己的要求,可能会违反其他标准。

最佳答案

关于((int*)p)++:

(int *) p 的结果是一个值。这与左值不同。左值(可能)指定一个对象。例如,在 int x = 3; 之后,名称 x 指定我们定义的对象。我们一般可以在表达式中使用它,比如y = 2*x,然后x就是它的值。但我们也可以在赋值中使用它,例如x = 5,然后将x用于对象。

表达式(int *) p接受p并将其转换为指向int的指针。结果只是一个值。它不是左值,因此不代表可以修改的对象。

++ 运算符修改一个对象。所以它只能应用于左值。由于 (int *) p 不是左值,因此 ++ 不能应用于它。

正如您展示的那样,幻灯片中的代码是不正确的,我不希望它在任何 C 实现中都能正常工作。 (C 确实允许实现进行许多扩展,但扩展 C 以允许此操作是不寻常的。)

关于(double*)a(int*)p:

C 确实允许您将指向对象的指针转换为指向不同类型对象的指针。对此有各种规定。重要的一点是生成的指针必须与其指向的类型正确对齐。

对象有各种对齐要求,这意味着它们必须放置在内存中的特定地址。通常,char 对象可以有任何地址,int 对象必须是四字节的倍数,而 double 对象必须是八字节的倍数.这些要求因 C 实现而异。我将使用这些值进行说明。

当您将适当的 double * 转换为 int * 时,我们知道生成的指针是四的倍数,因为它开始时是八的倍数 (假设上述要求)。所以这是一个安全的转换。当您将 int * 转换为 double * 时,它可能有错误的对齐方式。特别是,给定一个 int 数组 a,我们知道 a[0]a[1] 对于 double 必须不正确对齐,因为如果其中一个是八字节的倍数,另一个必须是八的倍数的四个字节。因此,这段代码中int *double *的转换不是C标准定义的。

它们可能适用于许多 C 实现,但您不应依赖它们。

C 规则还规定,当指向对象的指针转换回其原始类型时,结果等于原始指针。因此,如果遵守了对齐规则,示例代码中的往返转换就没问题了:您可以将 int * 转换为 double *,然后再转换回int *,前提是遵守对齐要求。

如果 double * 被用于访问 double,那将违反别名规则。通常,当一种类型的对象被当作另一种类型来访问时,C 并没有定义行为。有一些异常(exception),特别是字符类型。然而,简单地来回转换指针而不使用它们来访问对象是可以的,除了对齐问题。

关于c - 指针、转换和不同的编译器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21785302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com