2009-07-15 3 views
2

Если у меня есть int x[10] и int *y, как я могу рассказать о различии между ними?массив целых чисел против указателя на целое число в C++

У меня есть две идеи:

  1. SizeOf() отличается.

  2. & x имеет другой тип --- int (*p)[10] = &x работ, но не int **q = &x.

Любые другие?

В некотором шаблоне библиотеки библиотеки мне нужно определить, является ли указатель «реальным» указателем или дегенерирован из массива. Я не могу смотреть на исходный код, поскольку пользователь библиотеки не существует, пока не напишу библиотеку. ... Я могу обойти это, переписав код, так что теперь это всего лишь теоретическое упражнение.

+7

Что именно вы подразумеваете под словом «рассказать разницу»? Почему «рассмотрение объявления типа» не будет полным решением? Вам нужно иметь какое-то другое поведение для частичной специализации шаблона или подобного? –

+0

Будут случаи, когда sizeof равен. В любом случае, легкий способ увидеть разницу - посмотреть исходный код. Какова реальная проблема, которую вы пытаетесь решить? – nos

ответ

2

Идея sizeof не очень хороша, потому что если массив имеет один элемент, а тип элемента имеет тот же размер, что и указатель, то он будет такого же размера, как размер указателя ,

Подход соответствия типов выглядит более перспективным и, предположительно, может использоваться для выбора специализированной специализации (если это то, что вы делаете).

5

Нет общего метода - вы либо уже знаете тип, потому что вы только что объявили объект, либо тип будет разлагаться на указатель и потерян. Пожалуйста, объясните, какую проблему вы пытаетесь решить, дифференцируя их.

+0

То же :-) –

+2

Я подозреваю, что он либо написал код шаблона, который различает массив или указатель, либо пытается написать функцию count/macro count, которая не подходит для указателей. – MSN

0

int x [10] будет всегда размещен в стеке на месте, если бы он был вызван. Значение x никогда не может быть изменено.

int * y просто объявляет указатель на память, значение указателя может быть изменено в любое время без каких-либо ограничений.

int * y может иметь любое произвольное значение. Смысл, он может указывать на выделенную стекю память памяти памяти, выделенную стеклом. Технически это также может указывать на недопустимую память, но это не имеет никакого смысла.

int x [10] guarntee, вы всегда указываете на действительную память, и вам не нужно беспокоиться об освобождении памяти.

при использовании int * y, вам нужно беспокоиться о памяти, на которую она указывает.

Также имейте в виду, что у вашей порграммы есть динамически распределенная память, тем больше она будет подвержена ошибкам, утечкам, проблемам с выполнением, ассимиляции распределения \ освобождения и многих других проблем.

0

Это разные типы.

Как вы скажете разницу между int32 и uint32, или uint32 и char [4]?

Правильный способ думать о том, что единственный способ, которым они похожи, заключается в том, что в определенных контекстах (включая индексирование массива!) Массив продвигается в указатель.

2

Предполагая, что вы не пытаетесь сделать это для типа, объявленного в области видимости функции:

struct yes { char pad; }; 
struct no { yes pad[2]; }; 

template <typename T, size_t N> yes is_array_test(T (&arr)[N]); 
no is_array_test(...); 

#define IS_ARRAY(x) (sizeof(is_array_test(x))==sizeof(yes)) 
+0

Я бы предпочел SFINAE (= специализированный шаблон) для макроса, но, тем не менее, этот общий метод - путь. –

+0

Ну, да. Это, однако, доступно как постоянная времени компиляции. – MSN

+0

MSN: так специализированный шаблон. ;-) Только синтаксис вызова немного меняется, в идеале он будет выглядеть как тип типа Boost: 'is_array :: value'. –

0

Я просто попытался эквивалент в г ++ 4.5 C++ 0x режим для символьных массивов и не позвольте мне как определить

template <typename T>void moresilly(const T v[],const char *description) 

и

template <typename T>void moresilly(const T *v,const char *description) 

он утверждает, что оба эти же типа.

Я имел функцию:

template <typename T>void silly(const T & v,const char *description) 
{ 
    cout<<"size of "<<description<<" is "<< sizeof(T)<<endl; 
    moresilly(v,description); 
} 

Это правильно получает размер массива, если он принят и указатель, если он принят, но я не могу использовать moresilly различать указатель и массив, так что я могу 't указать массив из 4 символов из указателя на n символов.

Возможно, что у него есть шаблоны на T [1], T [2], T [3] и т. Д., Но уже есть сообщение о том, что разные компиляторы обрабатывают этот (или какой-то подобный случай) по-разному и что gnu предпочитает совпадение указателей в C++ 11.

... добавлено позже: После некоторого эксперимента я нашел то, что работает в г ++ 4,5

template <typename T,size_t L>void moresilly(const T (&v)[L],const char *description) 
{ 
    cout<<description<<" is an array"<<endl; 
} 
template <typename T>void moresilly(const T *v,const char *description) 
{ 
    cout<<description<<" is a pointer"<<endl; 
} 
template <typename T>void moresilly(const T v,const char *description) 
{ 
    cout<<description<<" is a raw value"<<endl; 
} 
template <typename T>void silly(const T & v,const char *description) 
{ 
    cout<<"size of "<<description<<" is "<< sizeof(T)<<endl; 
    moresilly(v,description); 
} 

со следующими работает правильно

silly("12345","immediate string of 5 characters plus zero"); 
    silly((const char *)"12345","immediate constant char pointer of 5 characters plus zero"); 
    char testarray[]="abcdef"; 
    silly(testarray,"char array of 6 characters plus zero"); 
const char testarray2[]="abcdefg"; 
silly(testarray2,"const char array of 7 characters plus zero"); 

Обратите внимание, что если первая функция определяется с "const T v [L]" вместо "const T (& v) [L]" он не работает, никогда не согласуется ни с чем.

Итак, я решил вашу проблему, но не ожидаю, что это сработает в других версиях компилятора, включая будущие. Вот почему я ненавижу C++. Так или иначе, определение языка настолько непонятно, что компиляторы полны неустойчивых краевых случаев.

Это полезный трюк, хотя я могу его использовать.

Смежные вопросы