Вы можете просмотреть Отчет об охвате идентификатора пользователя
ПРИМЕЧАНИЕ. Этот отчет отображается только в свойствах с включенным идентификатором пользователя и только в представлениях для этого свойства, которые не были пользователем -ID включен.
Отчет об охвате идентификатора пользователя представляет собой обзор распределения назначенных идентификаторов пользователя среди всего вашего трафика. Вы можете использовать этот отчет, чтобы увидеть общее количество сеансов и сравнить пропорцию, в которой пользователям назначен идентификатор пользователя, с долей, в которой пользователям не назначен идентификатор пользователя.
blockquote>Связанная статья , которая может быть полезна
Еще одна вещь, которую стоит отметить: source
поле userId недоступно как измерение в отчетах и не может быть экспортировано из Analytics.
BLOCKQUOTE>
Большую часть времени компиляторы пытаются очень трудно остаться обратно совместимыми.
Изменение их поведения в этом вопросе для броска ошибок взломает существующий законный код, и даже начинающий бросать предупреждения об этом вызовет проблемы с автоматическими системами, которые отслеживают код путем автоматической компиляции его и проверки ошибок и предупреждения.
Это - зло, мы в значительной степени застреваем с банкоматом, но существуют способы обойти и уменьшить опасности его.
Пример:
void *ptr = calloc(1, sizeof(array));
if (NULL = ptr) {
// some error
}
Это вызывает ошибку компиляции.
Вот почему лучше записать:
0 = = CurrentItem
Вместо:
CurrentItem == 0
так, чтобы компилятор предупредил Вас, если Вы вводите = вместо ==.
На практике я не делаю этого, но хороший совет должен сделать:
if ( true == $x )
В случае, который Вы не учитываете равняние, присваивая $x
кому: true
очевидно, возвратит ошибку.
Компилятор не отметит его как ошибку, потому что это - допустимый C/C++. Но то, что можно сделать (по крайней мере, с Visual C++), поднимают уровень предупреждения так, чтобы он отметил его как предупреждение, и затем скажите компилятору рассматривать предупреждения как ошибки. Это - хорошая практика так или иначе так, чтобы разработчики не игнорировали предупреждения.
Если Вы на самом деле имели в виду = вместо == затем, необходимо быть более явными об этом. например.
if ((x = y) != 0)
Теоретически, Вы, как предполагается, можете сделать это:
if ((x = y))
для переопределения предупреждения но это, кажется, всегда не работает.
Язык программирования D действительно отмечает это как ошибку. Для предотвращения проблемы с желанием использовать значение позже, это позволяет вид объявлений подобного C++, позволяет с for
циклы.
if(int i = some_fn())
{
another_fn(i);
}
Как указано в других ответах, существуют случаи, где использование присвоения в условии предлагает краткую-но-читаемую часть кода, который делает то, что Вы хотите. Кроме того, много актуальных компиляторов предупредит Вас, если они будут видеть присвоение, где они ожидают условие. (Если Вы - поклонник подхода нулевых предупреждений к разработке, Вы будете видеть их.)
Одна привычка, которую я разработал, который мешает мне то, чтобы быть укушенным этим (по крайней мере, на языках C-выхода) состоит в том, что, если одно из двух значений я выдерживаю сравнение, константа (или иначе не легальный lvalue), я поместил его на левой стороне компаратора: if (5 == x) { whatever(); }
Затем если я должен случайно ввести if (5 = x)
, код не скомпилирует.
Размещение константы на левой стороне сравнения является безопасным программированием. Уверенный ВЫ никогда не делали бы глупую ошибку упущения, что дополнительный '=', но кто знает о ДРУГОМ парне.
У меня только была эта опечатка ОДНАЖДЫ за мои 15 лет разработки. Я не сказал бы, что это находится на верхней части моего списка вещей высматривать. Я также избегаю той конструкции так или иначе.
Обратите внимание также, что некоторые компиляторы (тот, который я использую) выдают предупреждение на том коде. Предупреждения можно рассматривать как ошибки для любого достойного компилятора. Они могут также быть проигнорированы.
Существует несколько тактики, чтобы помочь определить это.. каждый ужасен, другой обычно макрос. Это действительно зависит от того, как Вы читаете свой разговорный язык (слева направо, справа налево).
Например:
if ((fp = fopen("foo.txt", "r") == NULL))
По сравнению с:
if (NULL == (fp = fopen(...)))
Иногда может быть легче к чтению-записи (сначала), что Ваше тестирование на, который помогает определить присвоение по сравнению с тестом. Затем введите большинство comp.lang.c людей, которые ненавидят этот стиль со страстью.
Так, мы вводим, утверждают ():
#include <assert.h>
...
fp = fopen("foo.txt", "r");
assert(fp != NULL);
...
то, когда Ваш в среде или конец замысловатого набора условных выражений, утверждает () является Вашим другом. В этом случае, если FP == ПУСТОЙ УКАЗАТЕЛЬ, аварийное прекращение работы () повышено, и строка/файл незаконного кода передается.
Таким образом, если Вы ой:
if (i = foo)
insted
if (i == foo)
сопровождаемый
assert (i > foo + 1)
... Вы быстро определите такие ошибки.
Надежда это помогает :)
Короче говоря, инвертирование аргументов иногда помогает при отладке.. утверждайте (), Ваш длинный пожизненный друг и может быть выключен во флагах компилятора в производственных выпусках.
Вы спросили, почему это было полезно, но продолжайте опрашивать людей в качестве примера, обеспечивают. Это полезно, потому что это кратко.
Да, все примеры, которые используют его, могут быть переписаны - как более длинные части кода.
Я, лично, считаю это самым полезным примером.
Скажите, что у Вас есть функция read()
это возвращает количество чтения байтов, и необходимо использовать это в цикле. Намного более просто использовать
while((count = read(foo)) > 0) {
//Do stuff
}
чем попытаться вытащить присвоение из головы цикла, которая привела бы к вещам как
while(1) {
count = read(foo);
if(!(count > 0))
break;
//...
}
или
count = read(foo);
while(count > 0) {
//...
count = read(foo);
}
Первая конструкция чувствует себя неловкой, и второй код повторений неприятным способом.
Если, конечно, я не пропустил некоторую блестящую идиому для этого...
Присвоение как условное выражение является легальным C и C++ и любым компилятором, который не разрешает, чтобы это не был реальный C или компилятор C++. Я надеялся бы, что любой современный язык, не разработанный, чтобы быть явно совместимым с C (поскольку C++ был), будет считать это ошибкой.
Существуют случаи, где это позволяет краткие выражения, такой как идиоматическое while (*dest++ = *src++);
для копирования строки в C но в целом это не очень полезно, и я считаю это ошибкой в дизайне языка. По моему опыту, легко сделать эту ошибку и трудно определить, когда компилятор не выдает предупреждение.
Это очень распространено с "низкоуровневыми" конструкциями цикла в C/C++, такой как с копиями:
void my_strcpy(char *dst, const char *src)
{
while((*dst++ = *src++) != '\0') { // Note the use of extra parentheses, and the explicit compare.
/* DO NOTHING */
}
}
Конечно, присвоения очень характерны с для циклов:
int i;
for(i = 0; i < 42; ++i) {
printf("%d\n", i);
}
Я действительно полагаю, что легче считать присвоения, когда они за пределами if
операторы:
char *newstring = malloc(strlen(src) * sizeof(char));
if(newstring == NULL) {
fprintf(stderr, "Out of memory, d00d! Bailing!\n");
exit(2);
}
// Versus:
if((newstring = malloc(strlen(src) * sizeof(char))) == NULL) // ew...
Удостоверьтесь, что присвоение очевидно, thuogh (как с первыми двумя примерами). Не скрывайте его.
Что касается случайного использования..., которого не происходит со мной очень. Общая гарантия состоит в том, чтобы поместить Вашу переменную (lvalues) на правой стороне сравнения, но это не работает хорошо с вещами как:
if(*src == *dst)
потому что оба oprands к ==
lvalues!
Что касается компиляторов..., кто может обвинить их? Запись компиляторов является трудной, и необходимо ли писать, идеальные программы для компилятора так или иначе (помните GIGO?). Некоторые компиляторы (самое известное наверняка) обеспечивают встроенный lint
- проверка стиля, но это, конечно, не требуется. Некоторые браузеры не проверяют каждый байт HTML и JavaScript, он брошен, итак, почему был бы компиляторы?
'Если (0 = x)' идиома рядом с бесполезным, потому что не помогает, когда обе стороны являются переменными ('если (x = y)') и большинство (все?) времени необходимо использовать постоянные переменные, а не магические числа.
Две других причины я никогда не использую эту идиому, по моему скромному мнению, она делает код менее читаемым, и быть честным я нахожу, что сингл '= 'корень очень небольшого количества зла. При тестировании кода полностью (который все мы делаем, очевидно), этот вид синтаксической ошибки поднимается очень быстро.
Попытайтесь просмотреть
if( life_is_good() )
enjoy_yourself();
как
if( tmp = life_is_good() )
enjoy_yourself();
Часть его имеет отношение к персональному стилю и привычкам. Я - агностик к чтению также если (kConst == x) или если (x == kConst). Я не использую константу слева, потому что исторически я не совершаю ту ошибку, и я пишу код, поскольку я сказал бы это или хотел бы считать его. Я рассматриваю это как персональное решение как часть личной ответственности перед тем, чтобы быть обладающим самосознанием, улучшающимся инженером. Например, я начал анализировать типы ошибок, которые я создавал и начал повторно проектировать свои привычки, чтобы не сделать их - подобными константе слева, только с другими вещами.
Тем не менее предупреждения компилятора, исторически, являются довольно дрянными и даже при том, что эта проблема была известна в течение многих лет, я не видел его в производственном компиляторе до конца 80-х. Я также нашел, что работа над проектами, которые были портативными, помогла очистить мой C много, как различные компиляторы и различные вкусы (т.е., предупреждения) и различные тонкие семантические различия.
Я думаю, C и разработчики языка C++ заметили, что нет никакого реального использования в запрещении его потому что
Нет сложности, вовлеченной в разрешение его. C++ просто говорит что выражение, неявно конвертируемое к bool
требуется. В C существуют полезные случаи, детализированные другими ответами. В C++ они идут один шаг вперед и позволили этому, кроме того:
if(type * t = get_pointer()) {
// ....
}
Который на самом деле ограничивает объем t к только если и его тела.
Это - действительно такая распространенная ошибка? Я узнал об этом, когда я изучил C сам, и как учитель я иногда предупреждал своих студентов и говорил им, что это - распространенная ошибка, но я редко видел его в реальном коде, даже от новичков. Конечно, не чаще, чем другие ошибки оператора, такой что касается примера, пишущий "&&" вместо "||".
Таким образом, причина, что компиляторы не отмечают его как ошибку (за исключением него являющийся совершенно действительным кодом) состоит, возможно в том, что это не корень очень многого зла.
Стандарт C идиома для итерации:
list_elem* curr;
while ( (curr = next_item(list)) != null ) {
/* ... */
}
Это зависит от языка. Java отмечает его как ошибку как, только булевы выражения могут использоваться в, если круглая скобка (и если эти две переменные не являются булевской переменной, в этом случае присвоение, также булевская переменная).
В C это - довольно общая идиома для тестирования указателей, возвращенных malloc или если после ветвления мы находимся в родительском или дочернем процессе:
if ( x = (X*) malloc( sizeof(X) ) {
// malloc worked, pointer != 0
if ( pid = fork() ) {
// parent process as pid != 0
Компиляторы C/C++ предупредят с достаточно высоким уровнем предупреждения, если Вы попросите его, но это нельзя считать ошибкой, поскольку язык позволяет его. Если с другой стороны Вы не просите, чтобы компилятор рассматривал предупреждения как ошибки.
Соответствуя константам, некоторые авторы предлагают использовать тест, постоянный == переменная так, чтобы компилятор обнаружил, если пользователь забудет второй знак равенства.
if ( 0 == variable ) {
// the compiler will complaint if you mistakenly
// write =, as you cannot assign to a constant
Так или иначе необходимо попытаться скомпилировать с максимально возможными настройками предупреждения.
Многие компилятор обнаружит это и предупредит Вас, но только если Вы уровень предупреждения установлены достаточно высоко.
Например:
~> gcc -c -Wall foo.c foo.c: In function ‘foo’: foo.c:5: warning: suggest parentheses around assignment used as truth value
Существует большое большое использование оператора присваивания в условном операторе, и это была бы королевская боль в заднице для наблюдения предупреждений о каждом все время. То, что было бы хорошо, будет функцией в Вашем IDE, которые позволяют Вам выделить все места, где присвоение использовалось вместо проверки равенства - или - после записи чего-то вроде этого:
if (x = y) {
затем та строка мигает пару раз. Достаточно, чтобы сообщить, что Вы сделали что-то не точно стандарт, но не так, что это является раздражающим.
Поскольку это не недопустимо (в C или C++ так или иначе) и иногда полезно...
if ( (x = read(blah)) > 0)
{
// now you know how many bits/bytes/whatever were read
// and can use that info. Esp. if you know, say 30 bytes
// are coming but only got 10
}
Большинство компиляторов поднимает реальную вонь, если Вы не помещаете круглую скобку вокруг присвоения так или иначе, которое я люблю.
Проблема состоит в том, что Вы берете проблему вверх тормашками. "Если" нотация не о сравнении двух значений как на некоторых других языках.
C/C++, "если" инструкция ожидает какого-либо выражения, которое оценит или к булевской переменной или к значению null/non-null. Это выражение может включать два сравнения значений и/или может быть намного более сложным.
Например, Вы можете иметь:
if(i >> 3)
{
std::cout << "i is less than 8" << std::endl
}
Который доказывает, что, в C/C++, если выражение не ограничено == и =. Что-либо сделает, пока это может быть оценено как TRUE или FALSE (C++) или обнулить ненулевой (C/C++).
Другой C++ допустимое использование:
if(MyObject * pObject = dynamic_cast<MyInterface *>(pInterface))
{
pObject->doSomething() ;
}
И это простое использование, если выражение (отмечают, что это может использоваться также в для строки объявления цикла). Более сложное использование действительно существует.
После обнаружения дубликата этого вопроса в, В этом случае, если (a=b) хорошая идея?, я решил завершить этот ответ с дополнительной премией, то есть, переменной инжекцией в объем, который возможен в C++ потому что if
оценит его выражение, включая объявление переменной, вместо того, чтобы ограничить себя для сравнения двух операндов как он сделан на других языках:
Так, заключение в кавычки от меня:
Другое использование должно было бы использовать то, что называют Инжекцией Переменной C++. В Java существует это прохладное ключевое слово:
synchronized(p)
{
// Now, the Java code is synchronized using p as a mutex
}
В C++ можно сделать это, также. Я не имею точного кода в виду (ни статья точного DDJ, где я обнаружил его), но это простое определяет, должен быть достаточно в демонстрационных целях:
#define synchronized(lock) \
if (auto_lock lock_##__LINE__(lock))
synchronized(p)
{
// Now, the C++ code is synchronized using p as a mutex
}
Это - тот же путь, смешивая инжекцию с тем, если и для объявления, можно объявить примитивный foreach макрос (если Вы хотите промышленную силу foreach, используйте повышение).
См. следующие статьи для менее наивного, больше завершенное и больше устойчивой реализации:
Редко. На самом деле я должен все же помнить один, и я профессионален с 8 лет. Я предполагаю, что это произошло, но затем, за 8 лет, я действительно произвел большое количество ошибок. Это просто, что этого вида ошибок не произошло достаточно, чтобы сделать, чтобы я помнил их в разочаровании.
В C у Вас будет больше ошибок из-за переполнения буфера, как:
void doSomething(char * p)
{
strcpy(p, "Hello World, how are you \?\n") ;
}
void doSomethingElse()
{
char buffer[16] ;
doSomething(buffer) ;
}
На самом деле Microsoft была записана настолько трудно из-за этого, они добавили предупреждение в Visual C++ 2008, удерживающий от использования strcpy!!!
Самая первая "защита" от этой ошибки должна "изменить к лучшему" выражение: Поскольку Вы не можете присвоить значение константе, этому:
if(0 = p) // ERROR : It should have been if(0 == p). WON'T COMPILE !
Не скомпилирует.
Но я нахожу это вполне плохим решением, потому что оно пытается скрыть позади стиля, что должно быть общей практикой программирования, которая является: Любая переменная, которая, как предполагается, не изменяется, должна быть постоянной.
Например, вместо:
void doSomething(char * p)
{
if(p == NULL) // POSSIBLE TYPO ERROR
return ;
size_t length = strlen(p) ;
if(length == 0) // POSSIBLE TYPO ERROR
printf("\"%s\" length is %i\n", p, length) ;
else
printf("the string is empty\n") ;
}
При попытке к "константе" как можно больше переменные заставят Вас избежать большинства ошибок опечатки, включая тех не внутри "если" выражения:
void doSomething(const char * const p) // CONST ADDED HERE
{
if(p == NULL) // NO TYPO POSSIBLE
return ;
const size_t length = strlen(p) ; // CONST ADDED HERE
if(length == 0) // NO TYPO POSSIBLE
printf("\"%s\" length is %i\n", p, length) ;
else
printf("the string is empty\n") ;
}
Конечно, это не всегда возможно (когда некоторые переменные действительно должны измениться), но я нашел, чем большинство переменных, которые я использую, константы (я продолжаю инициализировать их однажды, и затем, только читая их).
Обычно, я вижу, что код использует если (0 == p) нотация, но без нотации константы.
Мне это похоже на наличие корзины для вторсырья и другого для негодного для повторного использования, и theni n конец, бросьте их вместе в тот же контейнер.
Так, не бессмысленно повторяйте легкую привычку стиля надеяться, что она сделает Ваш код намного лучше. Это не будет. Используйте конструкции языка как можно больше, что означает, в этом случае, с помощью обоих если (0 == p) нотация, когда доступно и использование ключевого слова константы как можно больше.
Простой ответ: операция присвоения, такая как x=y, имеет значение, которое совпадает с недавно присвоенным значением в x. Можно использовать это непосредственно в сравнении, таким образом, вместо
x = y; if (x) ...
можно записать
if (x = y) ...
Это - меньше кода для записи (и читать), который иногда является хорошей вещью, но в наше время большинство людей соглашается, что это должно быть записано некоторым другим способом увеличить удобочитаемость. Например, как это:
if ((x = y) != 0) ...
Вот реалистический пример. Предположите, что Вы хотите выделить некоторую память с malloc и видеть, работало ли это. Это может быть записано шаг за шагом как это:
p = malloc(4711); if (p != NULL) printf("Ok!");
Сравнение с ПУСТЫМ УКАЗАТЕЛЕМ избыточно, таким образом, можно переписать его как это:
p = malloc(4711); if (p) printf("Ok!");
Но так как операция присвоения имеет значение, которое может использоваться, Вы могли вставить все присвоение если условие:
if (p = malloc(4711)) printf("Ok!");
Это делает то же самое, но более кратко.
одна полезная конструкция, например:
char *pBuffer;
if (pBuffer = malloc(100))
{
//continue to work here
}
править:
как упомянуто прежде, и downvoted несколько раз теперь, я мог бы добавить, что это не специально хороший стиль, но замечаемый достаточно часто сказать, что это полезно. Я также видел это с new
, но это делает больше боли в моей груди.
другой пример, менее спорный, мог бы быть:
while (pointer = getNextElement(context))
{
//go for it, use the pointer to the new segment of data
}
который подразумевает что функция getNextElement()
возвраты NULL
когда существует никакой следующий элемент так, чтобы из цикла вышли.
if ((k==1) || (k==2)) is a conditional
if ((k=1) || (k=2) ) is BOTH a conditional AND an assignment statement
Как и большинство языков, C работает от внутреннего к самому внешнему в порядке приоритета операторов.
Сначала он пытается установить k равным 1, и ему это удается.
Result: k = 1 and Boolean = 'true'
Далее: он устанавливает k равным 2 и завершается успешно.
Result: k = 2 and Boolean = 'true'
Далее: он оценивает (истина || истина)
Result: k still = 2, and Boolean = true
Наконец, он затем разрешает условие: Если (истина)
Result: k = 2 and the program takes the first branch.
За почти 30 лет программирования Я не видел веской причины для использования этой конструкции, хотя, если она существует, вероятно, это связано с необходимостью намеренно запутать ваш код.
Когда у одного из наших новых сотрудников возникает проблема, это одна из вещей, которые я ищу, наряду с тем, чтобы не вставлять терминатор в строку и копировать оператор отладки из одного места в другое и не менять '% i на "% s", чтобы соответствовать новому полю, которое они выгружают.
Это довольно распространенное явление в нашем магазине, потому что мы постоянно переключаемся между C и Oracle PL / SQL; if (k = 1) ЕСТЬ правильный синтаксис в PL / SQL.
RegEx sample
RegEx r; if(((r = new RegEx("\w*)).IsMatch()) { // ... do something here } else if((r = new RegEx("\d*")).IsMatch()) { // ... do something here }
asign a value test
int i = 0; if((i = 1) == 1) { // 1 is equal to i that was assigned to a int value 1 } else { // ? }