Поведение printf / snprintf в 64-битной среде - PullRequest
0 голосов
/ 23 апреля 2019

Печать 0 в 64-битной среде с %lu дает 140733193388032 вывод.

Я печатаю 8 раз 0 в 64-битной среде, а после 6-го числа значение печатается как 0, а последние 2 печатаются 140733193388032.

#include <stdio.h>

struct size {
    unsigned long length;
    unsigned long breadth;
};

struct pad {
    unsigned long len;
    unsigned long bre;
    unsigned char hei;
    unsigned char pad[7];
};

int main() {
    unsigned long a;
    unsigned long b = 0;
    struct size sz;
    struct pad sz1;

    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero\n",
           a, b, sz.length, sz.breadth, sz1.len, sz1.bre, sz1.hei, 0);
    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero",
           0, 0, 0, 0, 0, 0, 0, 0);
}

Выход:

140737488347824 is a, 0 is b , 0 is length, 4195408 is breadth, 140737346312864 is len, 4195893 is bre, 140733193388064 is hei, 140733193388032 is zero
0 is a, 0 is b , 0 is length, 0 is breadth, 0 is len, 0 is bre, 140733193388032 is hei, 140733193388032 is zero

С Инициализирующей структурой и локальным:

#include <stdio.h>

struct size {
    unsigned long length;
    unsigned long breadth;
};

struct pad {
    unsigned long len;
    unsigned long bre;
    unsigned char hei;
    unsigned char pad[7];
};

int main() {
    unsigned long a = 0;
    unsigned long b = 0;
    struct size sz = { 0 };
    struct pad sz1 = { 0 };

    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero\n",
           a, b, sz.length, sz.breadth, sz1.len, sz1.bre, sz1.hei, 0);
    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero",
           0, 0, 0, 0, 0, 0, 0, 0);
}

Выход:

0 is a, 0 is b , 0 is length, 0 is breadth, 0 is len, 0 is bre, 140733193388032 is hei, 140733193388032 is zero
0 is a, 0 is b , 0 is length, 0 is breadth, 0 is len, 0 is bre, 140733193388032 is hei, 140733193388032 is zero

Ответы [ 3 ]

1 голос
/ 23 апреля 2019

Переменные, на которые вы ссылаетесь, неинициализированы и содержат некоторый мусор из памяти.Компилятор не обязан инициализироваться нулями, следовательно, это числа.При объявлении инициализируйте все переменные равными нулю, например:

memset(&sz, 0, sizeof(sz))

или все элементы отдельно.

Редактировать после предоставления фрагмента

Я попытался инициализировать нулем все переменные следующим образом:

#include <stdio.h>
struct size
{
  unsigned long length;
  unsigned long breadth;
};

struct pad
{
  unsigned long len;
  unsigned long bre;
  unsigned char hei;
  unsigned char pad[7];
};


int main()
{

  unsigned long a = 0;
  unsigned long b = 0;
  struct size sz = { 0 };
  struct pad sz1 = { 0 };

  printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, %lu is bre, %lu is hei, %lu is zero\n",a,b,sz.length, sz.breadth, sz1.len, sz1.bre, sz1.hei, 0);
  printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, %lu is bre, %lu is hei, %lu is zero",0,0,0,0,0,0, 0, 0);
 }

и получил следующий вывод:

0 is a, 0 is b , 0 is length, 0 is breadth, 0 is len, 0 is bre, 0 is hei, 0 is zero
0 is a, 0 is b , 0 is length, 0 is breadth, 0 is len, 0 is bre, 0 is hei, 0 is zero
0 голосов
/ 23 апреля 2019

В вашем коде 2 проблемы:

  • вы печатаете неинициализированные данные, поведение не определено, выходные данные непредсказуемы.
  • sz1.hei имеет тип unsigned char, вы не должны использовать формат %lu, или вы должны привести это значение как (unsigned long)sz1.hei.
  • 0 имеет тип int, вы должны передать 0L или 0UL для формата %luво втором printf.

С инициализаторами этот код ведет себя, как и ожидалось, в 32-битной (и 64-битной Windows), потому что unsigned long на ваших платформах 32-битная, то же самоеsize as unsigned int.

Необходимо передать printf аргументов с ожидаемым типом для каждого спецификатора преобразования, в противном случае поведение не определено.Вы должны увеличить уровень предупреждения (например, gcc -Wall -Wextra -Werror), чтобы компилятор предупреждал вас о таких ошибках и многих других.

Вот исправленная версия:

#include <stdio.h>

struct size {
    unsigned long length;
    unsigned long breadth;
};

struct pad {
    unsigned long len;
    unsigned long bre;
    unsigned char hei;
    unsigned char pad[7];
};

int main() {
    unsigned long a = 0;
    unsigned long b = 0;
    struct size sz = { 0 };
    struct pad sz1 = { 0 };

    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero\n",
           a, b, sz.length, sz.breadth, sz1.len, sz1.bre, (unsigned long)sz1.hei, 0UL);
    printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, "
           "%lu is bre, %lu is hei, %lu is zero",
           0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
    return 0;
}
0 голосов
/ 23 апреля 2019
#include <stdio.h>

struct size
{

  unsigned long length;
  unsigned long breadth;
};

struct pad
{
  unsigned long len;
  unsigned long bre;
  unsigned char hei;
  unsigned char pad[7];
};


int main()
{

   unsigned long a = 0;
   unsigned long b = 0;
   struct size sz = {0};
   struct pad sz1= {0};

   printf("%lu is a, %lu is b , %lu is length, %lu is breadth, %lu is len, %lu is 
   bre, %uc is hei, %u is zero\n",a,b,sz.length, sz.breadth, sz1.len, sz1.bre, 
   sz1.hei, 0);
   printf("%u is a, %u is b , %u is length, %u is breadth, %u is len, %u is bre, %u 
   is hei, %u is zero",0,0,0,0,0,0, 0, 0);
  }

Этот вывод - все 0

Используется -wformat в gcc, исправлены предупреждения, после чего он печатает все 0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...