2

Trying to figure out string literal types in C/CPP

printf("%s\n", typeid("abc").name());
printf("%s\n", typeid(const char[]).name());

print

A4_c
A_c

Not familiar with C, is different length/capacity of array means different type in C? if yes, why could we pass char[n] as char[] when passing function parameters?

tadman
  • 208,517
  • 23
  • 234
  • 262
igonejack
  • 2,366
  • 20
  • 29
  • 2
    `typeid` is a C++ thing. You may want to read up on [decaying](https://stackoverflow.com/questions/1461432/what-is-array-decaying). – tadman Apr 03 '19 at 02:00

2 Answers2

5

is different length/capacity of array means different type in C?

Yes.

if yes, why could we pass char[n] as char[] when passing function parameters?

It is actually not possible to accept an array value as a function argument. When a function argument is declared to be an array type, that declaration is adjusted by the language to mean a pointer to an element of that array type. I.e. array of char becomes pointer to char. Same applies to return types. Example:

void function(char argument[N]); // this
void function(char *argument);   // actually means this

Similarly, when an array name is used as a value argument, that array name implicitly converts to a pointer to the first element of the array. This implicit conversion is called decaying. Example:

void function(char *argument);
char array[N];
function(array); // array decays to pointer to first element

Note that this adjustment is only applied to "toplevel" arrays. Pointers to arrays and references to arrays are not adjusted to be pointers or references to pointers to element of that array even in function argument declarations.


What's the difference between char[] and char[n] in C/CPP?

char[n] is an array type. It is an array of n elements. It is a complete type. It is possible to create arrays of this type.

char[] is an array of unknown bound. It is an incomplete type. It is not possible to create an array of this type. This type can only be used in contexts where it is adjusted to another type. In a function declaration, it is adjusted to a pointer to element.

In a declaration of a non-argument array, it is adjusted to the the actual array type of known bound that is deduced from an initialiser:

char arr[] = {'1', '\0'}; // type of arr is adjusted to char[2]
char arr[];               // ill-formed declaration
eerorika
  • 232,697
  • 12
  • 197
  • 326
2

Since the typeid().name() output varies from compiler to compiler, piping output to c++filt is a better way to see the type's name.

This code:

#include <iostream>

int main(void)
{
    std::cout << typeid("abc").name() << std::endl;
    std::cout << typeid(const char[]).name() << std::endl;
    return (0);
}

compiled and ran as ./a.out outputs:

A4_c
A_c

but when ran as ./a.out | c++filt outputs the following:

char [4]
char []

For char[] vs char[4] its minimal, but for big nested types and auto in later standards of C++ it becomes a real handy tool for seeing whats happening under the hood.

(Sorry for not being a direct answer but oh how I cringe to see unformatted typeid names in any context, especially since they are compiler specific)

smonroe
  • 91
  • 1
  • 2