Действительно ли безопасно использовать-1 для установки всех битов на истинный?

Две вещи:

Если вы хотите использовать библиотеку, вам не нужно использовать «другой файл». Вы можете просто отредактировать вкладку package.json, используя встроенный редактор, чтобы добавить нужную библиотеку.

enter image description here

Тем не менее, встроенный редактор действительно хорош только для тривиальных вещей, так что настройка вашего собственного проекта Firebase Cloud Function - хорошая идея .

Он не загружает код автоматически, firebase init просто создает набор заглушек. Конечно, вы можете просто скопировать и вставить файлы из встроенного редактора в локальную копию.

Однако, есть также способ загрузить zip-файл с файлами проекта. Нажав на значок загрузки, вы получите архив с файлами, включая файл README.md с подробными инструкциями.

enter image description here

После того, как вы загрузили файлы и развернули их непосредственно в Cloud Functions для Firebase, вы больше не будете использовать встроенный редактор в Dialogflow. Вместо этого вы установите URL выполнения, расположенный прямо над редактором.

Подробности имени, которое вы будете использовать, находятся в файле README.md, но вкратце:

  • Вы используете firebase deploy для установки своего кода в Firebase
  • [ 1111] Когда он завершится, он покажет вам конечную точку URL, которая будет выполнять ваш код
  • Это URL, который вы будете использовать для раздела Webhook на странице выполнения.

enter image description here

130
задан Antonio 6 October 2016 в 08:19
поделиться

12 ответов

Я рекомендую вам сделать это именно так, как вы показали, так как это самый прямой. Инициализируйте в -1 , который будет работать всегда , независимо от фактического представления знака, в то время как ~ будет иногда иметь удивительное поведение, потому что у вас должен быть правильный операнд тип. Только тогда вы получите самое высокое значение типа без знака .

В качестве примера возможной неожиданности рассмотрим следующий:

unsigned long a = ~0u;

Он не обязательно сохранит шаблон со всеми битами 1 в a . Но сначала он создаст шаблон со всеми битами 1 в unsigned int , а затем назначит его a . Что происходит, когда unsigned long имеет больше битов, так это то, что не все из них равны 1.

И рассмотрим это, который потерпит неудачу в представлении дополнения, отличном от двух:

unsigned int a = ~0; // Should have done ~0u !

Причина в том, что ~ 0 должен инвертировать все биты. Инвертирование, которое даст -1 на машине дополнения до двух (что является необходимым значением!), Но не не даст -1 в другом представлении. На машине дополнения это дает ноль. Таким образом, на машине дополнения вышеупомянутый инициализирует a к нулю.

Вы должны понимать, что все дело в ценностях, а не в битах. Переменная инициализируется значением . Если в инициализаторе вы измените биты переменной, используемой для инициализации, значение будет сгенерировано в соответствии с этими битами. Значение, которое вам нужно, чтобы инициализировать a до максимально возможного значения, равно -1 или UINT_MAX . Второй будет зависеть от типа a - вам нужно будет использовать ULONG_MAX для беззнакового long . Однако первое не будет зависеть от его типа, и это хороший способ получить наибольшее значение.

Мы не говорим о том, имеет ли -1 все биты один (это не всегда так). И мы не говорим о том, имеет ли ~ 0 все биты один (конечно, он имеет).

Но мы говорим о том, что является результатом инициализированного flags Переменная is. И для этого только -1 будет работать с каждым типом и машиной.

Второй будет зависеть от типа a - вам нужно будет использовать ULONG_MAX для беззнакового long . Однако первое не будет зависеть от его типа, и это хороший способ получить наибольшее значение.

Мы не говорим о том, имеет ли -1 все биты один (это не всегда так). И мы не говорим о том, имеет ли ~ 0 все биты один (конечно, он имеет).

Но мы говорим о том, что является результатом инициализированного flags Переменная is. И для этого только -1 будет работать с каждым типом и машиной.

Второй будет зависеть от типа a - вам нужно будет использовать ULONG_MAX для беззнакового long . Однако первое не будет зависеть от его типа, и это хороший способ получить наибольшее значение.

Мы не говорим о том, имеет ли -1 все биты один (это не всегда так). И мы не говорим о том, имеет ли ~ 0 все биты один (конечно, он имеет).

Но мы говорим о том, что является результатом инициализированного flags Переменная is. И для этого только -1 будет работать с каждым типом и машиной.

Это хороший способ получить самое высокое значение.

Мы не говорим о том, имеет ли -1 все биты один (не всегда). И мы не говорим о том, имеет ли ~ 0 все биты один (конечно, он имеет).

Но мы говорим о том, что является результатом инициализированного flags Переменная is. И для этого только -1 будет работать с каждым типом и машиной.

Это хороший способ получить самое высокое значение.

Мы не говорим о том, имеет ли -1 все биты один (не всегда). И мы не говорим о том, имеет ли ~ 0 все биты один (конечно, он имеет).

Но мы говорим о том, что является результатом инициализированного flags Переменная is. И для этого только -1 будет работать с каждым типом и машиной.

Но мы говорим о том, что является результатом инициализированной переменной flags . И для этого только -1 будет работать с каждым типом и машиной.

Но мы говорим о том, что является результатом инициализированной переменной flags . И для этого только -1 будет работать с каждым типом и машиной.

152
ответ дан 24 November 2019 в 00:22
поделиться

Это, безусловно, безопасно, поскольку -1 всегда будет иметь все доступные биты, но мне больше нравится ~ 0. -1 просто не имеет большого смысла для беззнакового целого . 0xFF ... не хорошо, потому что это зависит от ширины типа.

0
ответ дан 24 November 2019 в 00:22
поделиться

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

