在不同的C标准中应该打印什么样的C代码?
struct X { int a; char b[4]; };
struct X x, y; struct X *px;
printf("%x %x\n", x, &x); // what mean x in this context? suppose we get 0x12b45 and 0x34235
printf("%d\n", x == 0x12b45 ? 1 : 0)
px = &x;
x = *px;
printf("%x %x\n", x, *px);
x = y
printf("%x %x\n", x, y);
在其他方面,结构体的值是什么?或者更好地说,一个结构解析为什么值?使用与数组的类比,数组名称解析为第一个数组项的值,什么值解析为结构名称?
int a[3];
printf("%x %x\n", a, a[0]); // prints the same value twice
struct s { int a; } b;
printf("%x\n", b); // what value is printed?
@大卫格雷森要求一个最小的可重复的例子,在这里你是:
#include <stdio.h>
#include <stdlib.h>
struct X { int a; char b[4]; };
struct X x, y; struct X *px;
void main(int argc, char *argv[]) {
printf("%x %x\n", x, &x); // what mean x in this context?
printf("%p %p\n", x, &x);
px = &x;
x = *px;
printf("%x %x\n", x, *px);
x = y;
printf("%x %x\n", x, y);
int a[3];
printf("%x %x\n", a, &a[0]); // prints the same value twice
struct s { int a; } b;
printf("%x %x\n", b, b.a); // what value is printed?
}
我删除了带有?
/:
操作符的行,因为它不会在编译时出现试图对结构进行操作的错误。
使用TCC编译,此代码的结果如下:
0 402168
0000000000000000 0000000000402168
0 0
0 0
14feac 14feac
6 6
我对结果的理解是这样的,当然打印指针或十六进制数提供了相同的值,只是格式不同,所以我将忽略指针输出。
- 第一次打印显示
0
和一个数字,这是x
变量(结构X)的地址,“奇怪”的是第一个0
,我认为是结构X的一个成员的值,初始化为0,因为x是一个全局变量。 - 第二次打印打印相同的值
0
,因为它是相同的x
变量,通过自己的id和指向x
变量的指针进行访问。 - 第三次打印即使在打印两个不同的结构X变量
x
和y
时也会打印相同的值,因为我之前已经将变量y
,一个结构X,赋值给变量x
,所以它们都是相同的变量,并且它被初始化为0
,因为它是全局的,但问题是,当将一个结构赋值给另一个结构时,它是复制所有字节还是简单地分配指针? - 第四次打印涉及打印一个具有通常行为的数组
- 第五次打印很有趣,因为它将结构体作为一个整体和第一个(也是唯一的)成员打印,并且打印相同的值6。为什么是6?我猜这一次结构变量b是一个局部变量,因此没有初始化,所以我们得到了垃圾。这里的要点是使用结构变量似乎与使用第一个成员相同,类似于数组,但我不知道这是标准行为还是取决于编译器或C标准。
所以我的猜测是使用一个结构变量作为符号,解析为与结构的第一个成员相同的值,与数组的工作方式类似。这与@Eric Postpischil所说的一致,我想。
1条答案
按热度按时间dauxcl2d1#
C标准没有正式定义结构的值,尽管结构必须有一个值,因为标准指定的某些行为需要它,例如将一个结构对象的值赋给另一个结构对象。结构类型是一个成员序列,因此结构的值在概念上是其成员值的tuple。
以下是C 2018标准。我希望在其他版本的标准中没有重大变化。
printf("%x %x\n" , x, &x); // what mean x in this context? suppose we get 0x12b45 and 0x34235
这段代码的行为不是由C标准定义的,因为
%x
被指定为接受unsigned int
参数(7.21.6.1 8),并且“...如果任何参数不是相应转换规范的正确类型,则行为未定义”(7.21.6.1 9)。printf("%d\n" , x == 0x12b45 ? 1 : 0)
编译这段代码必须产生一条诊断消息,因为它违反了6.5.9 2中
==
的约束:应满足以下条件之一:
void
的限定或非限定版本的指针;或如果编译器接受表达式,则行为不是由C标准定义的。
px = &x;
x = *px;
在将
px
设置为指向x
之后,这仅仅将x
设置为它自己的值。printf("%x %x\n" , x, *px);
如上所述,这段代码的行为不是由C标准定义的。
x=y
这将
x
设置为具有y
的值(在它具有1的范围内;讨论未初始化的对象超出了这个答案的范围)。在执行之后,x
的每个成员都将具有y
的相应成员的值。x
和y
中的任何填充字节可能不同,因为x
中的填充字节的内容根据www.example.com 6未指定6.2.6.1。printf("%x %x\n" , x, y);
如上所述,这段代码的行为不是由C标准定义的。