У вас нет никакой гарантии; разыменование нулевого указателя - неопределенное поведение . Вероятно, в приведет к segfault, если у вас нет определенных оптимизаций или компиляции на странной платформе, и в этом случае он может начать выполнение некоторой другой функции с помощью эффективных случайных аргументов, создать некоторую другую ошибку, захватить некоторое значение из памяти, или заставить демонов вылететь из вашего носа или полностью пропустить эту линию. только , один из тех, с которым я даже удивляюсь, является следующим последним.
Подробнее:
NULL
, решить, «что это запрещено, так что путь кода никогда не произойдет» и избавиться от обычного кода очистки функции; это приведет к тому, что ваша программа сместится в любую функцию, которая будет следующей в выходном двоичном файле. Если по какой-то причине вы хотите сгенерировать segfault, гораздо лучший способ сделать это с помощью
kill(getpid(), SIGSEGV);
(после включения соответствующих заголовков). Это отправляет сигнал segfault без какого-либо фактического нарушения сегментации. Если вы действительно хотите на самом деле совершить нарушение сегментации, вам лучше всего отобразить карту, а затем отменить какую-либо страницу (это зависит от ОС), а затем попытаться получить доступ к указателю на эту страницу.
Ответ SerJ de SuDDeN абсолютно прав, но некоторые подробности о том, почему код, о котором вы говорили, работает так, как он работает.
val (a, b) = (1, 2)
называется экстрактором шаблона-match-expression. Значение с правой стороны сопоставляется с экстрактором левой стороны. Это можно сделать повсюду в Scala и иметь разные лица. Например, совпадение шаблона в List может выглядеть примерно так:
scala> val head :: tail = 1 :: 2 :: 3 :: Nil
head: Int = 1
tail: List[Int] = List(2, 3)
С правой стороны ::
-символ является методом класса List, который добавляет к нему элементы. С левой стороны ::
-символ является экстрактором класса ::
, подкласса List.
Некоторые другие места могут быть для-понимания
scala> for ((a, b) <- (1 to 3) zip (4 to 6)) println(a+b)
5
7
9
или эквивалентная нотация с более высокими порядковыми методами
scala> (1 to 3) zip (4 to 6) foreach { case (a, b) => println(a+b) }
5
7
9
Прежде всего val
является неизменным, поэтому вы не можете переназначить его. Во-вторых, if
, как и все структуры управления в Scala, может вернуть значение. Итак, вы можете сделать это следующим образом:
val text = "some text goes here"
val (first, rest) = if (text.contains("z")) text.splitAt(4) else text.splitAt(7)
println(first + " *" + rest)
val (first, rest) = text.splitAt(if (text.contains("z")) 4 else 7)
.
– Travis Brown
23 February 2012 в 20:14
Ответ Serj дает лучший способ написать это, но для ответа на ваш вопрос о том, почему ваша вторая версия не работает, вы можете перейти к спецификации Scala , что делает различие между определениями переменных и .
Из «4.2. Объявления переменных и определения»:
Определения переменных могут альтернативно имеют рисунок (§8.1) как левую сторону. Определение переменной
var p = e
, гдеp
- это шаблон, отличный от простого имени или имени, за которым следует двоеточие, и тип расширяется таким же образом (§4.1) в качестве определения значенияval p = e
, за исключением того, что свободный имена вp
вводятся как изменяемые переменные, а не значения.Из «6.15 Assignments»:
Интерпретация присваивания простой переменной
x = e
зависит от определенияx
. Еслиx
обозначает изменчивую переменную, то присваивание изменяет текущее значениеx
как результат оценки выраженияe
.
(first, rest)
вот шаблон , а не простая переменная, поэтому она работает в определении переменной, но не в присваивании.
match
, в for
пониманиях, в val
/ var
объявлениях и на catch
. Невозможно сделать (повторное) присвоение нескольким переменным одновременно.
– Daniel C. Sobral
23 February 2012 в 22:22