Nyomasek Bobó visszatér

Egy kis segítség Bobótól C-programozáshoz:

char uint16_t ezmiez[]= u"\u0020\ud83c\udf54"

Hát természetesen nem jó (gcc-vel és clang-gal próbáltam):
 

error: \u0020 is not a valid universal character
error: \ud83c is not a valid universal character
error: \udf54 is not a valid universal character

Szóval a szóköz nem megy, mert túl kicsi; a surrogate pair meg nem megy, mert... na mindegy, fő, hogy megy.

Hozzászólások

Szerkesztve: 2021. 07. 29., cs – 13:48
fn mitirki(sz: u32) {
    if let Some(x) = char::from_u32(sz) {
        println!("{:#06x} karakter: '{}'", sz, x);
    } else {
        println!("{:#06x} nincs valid karakter", sz);
    }
}

fn main() {
    mitirki(0x0020);
    mitirki(0xd83c);
    mitirki(0xdf54);
}

$ rustc pelda.rs
$ ./pelda

Helyesen cselekszik a GCC. Utóbbi 2 érték tényleg tiltott, nincs unicode megfelelője. Az első pedig szigorúan véve \u20-ként értelmes csak unicode stringben.

Mondjuk írásmód tekintetében a Rust sem szigorú, a \u{0020} itt szintén elfogadott. A többit értelemszerűen nem fordítja le.

$ rustc -O pelda2.rs
error: invalid unicode character escape
 --> pelda2.rs:2:23
  |
2 |     println!("\u{0020}\u{d83c}\u{df54}");
  |                       ^^^^^^^^ invalid escape
  |
  = help: unicode escape must not be a surrogate

error: invalid unicode character escape
 --> pelda2.rs:2:31
  |
2 |     println!("\u{0020}\u{d83c}\u{df54}");
  |                               ^^^^^^^^ invalid escape
  |
  = help: unicode escape must not be a surrogate

error: aborting due to 2 previous errors

Nem értem, hogy mi a gond.

C szabvány, 6.4.3-mas fejezet:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

 

"A universal character name shall not specify a character whose short identifier is less than 00A0 other than 0024 ($), 0040 (@), or 0060 (‘), nor one in the range D800 through DFFF inclusive."

Ezért nem jó a \u0020 meg a többi, pont benne vannak a tiltott intervallumokban.

A GCC tök szabványkövető.

Az, hogy miért ilyen a C szabvány, az más kérdés. Tessék a megfelelő szabványosítási munkacsoportban (JTC1/SC22/WG14) ezt jelezni.

A C++-os brigád ügyesebb volt, a C++11-ben javították ugyanezt.
De nem lenne értelme panaszolni: ami egyszer el van cseszve, azt úgy vehetjük, hogy örökre el van cseszve, hiszen nem tudhatjuk, hogy aki majd tényleg használja a programot, az milyen fordító-verzióval lesz megáldva.

"hiszen nem tudhatjuk, hogy aki majd tényleg használja a programot, az milyen fordító-verzióval lesz megáldva."

Azért ez erős csúsztatás. Mert ilyen erővel mindenki K&R C-t használna, hiszen nem tudhatja, hogy mi van a usernél.

Egy szoftver igenis írhat elő minimum szabvány verziót, amiben készült - főleg amiatt is, mert nem mindegy, hogy mit használ a standard libraryből.

Nincs ezzel gond.

A szabvány meg is magyarázza, hogy miért ezek a nem érvényes karakterek: The disallowed characters are the characters in the basic character set and the code positions reserved by ISO/IEC 10646 for control characters, the character DELETE, and the S-zone (reserved for use by UTF−16)

C++11-ben javították volna?

Nem hiszem:
https://timsong-cpp.github.io/cppwp/n3337/lex.charset

If the hexadecimal value for a universal-character-name corresponds to a surrogate code point (in the range 0xD800–0xDFFF, inclusive), the program is ill-formed. Additionally, if the hexadecimal value for a universal-character-name outside the c-char-sequences-char-sequence, or r-char-sequence of a character or string literal corresponds to a control character (in either of the ranges 0x00–0x1F or 0x7F–0x9F, both inclusive) or to a character in the basic source character set, the program is ill-formed.

Nem a surrogate pair-ra, gondoltam, hanem az U+A0 alatti kódra:


/* \u0020 works in C++ (but not in C) */
#if defined(__cplusplus)

static const char16_t ustr[] = u"\u043f\u0435\u0434\u0438\u0438\u0020\u2014\u0020";

#else

static const char16_t ustr[] = {0x043f,0x0435,0x0434,0x0438,0x0438,0x0020,0x2014,0x0020,0};

#endif