c - 在 C 中转换指针的规则是什么?

标签 c pointers casting

K&R 不讨论它,但他们使用它。我尝试通过编写一个示例程序来了解它是如何工作的,但效果并不理想:

#include <stdio.h> 
int bleh (int *); 

int main(){
    char c = '5'; 
    char *d = &c;

    bleh((int *)d); 
    return 0;  
}

int bleh(int *n){
    printf("%d bleh\n", *n); 
    return *n; 
}

它可以编译,但我的 print 语句会吐出垃圾变量(每次我调用程序时它们都不一样)。有任何想法吗?

最佳答案

在考虑指针时,绘制图表会有所帮助。指针是指向内存中地址的箭头,带有指示值类型的标签。地址表示要查找的位置,类型表示要获取的内容。转换指针会更改箭头上的标签,但不会更改箭头指向的位置。

main 中的

d 是指向c 的指针,类型为charchar 是一个字节的内存,因此当 d 被取消引用时,您将获得该内存字节中的值。在下图中,每个单元格代表一个字节。

-+----+----+----+----+----+----+-
 |    | c  |    |    |    |    | 
-+----+----+----+----+----+----+-
       ^~~~
       | char
       d

当您将 d 转换为 int* 时,您是说 d 确实指向一个 int值(value)。在当今的大多数系统上,int 占用 4 个字节。

-+----+----+----+----+----+----+-
 |    | c  | ?₁ | ?₂ | ?₃ |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       (int*)d

当您取消引用 (int*)d 时,您会得到一个由这四个内存字节确定的值。您获得的值取决于这些标记为 ? 的单元格中的内容,以及 int 在内存中的表示方式。

PC 是 little-endian ,这意味着 int 的值是这样计算的(假设它跨越 4 个字节): * ((int*)d) == c + ?₁ * 2⁸ + ?₂ * 2¹⁶ + ?₃ * 2²⁴。所以你会看到虽然这个值是垃圾,但如果你以十六进制打印 (printf("%x\n", *n)),最后两位数字将始终是 35(这是字符 '5' 的值)。

其他一些系统是大端的,并且以另一个方向排列字节:* ((int*)d) == c * 2²⁴ + ?₁ * 2¹⁶ + ?₂ * 2⁸ + ?₃。在这些系统上,当以十六进制打印时,您会发现该值总是开始 35。某些系统的 int 大小不同于 4 个字节。极少数系统以不同的方式排列 int,但您极不可能遇到它们。

根据您的编译器和操作系统,您可能会发现每次运行程序时该值都不同,或者它始终相同但即使您对源代码进行微小调整也会发生变化。

在某些系统上,int 值必须存储在 4(或 2,或 8)的倍数的地址中。这称为 alignment要求。根据 c 的地址是否恰好正确对齐,程序可能会崩溃。

与您的程序相反,当您有一个 int 值并获取指向它的指针时,会发生以下情况。

int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
 |    |         x         |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       p

指针p 指向一个int 值。箭头上的标签正确描述了内存单元中的内容,因此取消引用时不会出现意外。

关于c - 在 C 中转换指针的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17260527/

相关文章:

postgresql - 在 PostgreSQL 中找不到函数

C++ 将 pow 函数的 double 结果转换为整数

vb.net - 类型转换通用参数

c - 人们使用什么技术/策略在 C(不是 C++)中构建对象?

未为多个定义生成编译器警告

c++ - 如何在 Unix 控制台或 Mac 终端中编译和运行 C/C++ 代码?

c++ - 指针牌组替换函数C++

C++ - 比较字符串函数不起作用?

c++ - 需要简单的指针数组相等解释

c++ - 枚举指针可以指向常量值吗?