What's this end up as?

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 :wink:

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]
2 Likes

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.

1 Like

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) :smiley:

"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. :slightly_frowning_face:

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);
1 Like

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 @TheMemberFormerlyKnownAsAWOL for the clever example!