символ *a, *b; что тип (b-a) и как делают меня printf это?

Поблочное тестирование работает очень похожее на двойную бухгалтерию. Вы заявляете то же самое (бизнес-правило) двумя очень отличающимися способами (как запрограммированные правила в Вашем производственном коде, и как простые, представительные примеры в Ваших тестах). Очень маловероятно, что Вы делаете тот же ошибка в обоих, поэтому если они оба соглашаются друг с другом, довольно маловероятно, что Вы поняли его превратно.

, Как тестирует попытку стоить усилия? По моему опыту, по крайней мере четырьмя способами, по крайней мере, при выполнении разработки через тестирование:

  • это помогает Вам придумать хорошо разъединенный дизайн. Вы можете только код модульного теста, который хорошо разъединяется;
  • это помогает Вам определить, когда Вы сделаны. Необходимость определить необходимое поведение в тестах помогает не создать функциональность, в которой Вы на самом деле не нуждаетесь и определяете, когда функциональность завершена;
  • это дает Вам систему поддержки для рефакторингов, которая делает код намного более поддающимся изменениям; и
  • это сохраняет Вас большая отладка времени, которое является ужасно дорогостоящим (я услышал оценки, что традиционно, разработчики тратят до 80% своего времени, отлаживая).
5
задан Carl Norum 29 October 2009 в 18:41
поделиться

5 ответов

b - a is a ptrdiff_t, which you can print with %td in your printf format. From the spec section 6.5.6 Additive operators:

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the header.

For printf and related functions, section 7.19.6 Formatted input/output functions:

t Specifies that a following d, i, o, u, x, or X conversion specifier applies to a ptrdiff_t or the corresponding unsigned integer type argument; or that a following n conversion specifier applies to a pointer to a ptrdiff_t argument.

I poked around in the spec some more, and it seems to indicate that a difference of two pointers might not even fit in a ptrdiff_t, in which case behaviour is undefined:

J.2 Undefined behavior
- The result of subtracting two pointers is not representable in an object of type ptrdiff_t (6.5.6).

Though I can't imagine any implementation where that might come up. I guess you could check PTRDIFF_MIN and PTRDIFF_MAX in to be really sure.

22
ответ дан 18 December 2019 в 05:17
поделиться

Результат b - a определяется только тогда, когда оба a и b указывают на элементы одного и того же массива char. Это требование также можно интерпретировать как a и b , указывающие на байты, принадлежащие одному и тому же объекту, поскольку каждый объект может быть повторно интерпретирован как массив символов.

В противном случае, результат не определен. Т.е. попытка вычесть такие указатели приводит к неопределенному поведению.

Когда результат определен, он имеет тип ptrdiff_t . ptrdiff_t - это имя typedef, и какой тип скрывается за этим именем typedef, определяется реализацией. Однако известно, что тип подписан.

Также обратите внимание, этот язык C не гарантирует, что ptrdiff_t достаточно велик, чтобы содержать результат любого вычитания, даже если указатели указывают на элементы одного и того же массива. Если указатели расположены слишком далеко друг от друга для типа ptrdiff_t , чтобы учесть результат, поведение не определено.

Нет специального спецификатора формата printf для ptrdiff_t даже в C99, поэтому вам, вероятно, будет лучше преобразовать его в достаточно большой целочисленный тип со знаком и использовать спецификатор формата для этого типа

printf("%ld\n", (long) (b - a));

Исправление: C99 действительно имеет модификатор длины для ptrdiff_t . Правильный способ распечатать результат в C99:

printf("%td\n", b - a);

Обратите внимание, что t - это модификатор длины. Его можно комбинировать с d , o , Спецификаторы преобразования u , x или X , в зависимости от того, какой выходной формат вы хотите получить. В C89 / 90 вам все равно придется использовать достаточно большой подписанный тип.

