Printf для структуры? (C/C++, VC2008)

Просто соберите и запустите это в 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) не могут найти значение.

И еще одна хитрость: выведите закрытые члены структуры / класса

8 ответов

Решение

Если вы хотите сыграть, то разыграйте:

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

Это неопределенное поведение, поэтому в определенном смысле каждое возможное поведение можно назвать "нормальным" для этого вызова функции. Это можно объяснить, хотя.

printf принимает переменное число аргументов после строки формата. Как они упакованы, оставлено для реализации. Кажется, что Visual C++ упаковывает аргументы в памяти так же, как упаковывает элементы вашего struct Aтак что каждый раз, когда он звонит va_arg внутренне, он получает следующий элемент в a,

Что касается приведения, вы не можете полагаться на автоматическое вещание в контексте varargs, так как необязательные параметры не имеют типа. printf объявлен как int printf(char const *, ...), ... диапазон нетипизированных параметров

Нет такой вещи, как C/C++, ваш код - это просто смесь двух. В частности, он не компилируется со стандартным компилятором C, потому что вам не хватает struct Ключевое слово в декларации a,

Для вашего использования printf, Прежде всего, вы не должны, если это C++. У него свои механизмы для IO. Используй их.

Затем поместив структуру в качестве аргумента в ... список неопределенного поведения. Вам просто не повезло, и компилятор сделал то, что сделал. Это может просто печально сказать "нет, нет, не делай этого" или, по крайней мере, дать вам предупреждение.

Вы поместили три целых числа в стек, а затем получили три целых числа (по одному на "%d"). Да, это нормально - но в сфере "действительно безобразного хака" (и неопределенного поведения для загрузки, как правильно прокомментировал плинтус).

Это работает случайно. В большинстве случаев, когда ваш 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);

Есть много вещей, зависящих от компилятора / среды, в том, как printf может вести себя.

printf якобы использует функции var args C, когда у вас есть объявление

 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 фактически определяется из компилятора. Я полагаю, что от компилятора к компилятору поведение вашего кода может сильно отличаться, но неудивительно, что оно демонстрирует поведение, которое вы описываете.

Это из-за структуры памяти структуры. Ints прямо после друг друга. так что помещение структуры в вызове printf - это то же самое, что помещать каждый элемент один за другим.

printf() имеет подпись "(char *, ...)". Это означает, что функция "printf" должна обрабатывать все аргументы после "char *".

Вы передаете структуру A в printf(). В памяти он имеет следующую раскладку: "int, int, int". Функция printf() читает строку формата ("% d% d% d") и "думает", что вы передали ей 3 целых числа. И это "предположение" совпадает с макетом структуры. Таким образом, он печатает все свои поля как отдельные значения.

Попробуйте удалить поле "b", и вы увидите, что printf() будет печатать значения поля "a", поля "c" и ОТСУТСТВИЯ СЕГМЕНТАЦИИ.

Другие вопросы по тегам