2009-07-15 46 views
2

如果我有int x[10]int *y,我怎么能告诉两者之间的区别?整数数组与指针指向整数在c + +

我有两个想法:

  1. 的sizeof()是不同的。

  2. & x有不同的类型--- int (*p)[10] = &x作品,但不是int **q = &x

其他?

在一些模板库代码中,我需要确定指针是“真实”指针还是从数组退化。我无法查看源代码,因为在我编写库之前库用户不存在。 ...我可以通过重写代码来解决这个问题,所以现在这只是一个理论练习。

+7

你是什么意思的'告诉差异'?为什么不检查类型声明是一个完整的解决方案?你是否需要为模板部分专业化或类似模式有不同的行为? – 2009-07-15 18:45:03

+0

会有大小相等的情况。 无论如何,easies看到区别的方法是看源代码。你试图解决什么是真正的问题? – nos 2009-07-15 18:49:55

回答

2

sizeof想法不是很好,因为如果数组恰好有一个元素,并且元素类型与指针的大小相同,那么它的大小与指针的大小相同。

类型匹配的方法看起来更有希望,并可能被用来选择模板专业化(如果这就是你所要做的)。

5

没有通用的方法 - 您已经知道该类型是因为您刚刚声明了该对象,或者该类型已经衰减为指针并且已经丢失。请通过区分它们来解释您尝试解决的问题。

+0

同上:-) – 2009-07-15 19:23:46

+2

我怀疑他要么编写一些区分数组或指针的模板代码,要么尝试编写指针失败的数组计数函数/宏。 – MSN 2009-07-16 17:18:38

0

int x [10]将被全部分配在堆栈中被调用的地方。 x值永远不能改变。

int * y只需声明一个指向内存的指针,指针值可以在任何时间更改而没有任何限制。

int * y可以有任意的值。意思是,它可以指向栈分配的Memory或堆分配的内存。技术上它也可以指向无效的记忆,但这没有任何意义。

int x [10] guarntee你总是指向一个有效的内存,你不必担心内存释放。

当使用int * y时,您不得不担心它指向的内存。

另外请记住,您的porgram动态分配内存的次数越多,它将暴露于错误,泄漏,性能问题,分配\分配assimetry和许多其他类型的问题。

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(=专门的模板)宏,但不过,这种一般方法是要走的路。 – 2009-07-16 16:45:28

+0

嗯,是的。然而,这是可用的编译时间常量。 – MSN 2009-07-16 17:17:59

+0

MSN:也是专门的模板。 ;-)只有调用语法略有变化,理想情况下它看起来像一个Boost类型特征:'is_array :: value'。 – 2009-07-16 20:48:15

0

我只是试图以g ++ 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指针和阵列之间进行区分它正确地得到一个阵列的大小,所以可不会告诉从指针到n个字符的4个字符的数组。

它可能工作,有点模板T [1],T [2],T [3]等,但已有一篇文章说不同的编译器处理该(或某些类似的情况)不同和gnu更喜欢C++ 11中的指针匹配。

...后来补充: 经过一些实验,我发现的东西,用g ++ 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++的原因。不知何故,该语言的定义是如此不清楚,编译器充满了不稳定的边缘情况。

虽然这是一个很有用的技巧,但我可以使用它。