结构体的Printf? (C/C++,VC2008)

发布于 2024-09-30 11:57:29 字数 702 浏览 1 评论 0原文

在 VC2008 中构建并运行这个:

struct A
{
   int a;
   int b;
   int c;
};
A a = { 10, 20, 30 };
printf("%d %d %d\n", a);

正常吗?

10 20 30

我想投!但它不起作用:

struct A
{
   int a;
   int b;
   int c;
   operator int()
   {
      return a + b + c;
   }
};
A a = { 10, 20, 30 };
printf("%d\n", a);

输出只是:

10

我需要模板实用程序的自动转换。 这是:https://code.google.com /p/boolib/source/browse/boolib/crypt/ShakedValue.h 它应该隐藏在内存值中,任何黑客程序(ArtMoney)都无法找到值。

还有一个技巧用法:打印结构/类的私有成员

Just build&run this in VC2008:

struct A
{
   int a;
   int b;
   int c;
};
A a = { 10, 20, 30 };
printf("%d %d %d\n", a);

Is it normal?

10 20 30

I'd like to cast! but it don't works:

struct A
{
   int a;
   int b;
   int c;
   operator int()
   {
      return a + b + c;
   }
};
A a = { 10, 20, 30 };
printf("%d\n", a);

output is only:

10

I need auto-casting for template-utility.
Here it is: https://code.google.com/p/boolib/source/browse/boolib/crypt/ShakedValue.h
It should hide in memory value, that any hack-programms (ArtMoney) can't find value.

And one more trick usage: Print private members of the struct/class

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

誰ツ都不明白 2024-10-07 11:57:29

如果你想要强制转换,那就强制转换:

struct A
{
   int a;
   int b;
   int c;
   operator int()
   {
      return a + b + c;
   }
};
A a = { 10, 20, 30 };
printf("%d\n", (int)a);

输出将是

60

If you want a cast, then cast it:

struct A
{
   int a;
   int b;
   int c;
   operator int()
   {
      return a + b + c;
   }
};
A a = { 10, 20, 30 };
printf("%d\n", (int)a);

the output will be

60
静谧幽蓝 2024-10-07 11:57:29

这是未定义的行为,因此在某种意义上,对于此函数调用,每种可能的行为都可以称为“正常”。不过可以解释一下。

printf 在格式字符串之后接受可变数量的参数。如何打包这些内容留给实现。看来 Visual C++ 将参数打包在内存中的方式与打包 struct A 的成员的方式相同,因此每次它在内部调用 va_arg 时,它都会获取下一个元素一个

至于转换,您不能依赖可变参数上下文中的自动转换,因为可选参数没有类型。 printf 声明为 int printf(char const *, ...)... 是一系列无类型参数。

It's undefined behavior, so in a certain sense every possible behavior can be termed "normal" for this function call. It can be explained though.

printf takes a variable number of arguments after the format string. How these are packed is left to the implementation. It seems that Visual C++ packs the arguments in memory the same way it packs the members of your struct A, so every time it calls va_arg internally, it gets the next element in a.

As regards the casting, you can't rely on autocasting in a varargs context, since the optional parameters have no type. printf is declared as int printf(char const *, ...). ... is a range of untyped parameters.

遥远的绿洲 2024-10-07 11:57:29

不存在像 C/C++ 这样的东西,你的代码只是两者的混合。特别是它不能使用标准 C 编译器进行编译,因为您在 a 声明中缺少 struct 关键字。

供您使用 printf。首先,如果这是 C++,你不应该这样做。它有自己的IO机制。使用它们。

然后将结构作为参数放入 ... 列表中是未定义的行为。你只是运气不好,编译器做了它所做的事情。它可能只是悲伤地“不,不,不要这样做”,或者至少给了你一个警告。

There is no such thing like C/C++, your code is just a mixture of the two. In particular it doesn't compile with a standard C compiler because you are missing the struct keyword in the declaration of a.

For your use of printf. First of all you shouldn't if this is C++. It has its own mechanisms for IO. Use them.

Then placing a structure as an argument in a ... list is undefined behavior. You just had bad luck, and the compiler did what it did. It could just have sad "no, no, don't do that", or at least have given you a warning.

夜访吸血鬼 2024-10-07 11:57:29

