Две вещи:
Если вы хотите использовать библиотеку, вам не нужно использовать «другой файл». Вы можете просто отредактировать вкладку package.json
, используя встроенный редактор, чтобы добавить нужную библиотеку.
Тем не менее, встроенный редактор действительно хорош только для тривиальных вещей, так что настройка вашего собственного проекта Firebase Cloud Function - хорошая идея .
Он не загружает код автоматически, firebase init
просто создает набор заглушек. Конечно, вы можете просто скопировать и вставить файлы из встроенного редактора в локальную копию.
Однако, есть также способ загрузить zip-файл с файлами проекта. Нажав на значок загрузки, вы получите архив с файлами, включая файл README.md
с подробными инструкциями.
После того, как вы загрузили файлы и развернули их непосредственно в Cloud Functions для Firebase, вы больше не будете использовать встроенный редактор в Dialogflow. Вместо этого вы установите URL выполнения, расположенный прямо над редактором.
Подробности имени, которое вы будете использовать, находятся в файле README.md, но вкратце:
firebase deploy
для установки своего кода в Firebase Я рекомендую вам сделать это именно так, как вы показали, так как это самый прямой. Инициализируйте в -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
будет работать с каждым типом и машиной.
Это, безусловно, безопасно, поскольку -1 всегда будет иметь все доступные биты, но мне больше нравится ~ 0. -1 просто не имеет большого смысла для беззнакового целого
. 0xFF
... не хорошо, потому что это зависит от ширины типа.
Я бы не стал делать -1. Это довольно неинтуитивно (по крайней мере для меня). Присвоение подписанных данных переменной без знака, похоже, является нарушением естественного порядка вещей.
В вашей ситуации я всегда использую 0xFFFF
. (Используйте правильное количество Fs для переменного размера, конечно.)
[Кстати, я очень редко вижу трюк -1, выполненный в реальном коде.]
Кроме того, если вы действительно заботитесь об отдельных битах в vairable, было бы неплохо начать использовать фиксированный типы width uint8_t
, uint16_t
, uint32_t
.
Чтобы избежать упомянутых проблем, просто выполните:
unsigned int flags = 0;
flags = ~flags;
Portable и точно.
Честно говоря, я думаю, что все FFF более читабельны. Что касается комментария о том, что это антипаттерн, если вы действительно заботитесь о том, чтобы все биты были установлены / очищены, я бы сказал, что вы, вероятно, находитесь в ситуации, когда вам все равно важен размер переменной, что потребует чего-то вроде boost :: uint16_t и т. д.
На процессорах 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 бита, но так много людей ответили на это, что я решил добавить его как отдельный ответ.
Практически: Да
Теоретически: Нет.
-1 = 0xFFFFFFFF (или любого другого размера, который является целым на вашей платформе) верно только для арифметики с двумя дополнениями. На практике это будет работать, но есть устаревшие машины (мэйнфреймы IBM и т. Д.), Где у вас есть действительный знаковый бит, а не двоичное представление. Предложенное решение ~ 0 должно работать везде.
Я не уверен, что использование unsigned int для флагов - хорошая идея, прежде всего, в C ++. А как насчет bitset и тому подобного?
std :: numeric_limit
лучше, потому что 0xffffffff
предполагает, что unsigned int является 32-разрядным целым числом.
Пока у вас есть #include
в качестве одного из ваших включений, вы должны просто использовать
unsigned int flags = UINT_MAX;
Если вы хотите, чтобы биты длинных стоили, Вы можете использовать
unsigned long flags = ULONG_MAX;
. Эти значения гарантированно будут иметь все биты значений результата, равного 1, независимо от того, как реализованы целые числа со знаком.
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.
См. Литб ответ для очень четкого объяснения проблем.
Я не согласен с тем, что, строго говоря, нет никаких гарантий ни в том, ни в другом случае. Я не знаю ни одной архитектуры, которая не представляла бы беззнаковое значение `` на единицу меньше двух в степени числа битов '', когда все биты установлены, но вот что фактически говорит Стандарт (3.9.1 / 7 плюс примечание 44):
Представления целочисленных типов должны определять значения с использованием чистой двоичной системы счисления. [Примечание 44:] Позиционное представление для целых чисел, использующее двоичные цифры 0 и 1, в котором значения, представленные последовательными битами, являются аддитивными, начинаются с 1 и умножаются на последовательную интегральную степень 2, за исключением, возможно, бита с самая высокая позиция.
Преобразование -1 в любой беззнаковый тип гарантировано стандартом для получения всех единиц. Использование ~ 0U
обычно плохо, поскольку 0
имеет тип unsigned int
и не будет заполнять все биты большего беззнакового типа, если вы явно не напишете что-то вроде ~ 0ULL
. В нормальных системах ~ 0
должно быть идентично -1
, но поскольку стандарт допускает представления с дополнением до единицы и знаком / величиной, строго говоря, он не переносится.
Конечно, всегда можно записать 0xffffffff
, если вы знаете, что вам нужно ровно 32 бита, но -1 имеет то преимущество, что он будет работать в любом контексте, даже если вы не знаете размер тип, например макросы, которые работают с несколькими типами, или если размер типа зависит от реализации. Если вы знаете тип, другой безопасный способ получить все единицы - это макросы пределов UINT_MAX
, ULONG_MAX
, ULLONG_MAX
и т. Д.
Лично я всегда используйте -1. Это всегда работает, и вам не нужно об этом думать.