Почему _Bool и bool вместо int8_t или char? - PullRequest
0 голосов
/ 22 января 2020

Мне пришла в голову мысль о типах _Bool / bool (stdbool.h) в C и bool в C ++.


Мы используем логические типы объявлять объекты, которые должны содержать только значения 0 или 1. Например:

_Bool bin = 1;

или

bool bin = 1;

(Примечание: bool - это макрос для _Bool внутри файла заголовка stdbool.h.)

в C,

или

bool bin = 1;

в C ++.


Но действительно ли логические типы _Bool и bool действительно эффективны?


Я сделал тест, чтобы определить размер каждого объекта в памяти:

Для C:

#include <stdio.h>
#include <stdbool.h>   // for "bool" macro.

int main()
{
    _Bool bin1 = 1;
    bool bin2 = 1; // just for the sake of completeness; bool is a macro for _Bool.    

    printf("the size of bin1 in bytes is: %lu \n",(sizeof(bin1)));
    printf("the size of bin2 in bytes is: %lu \n",(sizeof(bin2)));  

    return 0;
}

Вывод:

the size of bin1 in bytes is: 1
the size of bin2 in bytes is: 1

Для C ++:

#include <iostream>

int main()
{
    bool bin = 1;

    std::cout << "the size of bin in bytes is: " << sizeof(bin);

    return 0;
}

Вывод:

the size of bin in bytes is: 1 

Итак, объекты объекта логический тип хранится в памяти в 1 байте (8 бит), а не только в 1 бите, как обычно требуется.

Причина, по которой здесь обсуждается: Почему char и bool одинакового размера в c ++? . Это не то, о чем мой вопрос.


Мой вопрос:

  • Почему мы используем типы _Bool / bool (stdbool.h) в C и bool в C ++, если они не обеспечивают преимущество в памяти, так как оно специально предназначено для использования этих типов?

  • Почему я не могу просто вместо этого использовать типы int8_t или char (при условии, что char содержится в 8-битном (что обычно имеет место) в реализации спецификации c) взамен?

Разве для читателя кода создается впечатление, что соответствующие объекты используются только для 0 или 1 / true или false? ​​

Большое спасибо участвовать.

Ответы [ 3 ]

4 голосов
/ 22 января 2020

Почему мы используем типы _Bool / bool (stdbool.h) в C и bool в C ++, если они не обеспечивают преимущества в памяти, так как они специально предназначены для использования этих типов ?

Вы уже упомянули причину в своем вопросе:

Мы используем логические типы для объявления объектов, которые будут содержать только значения 0 или 1

Преимущество использования логического типа данных заключается в том, что оно может представлять только true или false. Другие целочисленные типы имеют больше представимых значений, что нежелательно, когда вы хотите только два.

Почему я не могу просто использовать типы int8_t или char (при условии, что char содержит 8 бит (что обычно так) в спецификации c) вместо?

Вы можете . Фактически, C не имел логического типа данных до стандарта C99. Обратите внимание, что недостатком использования int8_t является то, что он не гарантированно предоставляется всеми системами. И проблема с char в том, что он может быть как подписанным, так и неподписанным.

Но вам это не нужно, поскольку вместо этого вы можете использовать логический тип данных.


Это подразумевает, что есть разница, когда я использую trueor и false с логическими типами по сравнению с тем, когда я использую их с char или int8_t. Не могли бы вы указать эту разницу?

Рассмотрим следующий тривиальный пример:

int8_t i = some_value;
bool b = some_value;

if (i == true)
if (i)
if (b == true)
if (b)

Для int8_t эти два условия имеют разное поведение, что создает возможность для неправильного поведения если неправильная форма выбрана. Для логического значения они имеют идентичное поведение и неправильного выбора нет.


PS Если вы хотите компактно хранить несколько логических значений (за счет нескольких инструкций на чтение и запись), вы можете использовать std::bitset или std::vector<bool> например. В C нет аналогичных стандартных библиотечных утилит, но такую ​​функциональность можно реализовать с помощью сдвига и маскирования.

1 голос
/ 22 января 2020

Существует более одного вида эффективности. Эффективность памяти одна. Еще одним фактором является эффективность скорости.

Исходный язык C вообще не имел типа boolean - обычно программист использовал бы int для логических флагов, 0 для ложных и 1 за правду. Если они действительно заботились об эффективности памяти, они могли бы использовать растровое изображение для хранения восьми логических значений в байте, но это обычно было необходимо только в ситуациях, когда памяти действительно было мало. Но доступ к int на быстрее , чем к int и распаковке составляющих его бит.

_Bool / bool был представлен в C99. Он отражает обычную практику хранения логических значений в int.

Тем не менее, он имеет преимущество в том, что компилятор знает, что это логическое значение, поэтому сложнее случайно присвоить ему значение 3, добавить его к целое число и т. д. c.

Большинство языков программирования сегодня хранят логическое значение в байте. Да, он использует в восемь раз больше памяти, чем необходимо - но это быстро, и редко бывает так много логических значений на go сразу, что потери становятся значительными.

Во многих языках программирования реализация Отдельно от языка spe c - Javascript spe c не говорит, как среда выполнения Javascript должна хранить true или false. Однако в C99 вы можете положиться на true, эквивалентное целому числу 1.

Если логические значения действительно используют слишком много памяти вашей системы, вы можете работать с побитовыми операциями для хранения 8 логических значений в unsigned char или больше для более крупных типов.

Вы можете сделать это для операций во время выполнения, если это необходимо, или просто для записи в выходной формат (если проблема заключается в размере записей в файловых системах или сетевых пакетах).

Стоит отметить, что во многих современных приложениях люди с радостью представляют false на проводе или в файловой системе как 7 байтов [ '"', 'f', 'a', 'l', 's', 'e', '"' ]

0 голосов
/ 22 января 2020

Одна из причин наличия bool и int заключается в том, чтобы повысить понятность кода для тех, кто приходит после него и пытается его поддерживать.

Рассмотрим эти

bool b; int c;

if (b == c)

c = 2; b = 2;

Теперь я бы сказал, что сравнение логического значения (true или false) с числом, скорее всего, ошибка. Поэтому такие вещи, как «if (b == 1)», могут указывать на ошибку кодирования. Я надеюсь, что вы согласитесь, что «b = 2» просто неправильно.

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

...