не в состоянии понять sizeof - PullRequest
       16

не в состоянии понять sizeof

2 голосов
/ 20 декабря 2011
#include <stdio.h>

int main (int argc, const char * argv[])
{
static struct item
{
    char code;
    float price;
}
table[] = 
{
    {'a', 3.29},
    {'b', 2.99},
    {'c', 0.59},
    {'d', 1.59},
    {'e', 2.39}
};

char item_code[2];
int quantity;
int i;

do {
    printf("Enter item code: ");
    scanf("%1s", item_code);

    if (*item_code != '.') {
        for (i=0; i< sizeof(table)/sizeof(struct item)
             && table[i].code != *item_code; i++);

        if (i < sizeof(table)/sizeof(struct item)) {
            printf("Enter quantity: ");
            scanf("%d", &quantity);
            printf("\nUnit price = %.2f, total price = %.2f.\n\n\n",
                   table[i].price, quantity * table[i].price);
        }
        else
            printf("\nItem code %c does not exist. \n\n\n", *item_code);
    }
} while (*item_code != '.');
printf("Thank you.\n");
return 0;
}

Я новичок. Я не могу понять второй «цикл» в вышеуказанной программе. Почему используется sizeof? Каково именно значение «i» каждый раз, когда выполняется цикл? Благодаря.

Ответы [ 5 ]

4 голосов
/ 20 декабря 2011

Давайте рассмотрим простой код в системе, где целые числа имеют длину четыре байта:

int xyzzy[] = {3,1,4,1,5,9,2,6,5,3,5,8,9};       // 13 integers
printf ("%d\n"", sizeof(xyzzy));                 // 13 * 4 = 52
printf ("%d\n"", sizeof(int));                   //           4
printf ("%d\n"", sizeof(xyzzy) / sizeof(int));   // 52 / 4 = 13

В соответствии с последней строкой этот расчет позволяет получить количество элементов в массиве.

В сторону, я предпочитаю конструкцию:

sizeof(xyzzy) / sizeof(*xyzzy)

, поскольку это продолжит работать, даже если я, например, поменяю тип xyzzy на double. Это означает, что мне нужно только изменить строку one , в которой объявлена ​​переменная, а не искать все вычисления размера.

На самом деле у меня даже есть любимый макрос для этого:

#define numof(x) (sizeof(x) / sizeof(*x))

чтобы сделать мой код немного меньше.

С точки зрения того, что именно делает цикл for (и, кстати, технически это не второй цикл for, поскольку есть только один, но является вторым циклом), он в основном перебирает все значения i (начиная с 0, первый индекс), пока не достигнет либо точки за последним элементом, либо не найдет элемент с требуемым кодом элемента.

При выходе из этого цикла, i будет установлен на количество элементов, если код элемента не был найден, или на правильный индекс, если он был найден, следовательно, if оператор, следующий за for loop.

3 голосов
/ 20 декабря 2011

i начинается с нуля (i=0) и увеличивается на одну каждую итерацию (i++). Итак, 0, 1, 2, 3... и т. Д.

sizeof возвращает размер своего параметра в байтах. sizeof(table)/sizeof(struct item) - это способ получить количество элементов в таблице. Например, «каждый городской квартал находится в 200 метрах. Сколько городских кварталов на улице 1000 метров?» sizeof(street)/sizeof(block). Простой.

1 голос
/ 20 декабря 2011

«Почему используется sizeof?»

Чтобы понять, почему используется sizeof (), вы должны сначала иметь общее представление о структуре и переменной, для которой она используется.define.

static struct item
{
    char code;
    float price;
}
table[] = 
{
    {'a', 3.29},
    {'b', 2.99},
    {'c', 0.59},
    {'d', 1.59},
    {'e', 2.39}
};

Это объявляет тип структуры с именем item , который состоит из двух переменных - code , который имеет тип char и цена , которая имеет тип float .Используя следующий оператор:

sizeof(struct item)

Предоставляет размер самой структуры ... char, 1 байт и число с плавающей запятой, 4 байта.

Затем код определяет массив элементов структурывызывается table [] и инициализирует его несколькими значениями.В этом конкретном случае есть пять символов и пять чисел с плавающей запятой (всего 25 байтов).Итак, взяв sizeof (таблицу) и разделив его на sizeof (элемент структуры), мы получаем общее значение элементов структуры в массиве (25/5 = 5).

Вы можете спросить,почему бы просто не сказать, что я <5?В конце концов, вы можете видеть, что в массиве таблицы есть пять элементов структуры.Однако, если это огромная таблица, вы можете не рассчитывать количество структур в массиве.Это также значительно облегчает последующее обслуживание в будущем. </p>

Каково значение «i» при каждом выполнении цикла?

Первыйи последняя часть цикла for (;;) дает ответ:

for (i = 0; 
     i < sizeof(table)/sizeof(struct item) && table[i].code != *item_code;
     i++);

Итак, i инициализируется значением 0. Во время каждой последующей итерации цикла i увеличивается на 1 (i ++).

Поэтому я буду продолжать увеличиваться на 1, пока не будет достигнута одна из следующих границ:

i == 5                        //(sizeof(table) / sizeof(struct item))
table[i].code == *item_code

Надеюсь, это поможет!

1 голос
/ 20 декабря 2011

ответ Пакдиабло прекрасно объясняет ситуацию; Я хотел бы предостеречь вас от вашего (возможного) оптимизма по поводу этой функции языка: массивы не знают своей длины . Вы не можете использовать полезный макрос paxdiablo для массива, который был передан функции:

#define numof(x) (sizeof(x) / sizeof(*x))

void f(char arr[]) {
    int len;

    len = numof(arr);  /* FAIL */
}

void bar() {
    char c[] = "initialized char array";

    f(c);
}

Прототип функции записан type name[] на самом деле распадается в type *name указатель . Хуже всего то, что использование numof() на самом деле не умрет , оно просто даст вам неправильный ответ: sizeof(arr) / sizeof (*arr) вернет 8 / 1 или 4 / 1, потому что это проверка размера char * против размера char.

Макрос paxdiablo полезен для проверки размера массива, определенного во вложенной области видимости, но не для параметров.

0 голосов
/ 20 декабря 2011

sizeof(table)/sizeof(struct item) вычисляется до размера в байтах во время компиляции, который сообщает вам количество элементов в вашей таблице в вашем случае, т.е. sizeof (таблица) в байтах по sizeof (struct item) - это количество элементов, которые вы есть в вашем массиве, который составляет 5.

Вы также можете написать это как

for (i=0; i < 5 && table[i].code != *item_code; i++);
{
   // ........
}

Цикл завершается, когда i становится 5 или ваше состояние table[i].code != *item_code оценивается как ложное.

...