不同C标准中的结构值

mwg9r5ms  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(133)

在不同的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变量xy时也会打印相同的值,因为我之前已经将变量y,一个结构X,赋值给变量x,所以它们都是相同的变量,并且它被初始化为0,因为它是全局的,但问题是,当将一个结构赋值给另一个结构时,它是复制所有字节还是简单地分配指针?
  • 第四次打印涉及打印一个具有通常行为的数组
  • 第五次打印很有趣,因为它将结构体作为一个整体和第一个(也是唯一的)成员打印,并且打印相同的值6。为什么是6?我猜这一次结构变量b是一个局部变量,因此没有初始化,所以我们得到了垃圾。这里的要点是使用结构变量似乎与使用第一个成员相同,类似于数组,但我不知道这是标准行为还是取决于编译器或C标准。

所以我的猜测是使用一个结构变量作为符号,解析为与结构的第一个成员相同的值,与数组的工作方式类似。这与@Eric Postpischil所说的一致,我想。

dauxcl2d

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的相应成员的值。xy中的任何填充字节可能不同,因为x中的填充字节的内容根据www.example.com 6未指定6.2.6.1。
    printf("%x %x\n" , x, y);
    如上所述,这段代码的行为不是由C标准定义的。

相关问题