#c #arrays #pointers #alias #typedef
#c #массивы #указатели #псевдоним #typedef
Вопрос:
Я выполняю упражнения по псевдониму типа (пример 3.44 C Primer 5th). Приведенный ниже код сделает:
-
псевдоним типа указателя на массив const int и
-
псевдоним типа ссылки на массив const int
Однако результат не соответствует ожидаемому (см. Комментарии). Почему?
int main(){
int ia[3] = {0, 1, 2};
typedef const int (*cpa)[3];
cpa g = 0; //(gdb) ptype g: type = int (*)[3]
typedef const int (amp;cra)[3];
cra h = ia; //(gdb) ptype h: type = int (amp;)[3]
return 0;
}
Когда я удаляю массив, он работает так, как ожидалось. Смотрите приведенный ниже код:
int main(){
int i = 42;
typedef const int* cp;
cp e = amp;i; //(gdb) ptype e: type = const int *
typedef const intamp; cr;
cr f = i; //(gdb) ptype f: type = const int amp;
return 0;
}
И последнее, как переписать определение псевдонима, если использовать ключевое слово «using»?
Комментарии:
1. Почему это не то, что вы ожидаете?
2. @Joseph Mansfield значение const отсутствует
3. Это правильно, и
using
делает это еще проще, потому что вам не нужно имя в середине беспорядка. Кстати, вы также можете проверить во время компиляции.const int arr[3]; static_assert(std::is_same<cpa, decltype(amp;arr)>::value, "");
4. @chris Но «const» отсутствует, если с array
5. @user3701346, если ты имеешь в виду
static_assert
, то это не функция и не макрос, а объявление ( static-assert-declaration ). Если вы имеете в видуdecltype
, это спецификатор. Если вы имеете в виду,std::is_same
это признак типа (просто структура сvalue
членом в основном).
Ответ №1:
Это просто выходные данные вашей версии gdb
, в которой опущено const
. const
По-прежнему важно. Мы можем доказать это с помощью следующей программы, которая не будет компилироваться:
int main(){
const int ia[3] = {0, 1, 2};
typedef int (*cpa)[3];
cpa g = 0;
typedef int (amp;cra)[3];
cra h = ia;
return 0;
}
Для меня с gdb 7.7 результат соответствует ожидаемому:
(gdb) ptype g
type = const int (*)[3]
(gdb) ptype h
type = const int (amp;)[3]
Чтобы переписать эти typedef
s с using
:
using cpa = const int (*)[3];
using cra = const int (amp;)[3];
Вы можете видеть, что за шаблоном просто using identifier =
следует объявление с отсутствующим идентификатором.
Комментарии:
1. Джозеф, не мог бы ты поделиться, включал ли ты какие-либо опции «print pretty»?
2. @user3701346 Если это означает выполнение
enable pretty-printer
заранее, похоже, это не имеет никакого эффекта.3. подождите.
cpa
это имя типа, как вы можете его напечатать? Я только сделалptype g
иptype h
, которые являются переменными.4. @user3701346 Тот же результат.
5. @user3701346 Я предполагаю, что это была ошибка, которая была исправлена между версиями 7.4 и 7.7
Ответ №2:
Вы слишком доверяете gdb. По причинам, которые я не понимаю, ‘const’ опускается. Вам следует проверять постоянство типов другими способами. Один из способов — попытаться присвоить g[0]. Это выдаст ошибку, которая включает в себя сообщение, подобное этому:
error: incompatible types in assignment of ‘int’ to ‘const int [3]’
Это сразу говорит вам о том, что вашей проблемы не существует.
Вы также можете использовать typeid, чтобы получить тип из компилятора и распечатать его. На VC это выполняет работу тривиально. С помощью gcc вам нужно изменить формат результатов, чтобы сделать их удобочитаемыми. Приведенный ниже код выводит тип g и g2, с константой и без нее.
#include <stdio.h>
#include <typeinfo>
#ifdef __GNUG__
#define DEMANGLE
#endif
#ifdef DEMANGLE
#include <cxxabi.h>
#endif
template <typename T>
const char* TypeName(const Tamp; type)
{
#ifdef DEMANGLE
int status = 0;
// Convert the cryptic gcc name decorations to something
// human readable.
return abi::__cxa_demangle(typeid(type).name(), NULL, NULL, amp;status);
#else
return typeid(type).name();
#endif
}
int main(){
int ia[3] = {0, 1, 2};
typedef const int (*cpa)[3];
cpa g = 0; //(gdb) ptype g: type = int (*)[3]
typedef int (*cpa2)[3];
cpa2 g2 = 0; //(gdb) ptype g: type = int (*)[3]
typedef const int (amp;cra)[3];
cra h = ia; //(gdb) ptype h: type = int (amp;)[3]
printf("Type of 'g' is '%s'n", TypeName(g));
printf("Type of 'g2' is '%s'n", TypeName(g2));
//g[0] = 2; This fails to compile, thus proving that cpa/g have the correct type.
return 0;
}
Комментарии:
1. Спасибо за совет. Теперь у меня есть альтернативный способ проверки типа.