2013-12-21 1 views
1

Kraaa.Неужели это плохо для нижнего слоя, а затем переполняет неподписанную переменную?

Я студент в школе программирования, которая требует от нас писать функции C с менее чем 25 строками кода. Итак, в основном, каждая строка подсчитывается. Иногда, у меня есть необходимость сократить задания следующим образом:

#include <stddef.h> 
#include <stdio.h> 

#define ARRAY_SIZE 3 

int  main(void) 
{ 
    int  nbr_array[ARRAY_SIZE] = { 1, 2, 3 }; 
    size_t i; 

    i = -1; 
    while (++i < ARRAY_SIZE) 
     printf("nbr_array[%zu] = %i\n", i, nbr_array[i]); 
    return (0); 
} 

Важной частью этого кода является size_t счетчика с именем i. Чтобы сэкономить несколько строк кода, я хотел бы предварительно увеличить его в состоянии цикла. Но, поскольку стандарт C определяет size_t как неподписанный тип, то, что я в основном делаю здесь, переполняет переменную i (от 0 до очень большого значения), а затем переполняет ее один раз (от этого большого значения до 0).

Мой вопрос заключается в следующем: независимо от плохой практики от того, чтобы сократить наш код, это безопасно установить (size_t) переменную unsigned -1, то Преинкремент его на каждой итерации для просмотра массив?

Спасибо!

+0

Чтобы помочь с «менее 25 строк», можно устранить '#define ARRAY_SIZE 3'. Используйте 'int nbr_array [] = {1, 2, 3}; while (++ i chux

+0

Вы также можете быть немного умным aleck с строками кода и просто поместить все (но предварительную обработку) в одну строку. .. – Cornstalks

+1

Вы можете написать C99-совместимую программу, опуская 'return 0;'. Это сохранит одну строку (и скобки не нужны в 'return 0;', сохраняя два символа для дополнительного кредита). –

ответ

4

i = -1; часть вашей программы в порядке.

Преобразование -1 в неподписанный целочисленный тип определено в C и приводит к значению, которое при увеличении приводит к нулю.

Это говорит о том, что вы не набираете строку кода относительно идиоматического for (i=0; i<ARRAY_SIZE; i++) ….

Ваш %zi формат должен быть %zu.

+0

Стандарт программирования в действии в моей школе запрещает нам использовать что-либо еще, кроме 'while()' операторов цикла. О, спасибо за ваш комментарий о модификаторе формата; Я считаю, что '% zi' будет для' ssize_t'? – Diti

+1

@Diti Это будет иметь смысл, поскольку 'ssize_t' определяется как подписанный тип, соответствующий' size_t', но вы не найдете стандарт C, говорящий, что все в порядке, так как 'ssize_t' является расширением POSIX (и я это делаю не имеют доступа к POSIX, поэтому я не могу сказать, предлагает ли он '% zi' для печати). –

1

Несанкционированная арифметика никогда не «переполняет/переполняет» (по крайней мере, так, как стандарт говорит о неопределенном поведении подписанного арифметического переполнения). Вся беззнаковая арифметика фактически равна modular arithmetic, и, как таковая, является безопасной (т. Е. Она сама по себе не вызывает неопределенное поведение).

1

Чтобы быть точным, стандарт C гарантирует две вещи:

  • Любое целое преобразование к unsigned типа хорошо определены (как если бы подписанный номер были представлены в виде 2-комплемента)
  • переполнения/потери значимости из unsigned чисел определенно корректно (модульная арифметика с 2^п)

Поскольку size_t является типом без знака, вы не делаете ничего плохого.

+0

"* 2-комплементное представление *": ни подписанные, ни целые числа без знака должны быть дополнением 2. – Cornstalks

+2

2 дополнение является представлением для подписанных значений. Любое понятие кодирования отрицательных значений не имеет значения для неподписанного типа. Стандарт только говорит, что неподписанные типы представлены в «чистом двоичном представлении». –

+0

Что я имел в виду, так это то, что результирующее беззнаковое число должно быть таким же, как результат переинтерпретации битового шаблона подписанного числа с 2 дополнениями как непознанный, усекая его до правильной ширины. Это самый простой способ подумать об этом для меня, стандарт использует разные формулировки, но смысл одинаков. – cmaster