I ran across something like this tonight.
char thing = {'12345678'};
I thought it was nonsense but it passed the compiler. What would it end up giving you? A string with no \0?
-jim lee
I ran across something like this tonight.
char thing = {'12345678'};
I thought it was nonsense but it passed the compiler. What would it end up giving you? A string with no \0?
-jim lee
char thing = '8';
...is equivalent.
Looks like list initialization in cpp.
https://en.cppreference.com/w/cpp/language/list_initialization
Checking at the assembly list, it seems that the bytes last character array are stored.
In your case.
char thing = {'12345678'};
"thing" is 0x38( or '8').
Because char is 1 byte.
When I tried it with int, it became 0x3738 (that is '78').
I'm sorry if it's different.
This is what the compiler thinks of it
C:\Users\sterretje\AppData\Local\Temp\arduino_modified_sketch_183414\sketch_jun10a.ino:1:15: warning: character constant too long for its type
char thing = {'12345678'};
^~~~~~~~~~
C:\Users\sterretje\AppData\Local\Temp\arduino_modified_sketch_183414\sketch_jun10a.ino:1:25: warning: narrowing conversion of '14136' from 'int' to 'char' inside { } [-Wnarrowing]
char thing = {'12345678'};
^
C:\Users\sterretje\AppData\Local\Temp\arduino_modified_sketch_183414\sketch_jun10a.ino:1:25: warning: overflow in implicit constant conversion [-Woverflow]
I think you can have a multi-character constant up to the size of an "int", so two ASCII characters on AVR, four ASCII characters on ARM.
The AVR compiler agrees...
sketch_feb19a.ino:2:21: warning: character constant too long for its type
uint32_t big_char = '1234';
^~~~~~
C++11 extends the syntax so UTF-32 is available. C++11 appears to not be enabled...
sketch_feb19a.ino:2:21: warning: character constant too long for its type
char32_t big_char = U'1234';
^~~~~~~
This is actually what I got.
-jim lee
This is confusing because it puts single-quotes around the integer value. 14136 is 0x3738 is '78'.
Yes, it's ironic that
int label = 'int';
won't work (at least in an AVR)
"won't work" in what way? The compiler gives a warning that the character constant is being truncated:
sketch_may19a.ino:1:13: warning: character constant too long for its type
int label = 'int';
^~~~~
When you compare the variable 'label' to the character constant 'int' the result is 'true'.
int label = 'int';
void setup()
{
Serial.begin(115200);
delay(200);
Serial.println(label);
Serial.println(label == 'int' ? "true" : "false");
}
void loop() {}
void setup()
{
Serial.begin (115200);
int label = 'int';
foobar (label);
}
void foobar (int label)
{
switch (label) {
case 'int' : Serial.println (F("'int' YAY!")); break;
case 'in' : Serial.println (F("'in' BOO!")); break;
case 'nt' : Serial.println (F("'nt' BOO!")); break;
default: Serial.println (F("Whisky Tango Foxtrot?")); break;
}
}
void loop()
{}
This doesn't compile, giving a duplicate case error for "case 'nt':".
Since the 'int' case truncates to 'nt' it is not surprising that it is considered a duplicate of 'nt'.
https://en.cppreference.com/w/cpp/language/character_literal
"Ordinary multicharacter literal, e.g. 'AB', is conditionally-supported, has type int and implementation-defined value."
So, won't work - "label" cannot contain 'int'.
If 'nt' and 'int' both are considered equal to 'int' that's not hugely useful, is it?
About as useful as putting 16-bit values into 8-bit variables.
If the goal is for 'label' to contain a representation of a data type, I would use an 'enum'. Of course you can't put a reserved word like 'int' in an enum so you would have to add a prefix (t_int), or a suffix (int_t), or change case (Int, INT).
But it is useful to put a UTF-32 value into a 32 bit variable. Something available with the C++11 standard. That the AVR compiler fails to support.
The compiler supports it but Serial.print() doesn't. This compiles without error or warning but it prints out 29438:
void setup()
{
Serial.begin(115200);
delay(200);
Serial.println();
char32_t c = U'猫';
Serial.print(c);
}
void loop() {}
If you want to use unicode characters with Serial.print() you have to put UTF-8 characters in strings. This prints the chinese character:
char s[] = u8"猫";
Serial.print(s);
Ah. Now I get it...
void setup()
{
#if __cplusplus >= 201103L
Serial.begin (115200);
char32_t label = U'int';
foobar (label);
#else
Urp.
#endif
}
void foobar (char32_t label)
{
switch (label) {
case U'int' : Serial.println (F("'int' YAY!")); break;
case U'in' : Serial.println (F("'in' BOO!")); break;
case U'nt' : Serial.println (F("'nt' BOO!")); break;
default: Serial.println (F("Whisky Tango Foxtrot?")); break;
}
}
sketch_feb19a\sketch_feb19a.ino:5:20: warning: character constant too long for its type
char32_t label = U'int';
^~~~~~
sketch_feb19a\sketch_feb19a.ino:15:11: warning: character constant too long for its type
case U'int' : Serial.println (F("'int' YAY!")); break;
^~~~~~
sketch_feb19a.ino:16:11: warning: character constant too long for its type
case U'in' : Serial.println (F("'in' BOO!")); break;
^~~~~
sketch_feb19a.ino:17:11: warning: character constant too long for its type
case U'nt' : Serial.println (F("'nt' BOO!")); break;
^~~~~
sketch_feb19a.ino: In function 'void foobar(char32_t)':
sketch_feb19a:17:6: error: duplicate case value
case U'nt' : Serial.println (F("'nt' BOO!")); break;
^~~~
sketch_feb19a.ino:15:6: note: previously used here
case U'int' : Serial.println (F("'int' YAY!")); break;
^~~~
exit status 1
duplicate case value
Multibyte character literals is optionally supported. The default is to treat them as int
. I have worked with compilers that treat them as the widest supported integral type. I apologize for the mistake.
Thank you to @anon73444976 for the clever example!
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.