PS Вы сказали, что не можете себе представить, что он потерпит неудачу на 32-битной или 64-битной машине. На самом деле очень легко вообразить (или фактически допустить) неудачу. Вы видите ptrdiff_t на 32-битной машине обычно 32-битного типа. Поскольку это тип со знаком, у него есть только 31 бит для представления величины значения. Если вы возьмете два указателя, которые находятся дальше друг от друга (т.е. требуется 32 бита для представления «расстояния»), результат b - a будет переполняться и будет бессмысленным. Чтобы предотвратить эту неудачу, вы d требуется как минимум 33-битный подписанный ptrdiff_t на 32-битной машине и как минимум 65-битный подписанный ptrdiff_t на 64-битной машине. Реализации обычно этого не делают, они просто используют «разрешение» из стандарта для получения неопределенного поведения при переполнении.

12
ответ дан 18 December 2019 в 05:17
поделиться

It's ptrdiff_t. From man stddef.h:

ptrdiff_t
              Signed integer type of the result of subtracting two pointers.

Print it with %td.

5
ответ дан 18 December 2019 в 05:17
поделиться

Тип ba - ptrdiff_t

2
ответ дан 18 December 2019 в 05:17
поделиться

Поскольку вы не инициализировали переменные a и b , код дает неопределенное поведение. Но кроме этого, типом ba является ptrdiff_t , который достаточно велик, чтобы вместить результат. Если у вас достаточно современный C, вы можете распечатать его с помощью % tx .

Если вы не хотите использовать % tx , вы должны преобразовать свой результат, чтобы он действительно соответствует (и не случайно) вашему спецификатору формата:

printf("%lx", (unsigned long)(a-b));

Не исключено, что система может иметь, например, 32-битное адресное пространство и 32-битный ptrdiff_t, но 64-битный длинный, а затем ваш printf завершится ошибкой.

t инициализировал переменные a и b , код дает неопределенное поведение. Но кроме этого, типом ba является ptrdiff_t , который достаточно велик, чтобы вместить результат. Если у вас достаточно современный C, вы можете распечатать его с помощью % tx .

Если вы не хотите использовать % tx , вы должны преобразовать свой результат, чтобы он действительно совпадает (и не случайно) с вашим спецификатором формата:

printf("%lx", (unsigned long)(a-b));

Не исключено, что система может иметь, например, 32-битное адресное пространство и 32-битный ptrdiff_t, но 64-битную длину, а затем ваш printf завершится ошибкой.

t инициализировал переменные a и b , код дает неопределенное поведение. Но кроме этого, типом ba является ptrdiff_t , который достаточно велик, чтобы вместить результат. Если у вас достаточно современный C, вы можете распечатать его с помощью % tx .

Если вы не хотите использовать % tx , вы должны преобразовать свой результат, чтобы он действительно совпадает (и не случайно) с вашим спецификатором формата:

printf("%lx", (unsigned long)(a-b));

Не исключено, что система может иметь, например, 32-битное адресное пространство и 32-битный ptrdiff_t, но 64-битную длину, а затем ваш printf завершится ошибкой.

который достаточно велик, чтобы вместить результат. Если у вас достаточно современный C, вы можете распечатать его с помощью % tx .

Если вы не хотите использовать % tx , вы должны преобразовать свой результат, чтобы он действительно совпадает (и не случайно) с вашим спецификатором формата:

printf("%lx", (unsigned long)(a-b));

Не исключено, что система может иметь, например, 32-битное адресное пространство и 32-битный ptrdiff_t, но 64-битную длину, а затем ваш printf завершится ошибкой.

который достаточно велик, чтобы вместить результат. Если у вас достаточно современный C, вы можете распечатать его с помощью % tx .

Если вы не хотите использовать % tx , вы должны преобразовать свой результат, чтобы он действительно соответствует (и не случайно) вашему спецификатору формата:

printf("%lx", (unsigned long)(a-b));

Не исключено, что система может иметь, например, 32-битное адресное пространство и 32-битный ptrdiff_t, но 64-битный длинный, а затем ваш printf завершится ошибкой.

2
ответ дан 18 December 2019 в 05:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: