c - C中的垃圾值
问题描述
我期待第一个 printf() 语句的垃圾值,但我得到了地址。为什么?
#include<stdio.h>
int main()
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p=a+10;
printf("%d\n",*(p));
printf("%u",(p));
}
解决方案
对于初学者来说,这个声明
p=a+10;
是无效的。
赋值的左侧具有类型int( * )[10]
,而赋值的右侧具有类型int *
,并且没有从一种类型到另一种类型的隐式转换。
你必须写
p = ( int( * )[10] )( a + 10 );
其次,这些呼吁printf
printf("%d\n",*(p));
printf("%u",(p));
具有未定义的行为,因为使用了无效的转换说明符d
和u
指针类型的参数,因为*p
和p
都是指针。
所以一个有效的程序可以如下所示
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a + 10 );
printf("%p\n",( void * )*p );
printf("%p\n", (void *)p );
return 0;
}
指针可能指向对象(或数组)的最后一个元素之后的内存。
所以在这个声明之后
p = ( int( * )[10] )( a+10 );
指针p
指向想象的二维数组元素的第一个元素之后,其中的元素依次是一维数组的类型int[10]
,并且想象的二维数组的第一个元素对应于数组a
。
表达式*p
也是一个指针。它的类型是int *
因为表达式 *p 给出了该类型的左值,int[10]
并且在表达式中,该左值被隐式转换为指向其第一个元素的指针(在这种情况下为 type int
)。
所以这两个表达式p
和*p
指向相同的内存并且具有相同的值。
程序输出证明了这一点
0x7ffcfd46ea48
0x7ffcfd46ea48
这两个指针p
和之间的区别在于*p
它们可能指向的对象的类型。
考虑以下演示程序
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a+10 );
printf("%zu\n",sizeof( *p ) );
printf("%zu\n",sizeof( **p ) );
return 0;
}
它的输出是
40
4
如果你写了,你可能会得到未定义的行为
printf( "%d\n", **p );
在这种情况下,表达式**p
具有类型int
,并且可以访问数组之外的内存a
。
推荐阅读
- html - 为什么我的图标容器总是可见而不是出现在悬停时?
- python - H2o 交叉验证与单折训练/测试不对应
- flutter - 如何通过单击不同的按钮向 ListView.builder 添加不同的元素?
- mysql - 在 Mosaic Decisions 中向项目添加数据源时出现问题
- c# - Web 应用程序表
- sql-server - SQL Server 备份问题 - 锁定文件
- android - Firebase 数据库权限在 2 个根子节点上被拒绝
- javascript - 通过 Sentry 包装器处理 React 错误
- linux - 确定运行一组 python 脚本的时间/日期?
- node.js - 如何通过相对路径导入非 TypeScript 模块?