您将三个整数放入堆栈,然后检索三个整数(每个“%d”一个)。是的,这是正常的 - 但在“真正丑陋黑客”领域(以及未定义的行为启动,正如底座正确评论的那样)。

You placed three integers on the stack, and then retrieved three integers (one per "%d"). Yes, it is normal - but in the realm of "really ugly hack" (and Undefined Behaviour to boot, as plinth correctly commented).

属性 2024-10-07 11:57:29

这是偶然发生的。大多数时候,当您的 printf 参数计数或类型不匹配时,结果不会很漂亮。

如果您想要 C++,请使用 ostream/cout

std::cout << a.a << ' ' << a.b << ' ' << a.c << std::endl;

如果您想要非脆弱的 C 代码,请使用:

printf("%d %d %d\n", a.a, a.b, a.c);

This works by accident. Most times when your printf arg count or types do not match the results will not be pretty.

If you want C++ use ostream/cout

std::cout << a.a << ' ' << a.b << ' ' << a.c << std::endl;

If you want non-brittle C code use:

printf("%d %d %d\n", a.a, a.b, a.c);
一花一树开 2024-10-07 11:57:29

这是因为结构的内存布局。整数是紧接着彼此的。因此,将结构放入 printf 调用中基本上与将每个结构体依次放入相同的位置

it's because of memory layout of the struct. the ints are straight after each other. so putting the struct in the printf call is basically putiing the same as putting each one on one after the other

醉酒的小男人 2024-10-07 11:57:29

printf 的行为方式有很多依赖于编译器/环境的内容。

printf 表面上使用 C 的 var args 功能,当您有声明时,

 int printf(char* formatStr, ...)

您可以在“...”中传递多个参数。然后在 printf 的主体中,您将执行如下所示的操作。

// count how many formatters are in the format string 
// and calculate "amount"
// here amount = 3
va_list valsToPrint;
va_start(valsToPrint,amount);    
for (int i = 0; i < amount; ++i)
{
    // treat each value as a 32-bit int and print it
}

va_end(vl);

重要的是 - 这里有很多依赖于编译器/环境的内容。例如,该结构可能已打包,以便每个值都显示在 32 位边界上,以及 va_list 是如何由编译器实际确定的。我想编译器到编译器可能会出现一些与您的代码非常不同的行为,但表现出您所描述的行为并不完全令人惊讶。

There's a lot of compiler/environment dependent stuff in how printf might behave.

printf ostensibly uses C's var args features where when you have a declaration

 int printf(char* formatStr, ...)

you can pass multiple arguments in the "...". Then in the body of printf you would do something like the following

// count how many formatters are in the format string 
// and calculate "amount"
// here amount = 3
va_list valsToPrint;
va_start(valsToPrint,amount);    
for (int i = 0; i < amount; ++i)
{
    // treat each value as a 32-bit int and print it
}

va_end(vl);

The important thing is -- there's a lot of compiler/environment dependent stuff in here. Such as the fact that the struct is probably packed so that each value shows up on 32-bit boundaries and how the va_list is actually determined from the compiler. I imagine compiler-to-compiler there could be some very different behavior from your code, but its not entirely surprising that exhibits the behavior you describe.

贪了杯 2024-10-07 11:57:29

printf() 具有“(char *, ...)”签名。这意味着由“printf”函数来处理“char *”之后的所有参数。

您将结构体 A 传递给 printf()。在内存中它具有以下布局:“int,int,int”。 printf() 函数读取格式字符串(“%d %d %d”)并“认为”您向其传递了 3 个整数。这个“假设”与结构的布局一致。因此它将所有字段打印为单独的值。

尝试删除“b”字段,您将看到 printf() 将打印“a”字段、“c”字段和SEGMENTATION FAULT的值。

printf() has "(char *, ...)" signature. That means it is up to "printf" function to handle all arguments after "char *".

You pass a struct A to printf(). In memory it has following layout: "int, int, int". printf() function reads format string ("%d %d %d") and "thinks" that you passed 3 integers to it. And this "assumption" coincides with the struct's layout. So it prints all its fields as separate values.

Try to remove "b" field and you will see that printf() will print values of "a" field, "c" field and SEGMENTATION FAULT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文