В вашей ситуации я всегда использую 0xFFFF . (Используйте правильное количество Fs для переменного размера, конечно.)

[Кстати, я очень редко вижу трюк -1, выполненный в реальном коде.]

Кроме того, если вы действительно заботитесь об отдельных битах в vairable, было бы неплохо начать использовать фиксированный типы width uint8_t , uint16_t , uint32_t .

3
ответ дан 24 November 2019 в 00:22
поделиться

Чтобы избежать упомянутых проблем, просто выполните:

unsigned int flags = 0;
flags = ~flags;

Portable и точно.

17
ответ дан 24 November 2019 в 00:22
поделиться

Честно говоря, я думаю, что все FFF более читабельны. Что касается комментария о том, что это антипаттерн, если вы действительно заботитесь о том, чтобы все биты были установлены / очищены, я бы сказал, что вы, вероятно, находитесь в ситуации, когда вам все равно важен размер переменной, что потребует чего-то вроде boost :: uint16_t и т. д.

25
ответ дан 24 November 2019 в 00:22
поделиться

На процессорах Intel IA-32 можно записать 0xFFFFFFFF в 64-битный регистр и получить ожидаемые результаты. Это связано с тем, что IA32e (64-разрядное расширение для IA32) поддерживает только 32-разрядные непосредственные соединения. В 64-битных инструкциях 32-битные непосредственные значения расширяются до до 64-битных.

Следующее является недопустимым:

mov rax, 0ffffffffffffffffh

Следующее помещает 64 1 с в RAX:

mov rax, 0ffffffffh

Просто для полноты, следующее помещает 32 1 с в нижнюю часть RAX (он же EAX):

mov eax, 0ffffffffh

И фактически я ' У меня были неудачные программы, когда я хотел записать 0xffffffff в 64-битную переменную, и вместо этого я получил 0xffffffffffffffff. В C это будет:

uint64_t x;
x = UINT64_C(0xffffffff)
printf("x is %"PRIx64"\n", x);

результат:

x is 0xffffffffffffffff

Я думал опубликовать это как комментарий ко всем ответам, в которых говорилось, что 0xFFFFFFFF предполагает 32 бита, но так много людей ответили на это, что я решил добавить его как отдельный ответ.

2
ответ дан 24 November 2019 в 00:22
поделиться

Практически: Да

Теоретически: Нет.

-1 = 0xFFFFFFFF (или любого другого размера, который является целым на вашей платформе) верно только для арифметики с двумя дополнениями. На практике это будет работать, но есть устаревшие машины (мэйнфреймы IBM и т. Д.), Где у вас есть действительный знаковый бит, а не двоичное представление. Предложенное решение ~ 0 должно работать везде.

1
ответ дан 24 November 2019 в 00:22
поделиться

Я не уверен, что использование unsigned int для флагов - хорошая идея, прежде всего, в C ++. А как насчет bitset и тому подобного?

std :: numeric_limit :: max () лучше, потому что 0xffffffff предполагает, что unsigned int является 32-разрядным целым числом.

13
ответ дан 24 November 2019 в 00:22
поделиться

Пока у вас есть #include в качестве одного из ваших включений, вы должны просто использовать

unsigned int flags = UINT_MAX;

Если вы хотите, чтобы биты длинных стоили, Вы можете использовать

unsigned long flags = ULONG_MAX;

. Эти значения гарантированно будут иметь все биты значений результата, равного 1, независимо от того, как реализованы целые числа со знаком.

5
ответ дан 24 November 2019 в 00:22
поделиться
  • unsigned int flags = -1; is portable.
  • unsigned int flags = ~0; isn't portable because it relies on a two's-complement representation.
  • unsigned int flags = 0xffffffff; isn't portable because it assumes 32-bit ints.

If you want to set all bits in a way guaranteed by the C standard, use the first one.

48
ответ дан 24 November 2019 в 00:22
поделиться

См. Литб ответ для очень четкого объяснения проблем.

Я не согласен с тем, что, строго говоря, нет никаких гарантий ни в том, ни в другом случае. Я не знаю ни одной архитектуры, которая не представляла бы беззнаковое значение `` на единицу меньше двух в степени числа битов '', когда все биты установлены, но вот что фактически говорит Стандарт (3.9.1 / 7 плюс примечание 44):

Представления целочисленных типов должны определять значения с использованием чистой двоичной системы счисления. [Примечание 44:] Позиционное представление для целых чисел, использующее двоичные цифры 0 и 1, в котором значения, представленные последовательными битами, являются аддитивными, начинаются с 1 и умножаются на последовательную интегральную степень 2, за исключением, возможно, бита с самая высокая позиция.

2
ответ дан 24 November 2019 в 00:22
поделиться

Преобразование -1 в любой беззнаковый тип гарантировано стандартом для получения всех единиц. Использование ~ 0U обычно плохо, поскольку 0 имеет тип unsigned int и не будет заполнять все биты большего беззнакового типа, если вы явно не напишете что-то вроде ~ 0ULL . В нормальных системах ~ 0 должно быть идентично -1 , но поскольку стандарт допускает представления с дополнением до единицы и знаком / величиной, строго говоря, он не переносится.

Конечно, всегда можно записать 0xffffffff , если вы знаете, что вам нужно ровно 32 бита, но -1 имеет то преимущество, что он будет работать в любом контексте, даже если вы не знаете размер тип, например макросы, которые работают с несколькими типами, или если размер типа зависит от реализации. Если вы знаете тип, другой безопасный способ получить все единицы - это макросы пределов UINT_MAX , ULONG_MAX , ULLONG_MAX и т. Д.

Лично я всегда используйте -1. Это всегда работает, и вам не нужно об этом думать.

10
ответ дан 24 November 2019 в 00:22
поделиться